init new empty branch feature.
diff --git a/admin/admin.go b/admin/admin.go
deleted file mode 100644
index 06908f4..0000000
--- a/admin/admin.go
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package admin
-
-import (
-	"context"
-	"fmt"
-	"sync"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type Admin interface {
-	CreateTopic(ctx context.Context, opts ...OptionCreate) error
-	DeleteTopic(ctx context.Context, opts ...OptionDelete) error
-	//TODO
-	//TopicList(ctx context.Context, mq *primitive.MessageQueue) (*remote.RemotingCommand, error)
-	//GetBrokerClusterInfo(ctx context.Context) (*remote.RemotingCommand, error)
-	Close() error
-}
-
-// TODO: move outdated context to ctx
-type adminOptions struct {
-	internal.ClientOptions
-}
-
-type AdminOption func(options *adminOptions)
-
-func defaultAdminOptions() *adminOptions {
-	opts := &adminOptions{
-		ClientOptions: internal.DefaultClientOptions(),
-	}
-	opts.GroupName = "TOOLS_ADMIN"
-	opts.InstanceName = time.Now().String()
-	return opts
-}
-
-// WithResolver nameserver resolver to fetch nameserver addr
-func WithResolver(resolver primitive.NsResolver) AdminOption {
-	return func(options *adminOptions) {
-		options.Resolver = resolver
-	}
-}
-
-type admin struct {
-	cli internal.RMQClient
-
-	opts *adminOptions
-
-	closeOnce sync.Once
-}
-
-// NewAdmin initialize admin
-func NewAdmin(opts ...AdminOption) (Admin, error) {
-	defaultOpts := defaultAdminOptions()
-	for _, opt := range opts {
-		opt(defaultOpts)
-	}
-	namesrv, err := internal.NewNamesrv(defaultOpts.Resolver)
-	defaultOpts.Namesrv = namesrv
-	if err != nil {
-		return nil, err
-	}
-
-	cli := internal.GetOrNewRocketMQClient(defaultOpts.ClientOptions, nil)
-	if cli == nil {
-		return nil, fmt.Errorf("GetOrNewRocketMQClient faild")
-	}
-	defaultOpts.Namesrv = cli.GetNameSrv()
-	//log.Printf("Client: %#v", namesrv.srvs)
-	return &admin{
-		cli:  cli,
-		opts: defaultOpts,
-	}, nil
-}
-
-// CreateTopic create topic.
-// TODO: another implementation like sarama, without brokerAddr as input
-func (a *admin) CreateTopic(ctx context.Context, opts ...OptionCreate) error {
-	cfg := defaultTopicConfigCreate()
-	for _, apply := range opts {
-		apply(&cfg)
-	}
-
-	request := &internal.CreateTopicRequestHeader{
-		Topic:           cfg.Topic,
-		DefaultTopic:    cfg.DefaultTopic,
-		ReadQueueNums:   cfg.ReadQueueNums,
-		WriteQueueNums:  cfg.WriteQueueNums,
-		Perm:            cfg.Perm,
-		TopicFilterType: cfg.TopicFilterType,
-		TopicSysFlag:    cfg.TopicSysFlag,
-		Order:           cfg.Order,
-	}
-
-	cmd := remote.NewRemotingCommand(internal.ReqCreateTopic, request, nil)
-	_, err := a.cli.InvokeSync(ctx, cfg.BrokerAddr, cmd, 5*time.Second)
-	if err != nil {
-		rlog.Error("create topic error", map[string]interface{}{
-			rlog.LogKeyTopic:         cfg.Topic,
-			rlog.LogKeyBroker:        cfg.BrokerAddr,
-			rlog.LogKeyUnderlayError: err,
-		})
-	} else {
-		rlog.Info("create topic success", map[string]interface{}{
-			rlog.LogKeyTopic:  cfg.Topic,
-			rlog.LogKeyBroker: cfg.BrokerAddr,
-		})
-	}
-	return err
-}
-
-// DeleteTopicInBroker delete topic in broker.
-func (a *admin) deleteTopicInBroker(ctx context.Context, topic string, brokerAddr string) (*remote.RemotingCommand, error) {
-	request := &internal.DeleteTopicRequestHeader{
-		Topic: topic,
-	}
-
-	cmd := remote.NewRemotingCommand(internal.ReqDeleteTopicInBroker, request, nil)
-	return a.cli.InvokeSync(ctx, brokerAddr, cmd, 5*time.Second)
-}
-
-// DeleteTopicInNameServer delete topic in nameserver.
-func (a *admin) deleteTopicInNameServer(ctx context.Context, topic string, nameSrvAddr string) (*remote.RemotingCommand, error) {
-	request := &internal.DeleteTopicRequestHeader{
-		Topic: topic,
-	}
-
-	cmd := remote.NewRemotingCommand(internal.ReqDeleteTopicInNameSrv, request, nil)
-	return a.cli.InvokeSync(ctx, nameSrvAddr, cmd, 5*time.Second)
-}
-
-// DeleteTopic delete topic in both broker and nameserver.
-func (a *admin) DeleteTopic(ctx context.Context, opts ...OptionDelete) error {
-	cfg := defaultTopicConfigDelete()
-	for _, apply := range opts {
-		apply(&cfg)
-	}
-	//delete topic in broker
-	if cfg.BrokerAddr == "" {
-		a.cli.GetNameSrv().UpdateTopicRouteInfo(cfg.Topic)
-		cfg.BrokerAddr = a.cli.GetNameSrv().FindBrokerAddrByTopic(cfg.Topic)
-	}
-
-	if _, err := a.deleteTopicInBroker(ctx, cfg.Topic, cfg.BrokerAddr); err != nil {
-		rlog.Error("delete topic in broker error", map[string]interface{}{
-			rlog.LogKeyTopic:         cfg.Topic,
-			rlog.LogKeyBroker:        cfg.BrokerAddr,
-			rlog.LogKeyUnderlayError: err,
-		})
-		return err
-	}
-
-	//delete topic in nameserver
-	if len(cfg.NameSrvAddr) == 0 {
-		a.cli.GetNameSrv().UpdateTopicRouteInfo(cfg.Topic)
-		cfg.NameSrvAddr = a.cli.GetNameSrv().AddrList()
-		_, _, err := a.cli.GetNameSrv().UpdateTopicRouteInfo(cfg.Topic)
-		if err != nil {
-			rlog.Error("delete topic in nameserver error", map[string]interface{}{
-				rlog.LogKeyTopic:         cfg.Topic,
-				rlog.LogKeyUnderlayError: err,
-			})
-		}
-		cfg.NameSrvAddr = a.cli.GetNameSrv().AddrList()
-	}
-
-	for _, nameSrvAddr := range cfg.NameSrvAddr {
-		if _, err := a.deleteTopicInNameServer(ctx, cfg.Topic, nameSrvAddr); err != nil {
-			rlog.Error("delete topic in nameserver error", map[string]interface{}{
-				"nameServer":             nameSrvAddr,
-				rlog.LogKeyTopic:         cfg.Topic,
-				rlog.LogKeyUnderlayError: err,
-			})
-			return err
-		}
-	}
-	rlog.Info("delete topic success", map[string]interface{}{
-		"nameServer":      cfg.NameSrvAddr,
-		rlog.LogKeyTopic:  cfg.Topic,
-		rlog.LogKeyBroker: cfg.BrokerAddr,
-	})
-	return nil
-}
-
-func (a *admin) Close() error {
-	a.closeOnce.Do(func() {
-		a.cli.Shutdown()
-	})
-	return nil
-}
diff --git a/admin/option.go b/admin/option.go
deleted file mode 100644
index d5a648e..0000000
--- a/admin/option.go
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package admin
-
-func defaultTopicConfigCreate() TopicConfigCreate {
-	opts := TopicConfigCreate{
-		DefaultTopic:    "defaultTopic",
-		ReadQueueNums:   8,
-		WriteQueueNums:  8,
-		Perm:            6,
-		TopicFilterType: "SINGLE_TAG",
-		TopicSysFlag:    0,
-		Order:           false,
-	}
-	return opts
-}
-
-type TopicConfigCreate struct {
-	Topic           string
-	BrokerAddr      string
-	DefaultTopic    string
-	ReadQueueNums   int
-	WriteQueueNums  int
-	Perm            int
-	TopicFilterType string
-	TopicSysFlag    int
-	Order           bool
-}
-
-type OptionCreate func(*TopicConfigCreate)
-
-func WithTopicCreate(Topic string) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.Topic = Topic
-	}
-}
-
-func WithBrokerAddrCreate(BrokerAddr string) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.BrokerAddr = BrokerAddr
-	}
-}
-
-func WithReadQueueNums(ReadQueueNums int) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.ReadQueueNums = ReadQueueNums
-	}
-}
-
-func WithWriteQueueNums(WriteQueueNums int) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.WriteQueueNums = WriteQueueNums
-	}
-}
-
-func WithPerm(Perm int) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.Perm = Perm
-	}
-}
-
-func WithTopicFilterType(TopicFilterType string) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.TopicFilterType = TopicFilterType
-	}
-}
-
-func WithTopicSysFlag(TopicSysFlag int) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.TopicSysFlag = TopicSysFlag
-	}
-}
-
-func WithOrder(Order bool) OptionCreate {
-	return func(opts *TopicConfigCreate) {
-		opts.Order = Order
-	}
-}
-
-func defaultTopicConfigDelete() TopicConfigDelete {
-	opts := TopicConfigDelete{}
-	return opts
-}
-
-type TopicConfigDelete struct {
-	Topic       string
-	ClusterName string
-	NameSrvAddr []string
-	BrokerAddr  string
-}
-
-type OptionDelete func(*TopicConfigDelete)
-
-func WithTopicDelete(Topic string) OptionDelete {
-	return func(opts *TopicConfigDelete) {
-		opts.Topic = Topic
-	}
-}
-
-func WithBrokerAddrDelete(BrokerAddr string) OptionDelete {
-	return func(opts *TopicConfigDelete) {
-		opts.BrokerAddr = BrokerAddr
-	}
-}
-
-func WithClusterName(ClusterName string) OptionDelete {
-	return func(opts *TopicConfigDelete) {
-		opts.ClusterName = ClusterName
-	}
-}
-
-func WithNameSrvAddr(NameSrvAddr []string) OptionDelete {
-	return func(opts *TopicConfigDelete) {
-		opts.NameSrvAddr = NameSrvAddr
-	}
-}
diff --git a/api.go b/api.go
deleted file mode 100644
index 31f58d5..0000000
--- a/api.go
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package rocketmq
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-type Producer interface {
-	Start() error
-	Shutdown() error
-	SendSync(ctx context.Context, mq ...*primitive.Message) (*primitive.SendResult, error)
-	SendAsync(ctx context.Context, mq func(ctx context.Context, result *primitive.SendResult, err error),
-		msg ...*primitive.Message) error
-	SendOneWay(ctx context.Context, mq ...*primitive.Message) error
-}
-
-func NewProducer(opts ...producer.Option) (Producer, error) {
-	return producer.NewDefaultProducer(opts...)
-}
-
-type TransactionProducer interface {
-	Start() error
-	Shutdown() error
-	SendMessageInTransaction(ctx context.Context, mq *primitive.Message) (*primitive.TransactionSendResult, error)
-}
-
-func NewTransactionProducer(listener primitive.TransactionListener, opts ...producer.Option) (TransactionProducer, error) {
-	return producer.NewTransactionProducer(listener, opts...)
-}
-
-type PushConsumer interface {
-	// Start the PullConsumer for consuming message
-	Start() error
-
-	// Shutdown the PullConsumer, all offset of MessageQueue will be sync to broker before process exit
-	Shutdown() error
-	// Subscribe a topic for consuming
-	Subscribe(topic string, selector consumer.MessageSelector,
-		f func(context.Context, ...*primitive.MessageExt) (consumer.ConsumeResult, error)) error
-
-	// Unsubscribe a topic
-	Unsubscribe(topic string) error
-}
-
-func NewPushConsumer(opts ...consumer.Option) (PushConsumer, error) {
-	return consumer.NewPushConsumer(opts...)
-}
-
-type PullConsumer interface {
-	// Start the PullConsumer for consuming message
-	Start() error
-
-	// Shutdown the PullConsumer, all offset of MessageQueue will be commit to broker before process exit
-	Shutdown() error
-
-	// Subscribe a topic for consuming
-	Subscribe(topic string, selector consumer.MessageSelector) error
-
-	// Unsubscribe a topic
-	Unsubscribe(topic string) error
-
-	// MessageQueues get MessageQueue list about for a given topic. This method will issue a remote call to the server
-	// if it does not already have any MessageQueue about the given topic.
-	MessageQueues(topic string) []primitive.MessageQueue
-
-	// Pull message for the topic specified. It is an error to not have subscribed to any topics before pull for message
-	//
-	// Specified numbers of messages is returned if message greater that numbers, and the offset will auto forward.
-	// It means that if you meeting messages consuming failed, you should process failed messages by yourself.
-	Pull(ctx context.Context, topic string, numbers int) (*primitive.PullResult, error)
-
-	// Pull message for the topic specified from a specified MessageQueue and offset. It is an error to not have
-	// subscribed to any topics before pull for message. the method will not affect the offset recorded
-	//
-	// Specified numbers of messages is returned.
-	PullFrom(ctx context.Context, mq primitive.MessageQueue, offset int64, numbers int) (*primitive.PullResult, error)
-
-	// Lookup offset for the given message queue by timestamp. The returned offset for the message queue is the
-	// earliest offset whose timestamp is greater than or equal to the given timestamp in the corresponding message
-	// queue.
-	//
-	// Timestamp must be millisecond level, if you want to lookup the earliest offset of the mq, you could set the
-	// timestamp 0, and if you want to the latest offset the mq, you could set the timestamp math.MaxInt64.
-	Lookup(ctx context.Context, mq primitive.MessageQueue, timestamp int64) (int64, error)
-
-	// Commit the offset of specified mqs to broker, if auto-commit is disable, you must commit the offset manually.
-	Commit(ctx context.Context, mqs ...primitive.MessageQueue) (int64, error)
-
-	// CommittedOffset return the offset of specified Message
-	CommittedOffset(mq primitive.MessageQueue) (int64, error)
-
-	// Seek set offset of the mq, if you wanna re-consuming your message form one position, the method may help you.
-	// if you want re-consuming from one time, you cloud Lookup() then seek it.
-	Seek(mq primitive.MessageQueue, offset int64) error
-
-	// Pause consuming for specified MessageQueues, after pause, client will not fetch any message from the specified
-	// message queues
-	//
-	// Note that this method does not affect message queue subscription. In particular, it does not cause a group
-	// rebalance.
-	//
-	// if a MessageQueue belong a topic that has not been subscribed, an error will be returned
-	//Pause(mqs ...primitive.MessageQueue) error
-
-	// Resume specified message queues which have been paused with Pause, if a MessageQueue that not paused,
-	// it will be ignored. if not subscribed, an error will be returned
-	//Resume(mqs ...primitive.MessageQueue) error
-}
-
-// The PullConsumer has not implemented completely, if you want have an experience of PullConsumer, you could use
-// consumer.NewPullConsumer(...), but it may changed in the future.
-//
-// The PullConsumer will be supported in next release
-func NewPullConsumer(opts ...consumer.Option) (PullConsumer, error) {
-	return nil, errors.ErrPullConsumer
-}
diff --git a/benchmark/consumer.go b/benchmark/consumer.go
deleted file mode 100644
index 907a1e7..0000000
--- a/benchmark/consumer.go
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package main
-
-import (
-	"context"
-	"flag"
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"os"
-	"os/signal"
-	"sync"
-	"sync/atomic"
-	"syscall"
-	"time"
-)
-
-type statiBenchmarkConsumerSnapshot struct {
-	receiveMessageTotal   int64
-	born2ConsumerTotalRT  int64
-	store2ConsumerTotalRT int64
-	born2ConsumerMaxRT    int64
-	store2ConsumerMaxRT   int64
-	createdAt             time.Time
-	next                  *statiBenchmarkConsumerSnapshot
-}
-
-type consumeSnapshots struct {
-	sync.RWMutex
-	head, tail, cur *statiBenchmarkConsumerSnapshot
-	len             int
-}
-
-func (s *consumeSnapshots) takeSnapshot() {
-	b := s.cur
-	sn := new(statiBenchmarkConsumerSnapshot)
-	sn.receiveMessageTotal = atomic.LoadInt64(&b.receiveMessageTotal)
-	sn.born2ConsumerMaxRT = atomic.LoadInt64(&b.born2ConsumerMaxRT)
-	sn.born2ConsumerTotalRT = atomic.LoadInt64(&b.born2ConsumerTotalRT)
-	sn.store2ConsumerMaxRT = atomic.LoadInt64(&b.store2ConsumerMaxRT)
-	sn.store2ConsumerTotalRT = atomic.LoadInt64(&b.store2ConsumerTotalRT)
-	sn.createdAt = time.Now()
-
-	s.Lock()
-	if s.tail != nil {
-		s.tail.next = sn
-	}
-	s.tail = sn
-	if s.head == nil {
-		s.head = s.tail
-	}
-
-	s.len++
-	if s.len > 10 {
-		s.head = s.head.next
-		s.len--
-	}
-	s.Unlock()
-}
-
-func (s *consumeSnapshots) printStati() {
-	s.RLock()
-	if s.len < 10 {
-		s.RUnlock()
-		return
-	}
-
-	f, l := s.head, s.tail
-	respSucCount := float64(l.receiveMessageTotal - f.receiveMessageTotal)
-	consumeTps := respSucCount / l.createdAt.Sub(f.createdAt).Seconds()
-	avgB2CRT := float64(l.born2ConsumerTotalRT-f.born2ConsumerTotalRT) / respSucCount
-	avgS2CRT := float64(l.store2ConsumerTotalRT-f.store2ConsumerTotalRT) / respSucCount
-	s.RUnlock()
-
-	rlog.Info("Benchmark Consumer Snapshot", map[string]interface{}{
-		"consumeTPS": int64(consumeTps),
-		"average(B2C)RT": avgB2CRT,
-		"average(S2C)RT": avgS2CRT,
-		"max(B2C)RT": l.born2ConsumerMaxRT,
-		"max(S2C)RT": l.store2ConsumerMaxRT,
-	})
-}
-
-type consumerBenchmark struct {
-	topic          string
-	groupPrefix    string
-	nameSrv        string
-	isPrefixEnable bool
-	filterType     string
-	expression     string
-	testMinutes    int
-	instanceCount  int
-
-	flags *flag.FlagSet
-
-	groupID string
-}
-
-func init() {
-	c := &consumerBenchmark{}
-	flags := flag.NewFlagSet("consumer", flag.ExitOnError)
-	c.flags = flags
-
-	flags.StringVar(&c.topic, "t", "BenchmarkTest", "topic")
-	flags.StringVar(&c.groupPrefix, "g", "benchmark_consumer", "group prefix")
-	flags.StringVar(&c.nameSrv, "n", "", "namesrv address list, separated by comma")
-	flags.BoolVar(&c.isPrefixEnable, "p", true, "group prefix is enable")
-	flags.StringVar(&c.filterType, "f", "", "filter type,options:TAG|SQL92, or empty")
-	flags.StringVar(&c.expression, "e", "*", "expression")
-	flags.IntVar(&c.testMinutes, "m", 10, "test minutes")
-	flags.IntVar(&c.instanceCount, "i", 1, "instance count")
-
-	registerCommand("consumer", c)
-}
-
-func (bc *consumerBenchmark) consumeMsg(stati *statiBenchmarkConsumerSnapshot, exit chan struct{}) {
-	c, err := rocketmq.NewPushConsumer(
-		consumer.WithGroupName(bc.groupID),
-		consumer.WithNameServer([]string{bc.nameSrv}),
-	)
-	if err != nil {
-		panic("new push consumer error:" + err.Error())
-	}
-
-	selector := consumer.MessageSelector{}
-	err = c.Subscribe(bc.topic, selector, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		for _, msg := range msgs {
-			atomic.AddInt64(&stati.receiveMessageTotal, 1)
-			now := time.Now().UnixNano() / int64(time.Millisecond)
-			b2cRT := now - msg.BornTimestamp
-			atomic.AddInt64(&stati.born2ConsumerTotalRT, b2cRT)
-			s2cRT := now - msg.StoreTimestamp
-			atomic.AddInt64(&stati.store2ConsumerTotalRT, s2cRT)
-
-			for {
-				old := atomic.LoadInt64(&stati.born2ConsumerMaxRT)
-				if old >= b2cRT || atomic.CompareAndSwapInt64(&stati.born2ConsumerMaxRT, old, b2cRT) {
-					break
-				}
-			}
-
-			for {
-				old := atomic.LoadInt64(&stati.store2ConsumerMaxRT)
-				if old >= s2cRT || atomic.CompareAndSwapInt64(&stati.store2ConsumerMaxRT, old, s2cRT) {
-					break
-				}
-			}
-		}
-		return consumer.ConsumeSuccess, nil
-	})
-
-	rlog.Info("Test Start", nil)
-	c.Start()
-	select {
-	case <-exit:
-		c.Shutdown()
-		return
-	}
-}
-
-func (bc *consumerBenchmark) run(args []string) {
-	bc.flags.Parse(args)
-	if bc.topic == "" {
-		rlog.Error("Empty Topic", nil)
-		bc.usage()
-		return
-	}
-
-	if bc.groupPrefix == "" {
-		rlog.Error("Empty Group Prefix", nil)
-		bc.usage()
-		return
-	}
-
-	if bc.nameSrv == "" {
-		rlog.Error("Empty Nameserver", nil)
-		bc.usage()
-		return
-	}
-
-	if bc.testMinutes <= 0 {
-		rlog.Error("Test Time Must Be Positive Integer", nil)
-		bc.usage()
-		return
-	}
-
-	if bc.instanceCount <= 0 {
-		rlog.Error("Thread Count Must Be Positive Integer", nil)
-		bc.usage()
-		return
-	}
-
-	bc.groupID = bc.groupPrefix
-	if bc.isPrefixEnable {
-		bc.groupID += fmt.Sprintf("_%d", time.Now().UnixNano()/int64(time.Millisecond)%100)
-	}
-
-	stati := statiBenchmarkConsumerSnapshot{}
-	snapshots := consumeSnapshots{cur: &stati}
-	exitChan := make(chan struct{})
-
-	wg := sync.WaitGroup{}
-
-	wg.Add(1)
-	go func() {
-		bc.consumeMsg(&stati, exitChan)
-		wg.Done()
-	}()
-
-	// snapshot
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		ticker := time.NewTicker(time.Second)
-		for {
-			select {
-			case <-ticker.C:
-				snapshots.takeSnapshot()
-			case <-exitChan:
-				ticker.Stop()
-				return
-			}
-		}
-	}()
-
-	// print statistic
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		ticker := time.NewTicker(time.Second * 10)
-		for {
-			select {
-			case <-ticker.C:
-				snapshots.printStati()
-			case <-exitChan:
-				ticker.Stop()
-				return
-			}
-		}
-	}()
-
-	signalChan := make(chan os.Signal, 1)
-	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
-	select {
-	case <-time.Tick(time.Minute * time.Duration(bc.testMinutes)):
-	case <-signalChan:
-	}
-
-	close(exitChan)
-	wg.Wait()
-	snapshots.takeSnapshot()
-	snapshots.printStati()
-	rlog.Info("Test Done", nil)
-}
-
-func (bc *consumerBenchmark) usage() {
-	bc.flags.Usage()
-}
diff --git a/benchmark/main.go b/benchmark/main.go
deleted file mode 100644
index 79eca8f..0000000
--- a/benchmark/main.go
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package main
-
-import (
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"os"
-)
-
-type command interface {
-	usage()
-	run(args []string)
-}
-
-var (
-	cmds = map[string]command{}
-)
-
-func registerCommand(name string, cmd command) {
-	if cmd == nil {
-		panic("empty command")
-	}
-
-	_, ok := cmds[name]
-	if ok {
-		panic(fmt.Sprintf("%s command existed", name))
-	}
-
-	cmds[name] = cmd
-}
-
-func usage() {
-	rlog.Info("Command", map[string]interface{}{
-		"name": os.Args[0],
-	})
-	for _, cmd := range cmds {
-		cmd.usage()
-	}
-}
-
-// go run *.go [command name] [command args]
-func main() {
-	if len(os.Args) < 2 {
-		rlog.Error("Lack Command Name", nil)
-		usage()
-		return
-	}
-
-	name := os.Args[1]
-	cmd, ok := cmds[name]
-	if !ok {
-		rlog.Error("Command Isn't Supported", map[string]interface{}{
-			"command": name,
-		})
-		usage()
-		return
-	}
-
-	cmd.run(os.Args[2:])
-}
diff --git a/benchmark/message.go b/benchmark/message.go
deleted file mode 100644
index d5690fe..0000000
--- a/benchmark/message.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package main
-
-import "strings"
-
-var (
-	longText    = ""
-	longTextLen = 0
-)
-
-func init() {
-	longText = strings.Repeat("0123456789", 100)
-	longTextLen = len(longText)
-}
-
-func buildMsg(size int) string {
-	return longText[:size]
-}
diff --git a/benchmark/producer.go b/benchmark/producer.go
deleted file mode 100644
index 7516352..0000000
--- a/benchmark/producer.go
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package main
-
-import (
-	"context"
-	"flag"
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"os"
-	"os/signal"
-	"sync"
-	"sync/atomic"
-	"syscall"
-	"time"
-)
-
-type statiBenchmarkProducerSnapshot struct {
-	sendRequestSuccessCount     int64
-	sendRequestFailedCount      int64
-	receiveResponseSuccessCount int64
-	receiveResponseFailedCount  int64
-	sendMessageSuccessTimeTotal int64
-	sendMessageMaxRT            int64
-	createdAt                   time.Time
-	next                        *statiBenchmarkProducerSnapshot
-}
-
-type produceSnapshots struct {
-	sync.RWMutex
-	head, tail, cur *statiBenchmarkProducerSnapshot
-	len             int
-}
-
-func (s *produceSnapshots) takeSnapshot() {
-	b := s.cur
-	sn := new(statiBenchmarkProducerSnapshot)
-	sn.sendRequestSuccessCount = atomic.LoadInt64(&b.sendRequestSuccessCount)
-	sn.sendRequestFailedCount = atomic.LoadInt64(&b.sendRequestFailedCount)
-	sn.receiveResponseSuccessCount = atomic.LoadInt64(&b.receiveResponseSuccessCount)
-	sn.receiveResponseFailedCount = atomic.LoadInt64(&b.receiveResponseFailedCount)
-	sn.sendMessageSuccessTimeTotal = atomic.LoadInt64(&b.sendMessageSuccessTimeTotal)
-	sn.sendMessageMaxRT = atomic.LoadInt64(&b.sendMessageMaxRT)
-	sn.createdAt = time.Now()
-
-	s.Lock()
-	if s.tail != nil {
-		s.tail.next = sn
-	}
-	s.tail = sn
-	if s.head == nil {
-		s.head = s.tail
-	}
-
-	s.len++
-	if s.len > 10 {
-		s.head = s.head.next
-		s.len--
-	}
-	s.Unlock()
-}
-
-func (s *produceSnapshots) printStati() {
-	s.RLock()
-	if s.len < 10 {
-		s.RUnlock()
-		return
-	}
-
-	f, l := s.head, s.tail
-	respSucCount := float64(l.receiveResponseSuccessCount - f.receiveResponseSuccessCount)
-	sendTps := respSucCount / l.createdAt.Sub(f.createdAt).Seconds()
-	avgRT := float64(l.sendMessageSuccessTimeTotal-f.sendMessageSuccessTimeTotal) / respSucCount
-	maxRT := atomic.LoadInt64(&s.cur.sendMessageMaxRT)
-	s.RUnlock()
-
-	rlog.Info("Benchmark Producer Snapshot", map[string]interface{}{
-		"sendTps": int64(sendTps),
-		"maxRt": maxRT,
-		"averageRt": avgRT,
-		"sendFailed": l.sendRequestFailedCount,
-		"responseFailed": l.receiveResponseFailedCount,
-		"total": l.receiveResponseSuccessCount,
-	})
-}
-
-type producerBenchmark struct {
-	topic         string
-	nameSrv       string
-	groupID       string
-	instanceCount int
-	testMinutes   int
-	bodySize      int
-
-	flags *flag.FlagSet
-}
-
-func init() {
-	p := &producerBenchmark{}
-	flags := flag.NewFlagSet("producer", flag.ExitOnError)
-	p.flags = flags
-
-	flags.StringVar(&p.topic, "t", "", "topic name")
-	flags.StringVar(&p.nameSrv, "n", "", "nameserver address")
-	flags.StringVar(&p.groupID, "g", "", "group id")
-	flags.IntVar(&p.instanceCount, "i", 1, "instance count")
-	flags.IntVar(&p.testMinutes, "m", 10, "test minutes")
-	flags.IntVar(&p.bodySize, "s", 32, "body size")
-
-	registerCommand("producer", p)
-}
-
-func (bp *producerBenchmark) produceMsg(stati *statiBenchmarkProducerSnapshot, exit chan struct{}) {
-	p, err := rocketmq.NewProducer(
-		producer.WithNameServer([]string{bp.nameSrv}),
-		producer.WithRetry(2),
-	)
-
-	if err != nil {
-		rlog.Error("New Producer Error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		return
-	}
-
-	err = p.Start()
-
-	defer p.Shutdown()
-
-	topic, tag := bp.topic, "benchmark-producer"
-	msgStr := buildMsg(bp.bodySize)
-
-AGAIN:
-	select {
-	case <-exit:
-		return
-	default:
-	}
-
-	now := time.Now()
-	r, err := p.SendSync(context.Background(), primitive.NewMessage(topic, []byte(msgStr)))
-
-	if err != nil {
-		rlog.Error("Send Message Error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		goto AGAIN
-	}
-
-	if r.Status == primitive.SendOK {
-		atomic.AddInt64(&stati.receiveResponseSuccessCount, 1)
-		atomic.AddInt64(&stati.sendRequestSuccessCount, 1)
-		currentRT := int64(time.Since(now) / time.Millisecond)
-		atomic.AddInt64(&stati.sendMessageSuccessTimeTotal, currentRT)
-		prevRT := atomic.LoadInt64(&stati.sendMessageMaxRT)
-		for currentRT > prevRT {
-			if atomic.CompareAndSwapInt64(&stati.sendMessageMaxRT, prevRT, currentRT) {
-				break
-			}
-			prevRT = atomic.LoadInt64(&stati.sendMessageMaxRT)
-		}
-		goto AGAIN
-	}
-	rlog.Error("Send Message Error", map[string]interface{}{
-		"topic": topic,
-		"tag": tag,
-		rlog.LogKeyUnderlayError: err.Error(),
-	})
-	goto AGAIN
-}
-
-func (bp *producerBenchmark) run(args []string) {
-	bp.flags.Parse(args)
-
-	if bp.topic == "" {
-		rlog.Error("Empty Topic", nil)
-		bp.flags.Usage()
-		return
-	}
-
-	if bp.groupID == "" {
-		rlog.Error("Empty Group Id", nil)
-		bp.flags.Usage()
-		return
-	}
-
-	if bp.nameSrv == "" {
-		rlog.Error("Empty Nameserver", nil)
-		bp.flags.Usage()
-		return
-	}
-	if bp.instanceCount <= 0 {
-		rlog.Error("Instance Count Must Be Positive Integer", nil)
-		bp.flags.Usage()
-		return
-	}
-	if bp.testMinutes <= 0 {
-		rlog.Error("Test Time Must Be Positive Integer", nil)
-		bp.flags.Usage()
-		return
-	}
-	if bp.bodySize <= 0 {
-		rlog.Error("Body Size Must Be Positive Integer", nil)
-		bp.flags.Usage()
-		return
-	}
-
-	stati := statiBenchmarkProducerSnapshot{}
-	snapshots := produceSnapshots{cur: &stati}
-	exitChan := make(chan struct{})
-	wg := sync.WaitGroup{}
-
-	for i := 0; i < bp.instanceCount; i++ {
-		i := i
-		go func() {
-			wg.Add(1)
-			bp.produceMsg(&stati, exitChan)
-			rlog.Info("Producer Done and Exit", map[string]interface{}{
-				"id": i,
-			})
-			wg.Done()
-		}()
-	}
-
-	// snapshot
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		ticker := time.NewTicker(time.Second)
-		for {
-			select {
-			case <-ticker.C:
-				snapshots.takeSnapshot()
-			case <-exitChan:
-				ticker.Stop()
-				return
-			}
-		}
-	}()
-
-	// print statistic
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		ticker := time.NewTicker(time.Second * 10)
-		for {
-			select {
-			case <-ticker.C:
-				snapshots.printStati()
-			case <-exitChan:
-				ticker.Stop()
-				return
-			}
-		}
-	}()
-
-	signalChan := make(chan os.Signal, 1)
-	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
-	select {
-	case <-time.Tick(time.Minute * time.Duration(bp.testMinutes)):
-	case <-signalChan:
-	}
-
-	close(exitChan)
-	wg.Wait()
-	snapshots.takeSnapshot()
-	snapshots.printStati()
-	rlog.Info("Test Done", nil)
-}
-
-func (bp *producerBenchmark) usage() {
-	bp.flags.Usage()
-}
diff --git a/benchmark/stable.go b/benchmark/stable.go
deleted file mode 100644
index 2659bc5..0000000
--- a/benchmark/stable.go
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package main
-
-import (
-	"flag"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"os"
-	"os/signal"
-	"syscall"
-	"time"
-)
-
-type stableTest struct {
-	nameSrv       string
-	topic         string
-	groupID       string
-	opIntervalSec int
-	testMin       int
-
-	op func()
-
-	flags *flag.FlagSet
-}
-
-func (st *stableTest) buildFlags(name string) {
-	flags := flag.NewFlagSet(name, flag.ExitOnError)
-	flags.StringVar(&st.topic, "t", "stable-test", "topic name")
-	flags.StringVar(&st.nameSrv, "n", "", "nameserver address")
-	flags.StringVar(&st.groupID, "g", "stable-test", "group id")
-	flags.IntVar(&st.testMin, "m", 10, "test minutes")
-	flags.IntVar(&st.opIntervalSec, "s", 1, "operation interval[produce/consume]")
-
-	st.flags = flags
-}
-
-func (st *stableTest) checkFlag() error {
-	if st.topic == "" {
-		return errors.ErrEmptyTopic
-	}
-
-	if st.nameSrv == "" {
-		return errors.ErrEmptyNameSrv
-	}
-
-	if st.groupID == "" {
-		return errors.ErrEmptyGroupID
-	}
-
-	if st.testMin <= 0 {
-		return errors.ErrTestMin
-	}
-
-	if st.opIntervalSec <= 0 {
-		return errors.ErrOperationInterval
-	}
-
-	return nil
-}
-
-func (st *stableTest) run() {
-	opTicker := time.NewTicker(time.Duration(st.opIntervalSec) * time.Second)
-	closeChan := time.Tick(time.Duration(st.testMin) * time.Minute)
-
-	signalChan := make(chan os.Signal, 1)
-	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
-	for {
-		select {
-		case <-signalChan:
-			opTicker.Stop()
-			rlog.Info("Test Done", nil)
-			return
-		case <-closeChan:
-			opTicker.Stop()
-			rlog.Info("Test Done", nil)
-			return
-		case <-opTicker.C:
-			st.op()
-		}
-	}
-}
-
-type stableTestProducer struct {
-	*stableTest
-	bodySize int
-
-	//p rocketmq.Producer
-}
-
-func (stp *stableTestProducer) buildFlags(name string) {
-	stp.stableTest.buildFlags(name)
-	stp.flags.IntVar(&stp.bodySize, "b", 32, "body size")
-}
-
-func (stp *stableTestProducer) checkFlag() error {
-	err := stp.stableTest.checkFlag()
-	if err != nil {
-		return err
-	}
-	if stp.bodySize <= 0 {
-		return errors.ErrMessageBody
-	}
-
-	return nil
-}
-
-func (stp *stableTestProducer) usage() {
-	stp.flags.Usage()
-}
-
-func (stp *stableTestProducer) run(args []string) {
-	err := stp.flags.Parse(args)
-	if err != nil {
-		rlog.Info("Parse Args Error", map[string]interface{}{
-			"args": args,
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		stp.usage()
-		return
-	}
-
-	err = stp.checkFlag()
-	if err != nil {
-		rlog.Error("Check Flag Error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		stp.usage()
-		return
-	}
-
-	//p, err := rocketmq.NewProducer(&rocketmq.ProducerConfig{
-	//	ClientConfig: rocketmq.ClientConfig{GroupID: stp.groupID, NameServer: stp.nameSrv},
-	//})
-	//if err != nil {
-	//	fmt.Printf("new consumer error:%s\n", err)
-	//	return
-	//}
-	//
-	//err = p.Start()
-	//if err != nil {
-	//	fmt.Printf("start consumer error:%s\n", err)
-	//	return
-	//}
-	//defer p.Shutdown()
-	//
-	//stp.p = p
-	stp.stableTest.run()
-}
-
-func (stp *stableTestProducer) sendMessage() {
-	//r, err := stp.p.SendMessageSync(&rocketmq.Message{Topic: stp.topic, Body: buildMsg(stp.bodySize)})
-	//if err == nil {
-	//	fmt.Printf("send result:%+v\n", r)
-	//	return
-	//}
-	//fmt.Printf("send message error:%s", err)
-}
-
-type stableTestConsumer struct {
-	*stableTest
-	expression string
-
-	//c       rocketmq.PullConsumer
-	offsets map[int]int64
-}
-
-func (stc *stableTestConsumer) buildFlags(name string) {
-	stc.stableTest.buildFlags(name)
-	stc.flags.StringVar(&stc.expression, "e", "*", "expression")
-}
-
-func (stc *stableTestConsumer) checkFlag() error {
-	err := stc.stableTest.checkFlag()
-	if err != nil {
-		return err
-	}
-
-	if stc.expression == "" {
-		return errors.ErrEmptyExpression
-	}
-	return nil
-}
-
-func (stc *stableTestConsumer) usage() {
-	stc.flags.Usage()
-}
-
-func (stc *stableTestConsumer) run(args []string) {
-	err := stc.flags.Parse(args)
-	if err != nil {
-		rlog.Error("Parse Args Error", map[string]interface{}{
-			"args": args,
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		stc.usage()
-		return
-	}
-
-	err = stc.checkFlag()
-	if err != nil {
-		rlog.Error("Check Flag Error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		stc.usage()
-		return
-	}
-	//
-	//c, err := rocketmq.NewPullConsumer(&rocketmq.PullConsumerConfig{
-	//	ClientConfig: rocketmq.ClientConfig{GroupID: stc.groupID, NameServer: stc.nameSrv},
-	//})
-	//if err != nil {
-	//	fmt.Printf("new pull consumer error:%s\n", err)
-	//	return
-	//}
-	//
-	//err = c.Start()
-	//if err != nil {
-	//	fmt.Printf("start consumer error:%s\n", err)
-	//	return
-	//}
-	//defer c.Shutdown()
-	//
-	//stc.c = c
-	stc.stableTest.run()
-}
-
-func (stc *stableTestConsumer) pullMessage() {
-	//mqs := stc.c.FetchSubscriptionMessageQueues(stc.topic)
-	//
-	//for _, mq := range mqs {
-	//	offset := stc.offsets[mq.ID]
-	//	pr := stc.c.Pull(mq, stc.expression, offset, 32)
-	//fmt.Printf("pull from %s, offset:%d, count:%+v\n", mq.String(), offset, len(pr.Messages))
-	//
-	//switch pr.Status {
-	//case rocketmq.PullNoNewMsg:
-	//	stc.offsets[mq.ID] = 0 // pull from the begin
-	//case rocketmq.PullFound:
-	//	fallthrough
-	//case rocketmq.PullNoMatchedMsg:
-	//	fallthrough
-	//case rocketmq.PullOffsetIllegal:
-	//	stc.offsets[mq.ID] = pr.NextBeginOffset
-	//case rocketmq.PullBrokerTimeout:
-	//	fmt.Println("broker timeout occur")
-	//}
-	//}
-}
-
-func init() {
-	// consumer
-	name := "stableTestProducer"
-	p := &stableTestProducer{stableTest: &stableTest{}}
-	p.buildFlags(name)
-	p.op = p.sendMessage
-	registerCommand(name, p)
-
-	// consumer
-	name = "stableTestConsumer"
-	c := &stableTestConsumer{stableTest: &stableTest{}, offsets: map[int]int64{}}
-	c.buildFlags(name)
-	c.op = c.pullMessage
-	registerCommand(name, c)
-}
diff --git a/config.go b/config.go
deleted file mode 100644
index 8f1592c..0000000
--- a/config.go
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-package rocketmq
diff --git a/consumer/consumer.go b/consumer/consumer.go
deleted file mode 100644
index 8056b22..0000000
--- a/consumer/consumer.go
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"sort"
-	"strconv"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	jsoniter "github.com/json-iterator/go"
-
-	"github.com/tidwall/gjson"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-const (
-	// Delay some time when exception error
-	_PullDelayTimeWhenError = 3 * time.Second
-
-	// Flow control interval
-	_PullDelayTimeWhenFlowControl = 50 * time.Millisecond
-
-	// Delay some time when suspend pull service
-	_PullDelayTimeWhenSuspend = 30 * time.Second
-
-	// Long polling mode, the Consumer connection max suspend time
-	_BrokerSuspendMaxTime = 20 * time.Second
-
-	// Long polling mode, the Consumer connection timeout (must greater than _BrokerSuspendMaxTime)
-	_ConsumerTimeoutWhenSuspend = 30 * time.Second
-
-	// Offset persistent interval for consumer
-	_PersistConsumerOffsetInterval = 5 * time.Second
-)
-
-type ConsumeType string
-
-const (
-	_PullConsume = ConsumeType("CONSUME_ACTIVELY")
-	_PushConsume = ConsumeType("CONSUME_PASSIVELY")
-
-	_SubAll = "*"
-)
-
-// Message model defines the way how messages are delivered to each consumer clients.
-// </p>
-//
-// RocketMQ supports two message models: clustering and broadcasting. If clustering is set, consumer clients with
-// the same {@link #ConsumerGroup} would only consume shards of the messages subscribed, which achieves load
-// balances; Conversely, if the broadcasting is set, each consumer client will consume all subscribed messages
-// separately.
-// </p>
-//
-// This field defaults to clustering.
-type MessageModel int
-
-const (
-	BroadCasting MessageModel = iota
-	Clustering
-)
-
-func (mode MessageModel) String() string {
-	switch mode {
-	case BroadCasting:
-		return "BroadCasting"
-	case Clustering:
-		return "Clustering"
-	default:
-		return "Unknown"
-	}
-}
-
-// Consuming point on consumer booting.
-// </p>
-//
-// There are three consuming points:
-// <ul>
-// <li>
-// <code>CONSUME_FROM_LAST_OFFSET</code>: consumer clients pick up where it stopped previously.
-// If it were a newly booting up consumer client, according aging of the consumer group, there are two
-// cases:
-// <ol>
-// <li>
-// if the consumer group is created so recently that the earliest message being subscribed has yet
-// expired, which means the consumer group represents a lately launched business, consuming will
-// start from the very beginning;
-// </li>
-// <li>
-// if the earliest message being subscribed has expired, consuming will start from the latest
-// messages, meaning messages born prior to the booting timestamp would be ignored.
-// </li>
-// </ol>
-// </li>
-// <li>
-// <code>CONSUME_FROM_FIRST_OFFSET</code>: Consumer client will start from earliest messages available.
-// </li>
-// <li>
-// <code>CONSUME_FROM_TIMESTAMP</code>: Consumer client will start from specified timestamp, which means
-// messages born prior to {@link #consumeTimestamp} will be ignored
-// </li>
-// </ul>
-type ConsumeFromWhere int
-
-const (
-	ConsumeFromLastOffset ConsumeFromWhere = iota
-	ConsumeFromFirstOffset
-	ConsumeFromTimestamp
-)
-
-type ExpressionType string
-
-const (
-	/**
-	 * <ul>
-	 * Keywords:
-	 * <li>{@code AND, OR, NOT, BETWEEN, IN, TRUE, FALSE, IS, NULL}</li>
-	 * </ul>
-	 * <p/>
-	 * <ul>
-	 * Data type:
-	 * <li>Boolean, like: TRUE, FALSE</li>
-	 * <li>String, like: 'abc'</li>
-	 * <li>Decimal, like: 123</li>
-	 * <li>Float number, like: 3.1415</li>
-	 * </ul>
-	 * <p/>
-	 * <ul>
-	 * Grammar:
-	 * <li>{@code AND, OR}</li>
-	 * <li>{@code >, >=, <, <=, =}</li>
-	 * <li>{@code BETWEEN A AND B}, equals to {@code >=A AND <=B}</li>
-	 * <li>{@code NOT BETWEEN A AND B}, equals to {@code >B OR <A}</li>
-	 * <li>{@code IN ('a', 'b')}, equals to {@code ='a' OR ='b'}, this operation only support String type.</li>
-	 * <li>{@code IS NULL}, {@code IS NOT NULL}, check parameter whether is null, or not.</li>
-	 * <li>{@code =TRUE}, {@code =FALSE}, check parameter whether is true, or false.</li>
-	 * </ul>
-	 * <p/>
-	 * <p>
-	 * Example:
-	 * (a > 10 AND a < 100) OR (b IS NOT NULL AND b=TRUE)
-	 * </p>
-	 */
-	SQL92 = ExpressionType("SQL92")
-
-	/**
-	 * Only support or operation such as
-	 * "tag1 || tag2 || tag3", <br>
-	 * If null or * expression, meaning subscribe all.
-	 */
-	TAG = ExpressionType("TAG")
-)
-
-func IsTagType(exp string) bool {
-	if exp == "" || exp == "TAG" {
-		return true
-	}
-	return false
-}
-
-type MessageSelector struct {
-	Type       ExpressionType
-	Expression string
-}
-
-type ConsumeResult int
-
-const (
-	ConsumeSuccess ConsumeResult = iota
-	ConsumeRetryLater
-	Commit
-	Rollback
-	SuspendCurrentQueueAMoment
-)
-
-type ConsumeResultHolder struct {
-	ConsumeResult
-}
-
-type ConsumerReturn int
-
-const (
-	SuccessReturn ConsumerReturn = iota
-	ExceptionReturn
-	NullReturn
-	TimeoutReturn
-	FailedReturn
-)
-
-type PullRequest struct {
-	consumerGroup string
-	mq            *primitive.MessageQueue
-	pq            *processQueue
-	nextOffset    int64
-	lockedFirst   bool
-}
-
-func (pr *PullRequest) String() string {
-	return fmt.Sprintf("[ConsumerGroup: %s, Topic: %s, MessageQueue: %d]",
-		pr.consumerGroup, pr.mq.Topic, pr.mq.QueueId)
-}
-
-type defaultConsumer struct {
-	/**
-	 * Consumers of the same role is required to have exactly same subscriptions and consumerGroup to correctly achieve
-	 * load balance. It's required and needs to be globally unique.
-	 * </p>
-	 *
-	 * See <a href="http://rocketmq.apache.org/docs/core-concept/">here</a> for further discussion.
-	 */
-	consumerGroup          string
-	model                  MessageModel
-	allocate               func(string, string, []*primitive.MessageQueue, []string) []*primitive.MessageQueue
-	unitMode               bool
-	consumeOrderly         bool
-	fromWhere              ConsumeFromWhere
-	consumerStartTimestamp int64
-
-	cType     ConsumeType
-	client    internal.RMQClient
-	mqChanged func(topic string, mqAll, mqDivided []*primitive.MessageQueue)
-	state     int32
-	pause     bool
-	once      sync.Once
-	option    consumerOptions
-	// key: primitive.MessageQueue
-	// value: *processQueue
-	processQueueTable sync.Map
-
-	// key: topic(string)
-	// value: map[int]*primitive.MessageQueue
-	topicSubscribeInfoTable sync.Map
-
-	// key: topic
-	// value: *SubscriptionData
-	subscriptionDataTable sync.Map
-	storage               OffsetStore
-	// chan for push consumer
-	prCh chan PullRequest
-
-	pullFromWhichNodeTable sync.Map
-
-	stat *StatsManager
-}
-
-func (dc *defaultConsumer) start() error {
-	if dc.model == Clustering {
-		// set retry topic
-		retryTopic := internal.GetRetryTopic(dc.consumerGroup)
-		sub := buildSubscriptionData(retryTopic, MessageSelector{TAG, _SubAll})
-		dc.subscriptionDataTable.Store(retryTopic, sub)
-	}
-
-	if dc.model == Clustering {
-		dc.option.ChangeInstanceNameToPID()
-		dc.storage = NewRemoteOffsetStore(dc.consumerGroup, dc.client, dc.client.GetNameSrv())
-	} else {
-		dc.storage = NewLocalFileOffsetStore(dc.consumerGroup, dc.client.ClientID())
-	}
-
-	dc.client.Start()
-	atomic.StoreInt32(&dc.state, int32(internal.StateRunning))
-	dc.consumerStartTimestamp = time.Now().UnixNano() / int64(time.Millisecond)
-	dc.stat = NewStatsManager()
-	return nil
-}
-
-func (dc *defaultConsumer) shutdown() error {
-	atomic.StoreInt32(&dc.state, int32(internal.StateShutdown))
-
-	mqs := make([]*primitive.MessageQueue, 0)
-	dc.processQueueTable.Range(func(key, value interface{}) bool {
-		k := key.(primitive.MessageQueue)
-		pq := value.(*processQueue)
-		pq.WithDropped(true)
-		// close msg channel using RWMutex to make sure no data was writing
-		pq.mutex.Lock()
-		close(pq.msgCh)
-		pq.mutex.Unlock()
-		mqs = append(mqs, &k)
-		return true
-	})
-	dc.stat.ShutDownStat()
-	dc.storage.persist(mqs)
-	dc.client.Shutdown()
-	return nil
-}
-
-func (dc *defaultConsumer) persistConsumerOffset() error {
-	err := dc.makeSureStateOK()
-	if err != nil {
-		return err
-	}
-	mqs := make([]*primitive.MessageQueue, 0)
-	dc.processQueueTable.Range(func(key, value interface{}) bool {
-		k := key.(primitive.MessageQueue)
-		mqs = append(mqs, &k)
-		return true
-	})
-	dc.storage.persist(mqs)
-	return nil
-}
-
-func (dc *defaultConsumer) updateOffset(queue *primitive.MessageQueue, offset int64) error {
-	dc.storage.update(queue, offset, false)
-	return nil
-}
-
-func (dc *defaultConsumer) subscriptionAutomatically(topic string) {
-	_, exist := dc.subscriptionDataTable.Load(topic)
-	if !exist {
-		s := MessageSelector{
-			Expression: _SubAll,
-		}
-		dc.subscriptionDataTable.Store(topic, buildSubscriptionData(topic, s))
-	}
-}
-
-func (dc *defaultConsumer) updateTopicSubscribeInfo(topic string, mqs []*primitive.MessageQueue) {
-	_, exist := dc.subscriptionDataTable.Load(topic)
-	if exist {
-		dc.topicSubscribeInfoTable.Store(topic, mqs)
-	}
-}
-
-func (dc *defaultConsumer) isSubscribeTopicNeedUpdate(topic string) bool {
-	_, exist := dc.subscriptionDataTable.Load(topic)
-	if !exist {
-		return false
-	}
-	_, exist = dc.topicSubscribeInfoTable.Load(topic)
-	return !exist
-}
-
-func (dc *defaultConsumer) doBalance() {
-	dc.subscriptionDataTable.Range(func(key, value interface{}) bool {
-		topic := key.(string)
-		v, exist := dc.topicSubscribeInfoTable.Load(topic)
-		if !exist {
-			rlog.Warning("do balance in group failed, the topic does not exist", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: dc.consumerGroup,
-				rlog.LogKeyTopic:         topic,
-			})
-			return true
-		}
-		mqs := v.([]*primitive.MessageQueue)
-		switch dc.model {
-		case BroadCasting:
-			changed := dc.updateProcessQueueTable(topic, mqs)
-			if changed {
-				dc.mqChanged(topic, mqs, mqs)
-				rlog.Debug("MessageQueue changed", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyTopic:         topic,
-					rlog.LogKeyMessageQueue:  fmt.Sprintf("%v", mqs),
-				})
-			}
-		case Clustering:
-			cidAll := dc.findConsumerList(topic)
-			if cidAll == nil {
-				rlog.Warning("do balance in group failed, get consumer id list failed", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyTopic:         topic,
-				})
-				return true
-			}
-			mqAll := make([]*primitive.MessageQueue, len(mqs))
-			copy(mqAll, mqs)
-			sort.Strings(cidAll)
-			sort.SliceStable(mqAll, func(i, j int) bool {
-				v := strings.Compare(mqAll[i].Topic, mqAll[j].Topic)
-				if v != 0 {
-					return v < 0
-				}
-
-				v = strings.Compare(mqAll[i].BrokerName, mqAll[j].BrokerName)
-				if v != 0 {
-					return v < 0
-				}
-				return (mqAll[i].QueueId - mqAll[j].QueueId) < 0
-			})
-			allocateResult := dc.allocate(dc.consumerGroup, dc.client.ClientID(), mqAll, cidAll)
-			changed := dc.updateProcessQueueTable(topic, allocateResult)
-			if changed {
-				dc.mqChanged(topic, mqAll, allocateResult)
-				rlog.Debug("MessageQueue do balance done", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyTopic:         topic,
-					"clientID":               dc.client.ClientID(),
-					"mqAllSize":              len(mqAll),
-					"cidAllSize":             len(cidAll),
-					"rebalanceResultSize":    len(allocateResult),
-					"rebalanceResultSet":     allocateResult,
-				})
-			}
-		}
-		return true
-	})
-}
-
-func (dc *defaultConsumer) SubscriptionDataList() []*internal.SubscriptionData {
-	result := make([]*internal.SubscriptionData, 0)
-	dc.subscriptionDataTable.Range(func(key, value interface{}) bool {
-		result = append(result, value.(*internal.SubscriptionData))
-		return true
-	})
-	return result
-}
-
-func (dc *defaultConsumer) makeSureStateOK() error {
-	if atomic.LoadInt32(&dc.state) != int32(internal.StateRunning) {
-		return fmt.Errorf("state not running, actually: %v", dc.state)
-	}
-	return nil
-}
-
-type lockBatchRequestBody struct {
-	ConsumerGroup string                    `json:"consumerGroup"`
-	ClientId      string                    `json:"clientId"`
-	MQs           []*primitive.MessageQueue `json:"mqSet"`
-}
-
-func (dc *defaultConsumer) lock(mq *primitive.MessageQueue) bool {
-	brokerResult := dc.client.GetNameSrv().FindBrokerAddressInSubscribe(mq.BrokerName, internal.MasterId, true)
-
-	if brokerResult == nil {
-		return false
-	}
-
-	body := &lockBatchRequestBody{
-		ConsumerGroup: dc.consumerGroup,
-		ClientId:      dc.client.ClientID(),
-		MQs:           []*primitive.MessageQueue{mq},
-	}
-	lockedMQ := dc.doLock(brokerResult.BrokerAddr, body)
-	var lockOK bool
-	for idx := range lockedMQ {
-		_mq := lockedMQ[idx]
-		v, exist := dc.processQueueTable.Load(_mq)
-		if exist {
-			pq := v.(*processQueue)
-			pq.WithLock(true)
-			pq.UpdateLastConsumeTime()
-			pq.UpdateLastLockTime()
-		}
-		if _mq == *mq {
-			lockOK = true
-		}
-	}
-	fields := map[string]interface{}{
-		"lockOK":                 lockOK,
-		rlog.LogKeyConsumerGroup: dc.consumerGroup,
-		rlog.LogKeyMessageQueue:  mq.String(),
-	}
-	if lockOK {
-		rlog.Debug("lock MessageQueue", fields)
-	} else {
-		rlog.Info("lock MessageQueue", fields)
-	}
-	return lockOK
-}
-
-func (dc *defaultConsumer) unlock(mq *primitive.MessageQueue, oneway bool) {
-	brokerResult := dc.client.GetNameSrv().FindBrokerAddressInSubscribe(mq.BrokerName, internal.MasterId, true)
-
-	if brokerResult == nil {
-		return
-	}
-
-	body := &lockBatchRequestBody{
-		ConsumerGroup: dc.consumerGroup,
-		ClientId:      dc.client.ClientID(),
-		MQs:           []*primitive.MessageQueue{mq},
-	}
-	dc.doUnlock(brokerResult.BrokerAddr, body, oneway)
-	rlog.Info("unlock MessageQueue", map[string]interface{}{
-		rlog.LogKeyConsumerGroup: dc.consumerGroup,
-		"clientID":               dc.client.ClientID(),
-		rlog.LogKeyMessageQueue:  mq.String(),
-	})
-}
-
-func (dc *defaultConsumer) lockAll() {
-	mqMapSet := dc.buildProcessQueueTableByBrokerName()
-	for broker, mqs := range mqMapSet {
-		if len(mqs) == 0 {
-			continue
-		}
-		brokerResult := dc.client.GetNameSrv().FindBrokerAddressInSubscribe(broker, internal.MasterId, true)
-		if brokerResult == nil {
-			continue
-		}
-		body := &lockBatchRequestBody{
-			ConsumerGroup: dc.consumerGroup,
-			ClientId:      dc.client.ClientID(),
-			MQs:           mqs,
-		}
-		lockedMQ := dc.doLock(brokerResult.BrokerAddr, body)
-		set := make(map[primitive.MessageQueue]bool)
-		for idx := range lockedMQ {
-			_mq := lockedMQ[idx]
-			v, exist := dc.processQueueTable.Load(_mq)
-			if exist {
-				pq := v.(*processQueue)
-				pq.WithLock(true)
-				pq.UpdateLastConsumeTime()
-			}
-			set[_mq] = true
-		}
-		for idx := range mqs {
-			_mq := mqs[idx]
-			if !set[*_mq] {
-				v, exist := dc.processQueueTable.Load(_mq)
-				if exist {
-					pq := v.(*processQueue)
-					pq.WithLock(false)
-					pq.UpdateLastLockTime()
-					rlog.Info("lock MessageQueue", map[string]interface{}{
-						"lockOK":                 false,
-						rlog.LogKeyConsumerGroup: dc.consumerGroup,
-						rlog.LogKeyMessageQueue:  _mq.String(),
-					})
-				}
-			}
-		}
-	}
-}
-
-func (dc *defaultConsumer) unlockAll(oneway bool) {
-	mqMapSet := dc.buildProcessQueueTableByBrokerName()
-	for broker, mqs := range mqMapSet {
-		if len(mqs) == 0 {
-			continue
-		}
-		brokerResult := dc.client.GetNameSrv().FindBrokerAddressInSubscribe(broker, internal.MasterId, true)
-		if brokerResult == nil {
-			continue
-		}
-		body := &lockBatchRequestBody{
-			ConsumerGroup: dc.consumerGroup,
-			ClientId:      dc.client.ClientID(),
-			MQs:           mqs,
-		}
-		dc.doUnlock(brokerResult.BrokerAddr, body, oneway)
-		for idx := range mqs {
-			_mq := mqs[idx]
-			v, exist := dc.processQueueTable.Load(_mq)
-			if exist {
-				rlog.Info("lock MessageQueue", map[string]interface{}{
-					"lockOK":                 false,
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyMessageQueue:  _mq.String(),
-				})
-				v.(*processQueue).WithLock(false)
-			}
-		}
-	}
-}
-
-func (dc *defaultConsumer) doLock(addr string, body *lockBatchRequestBody) []primitive.MessageQueue {
-	data, _ := jsoniter.Marshal(body)
-	request := remote.NewRemotingCommand(internal.ReqLockBatchMQ, nil, data)
-	response, err := dc.client.InvokeSync(context.Background(), addr, request, 1*time.Second)
-	if err != nil {
-		rlog.Error("lock MessageQueue to broker invoke error", map[string]interface{}{
-			rlog.LogKeyBroker:        addr,
-			rlog.LogKeyUnderlayError: err,
-		})
-		return nil
-	}
-	lockOKMQSet := struct {
-		MQs []primitive.MessageQueue `json:"lockOKMQSet"`
-	}{}
-	if len(response.Body) == 0 {
-		return nil
-	}
-	err = jsoniter.Unmarshal(response.Body, &lockOKMQSet)
-	if err != nil {
-		rlog.Error("Unmarshal lock mq body error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-		return nil
-	}
-	return lockOKMQSet.MQs
-}
-
-func (dc *defaultConsumer) doUnlock(addr string, body *lockBatchRequestBody, oneway bool) {
-	data, _ := jsoniter.Marshal(body)
-	request := remote.NewRemotingCommand(internal.ReqUnlockBatchMQ, nil, data)
-	if oneway {
-		err := dc.client.InvokeOneWay(context.Background(), addr, request, 3*time.Second)
-		if err != nil {
-			rlog.Error("lock MessageQueue to broker invoke oneway error", map[string]interface{}{
-				rlog.LogKeyBroker:        addr,
-				rlog.LogKeyUnderlayError: err,
-			})
-		}
-	} else {
-		response, err := dc.client.InvokeSync(context.Background(), addr, request, 1*time.Second)
-		rlog.Error("lock MessageQueue to broker invoke error", map[string]interface{}{
-			rlog.LogKeyBroker:        addr,
-			rlog.LogKeyUnderlayError: err,
-		})
-		if response.Code != internal.ResSuccess {
-			// TODO error
-		}
-	}
-}
-
-func (dc *defaultConsumer) buildProcessQueueTableByBrokerName() map[string][]*primitive.MessageQueue {
-	result := make(map[string][]*primitive.MessageQueue, 0)
-
-	dc.processQueueTable.Range(func(key, value interface{}) bool {
-		mq := key.(primitive.MessageQueue)
-		mqs, exist := result[mq.BrokerName]
-		if !exist {
-			mqs = make([]*primitive.MessageQueue, 0)
-		}
-		mqs = append(mqs, &mq)
-		result[mq.BrokerName] = mqs
-		return true
-	})
-
-	return result
-}
-
-func (dc *defaultConsumer) updateProcessQueueTable(topic string, mqs []*primitive.MessageQueue) bool {
-	var changed bool
-	mqSet := make(map[primitive.MessageQueue]bool)
-	for idx := range mqs {
-		mqSet[*mqs[idx]] = true
-	}
-	dc.processQueueTable.Range(func(key, value interface{}) bool {
-		mq := key.(primitive.MessageQueue)
-		pq := value.(*processQueue)
-		if mq.Topic == topic {
-			if !mqSet[mq] {
-				pq.WithDropped(true)
-				if dc.removeUnnecessaryMessageQueue(&mq, pq) {
-					dc.processQueueTable.Delete(key)
-					changed = true
-					rlog.Debug("remove unnecessary mq when updateProcessQueueTable", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: dc.consumerGroup,
-						rlog.LogKeyMessageQueue:  mq.String(),
-					})
-				}
-			} else if pq.isPullExpired() && dc.cType == _PushConsume {
-				pq.WithDropped(true)
-				if dc.removeUnnecessaryMessageQueue(&mq, pq) {
-					dc.processQueueTable.Delete(key)
-					changed = true
-					rlog.Debug("remove unnecessary mq because pull was paused, prepare to fix it", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: dc.consumerGroup,
-						rlog.LogKeyMessageQueue:  mq.String(),
-					})
-				}
-			}
-		}
-		return true
-	})
-
-	if dc.cType == _PushConsume {
-		for item := range mqSet {
-			// BUG: the mq will send to channel, if not copy once, the next iter will modify the mq in the channel.
-			mq := item
-			_, exist := dc.processQueueTable.Load(mq)
-			if exist {
-				continue
-			}
-			if dc.consumeOrderly && !dc.lock(&mq) {
-				rlog.Warning("do defaultConsumer, add a new mq failed, because lock failed", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyMessageQueue:  mq.String(),
-				})
-				continue
-			}
-			dc.storage.remove(&mq)
-			nextOffset := dc.computePullFromWhere(&mq)
-			if nextOffset >= 0 {
-				_, exist := dc.processQueueTable.Load(mq)
-				if exist {
-					rlog.Debug("do defaultConsumer, mq already exist", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: dc.consumerGroup,
-						rlog.LogKeyMessageQueue:  mq.String(),
-					})
-				} else {
-					rlog.Debug("do defaultConsumer, add a new mq", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: dc.consumerGroup,
-						rlog.LogKeyMessageQueue:  mq.String(),
-					})
-					pq := newProcessQueue(dc.consumeOrderly)
-					dc.processQueueTable.Store(mq, pq)
-					pr := PullRequest{
-						consumerGroup: dc.consumerGroup,
-						mq:            &mq,
-						pq:            pq,
-						nextOffset:    nextOffset,
-					}
-					dc.prCh <- pr
-					changed = true
-				}
-			} else {
-				rlog.Warning("do defaultConsumer, add a new mq failed", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: dc.consumerGroup,
-					rlog.LogKeyMessageQueue:  mq.String(),
-				})
-			}
-		}
-	}
-
-	return changed
-}
-
-func (dc *defaultConsumer) removeUnnecessaryMessageQueue(mq *primitive.MessageQueue, pq *processQueue) bool {
-	dc.storage.persist([]*primitive.MessageQueue{mq})
-	dc.storage.remove(mq)
-	return true
-}
-
-func (dc *defaultConsumer) computePullFromWhere(mq *primitive.MessageQueue) int64 {
-	if dc.cType == _PullConsume {
-		return 0
-	}
-	var result = int64(-1)
-	lastOffset := dc.storage.read(mq, _ReadFromStore)
-	if lastOffset >= 0 {
-		result = lastOffset
-	} else {
-		switch dc.option.FromWhere {
-		case ConsumeFromLastOffset:
-			if lastOffset == -1 {
-				if strings.HasPrefix(mq.Topic, internal.RetryGroupTopicPrefix) {
-					result = 0
-				} else {
-					lastOffset, err := dc.queryMaxOffset(mq)
-					if err == nil {
-						result = lastOffset
-					} else {
-						rlog.Warning("query max offset error", map[string]interface{}{
-							rlog.LogKeyMessageQueue:  mq,
-							rlog.LogKeyUnderlayError: err,
-						})
-					}
-				}
-			} else {
-				result = -1
-			}
-		case ConsumeFromFirstOffset:
-			if lastOffset == -1 {
-				result = 0
-			}
-		case ConsumeFromTimestamp:
-			if lastOffset == -1 {
-				if strings.HasPrefix(mq.Topic, internal.RetryGroupTopicPrefix) {
-					lastOffset, err := dc.queryMaxOffset(mq)
-					if err == nil {
-						result = lastOffset
-					} else {
-						result = -1
-						rlog.Warning("query max offset error", map[string]interface{}{
-							rlog.LogKeyMessageQueue:  mq,
-							rlog.LogKeyUnderlayError: err,
-						})
-					}
-				} else {
-					t, err := time.Parse("20060102150405", dc.option.ConsumeTimestamp)
-					if err != nil {
-						result = -1
-					} else {
-						lastOffset, err := dc.searchOffsetByTimestamp(mq, t.Unix()*1000)
-						if err != nil {
-							result = -1
-						} else {
-							result = lastOffset
-						}
-					}
-				}
-			}
-		default:
-		}
-	}
-	return result
-}
-
-func (dc *defaultConsumer) pullInner(ctx context.Context, queue *primitive.MessageQueue, data *internal.SubscriptionData,
-	offset int64, numbers int, sysFlag int32, commitOffsetValue int64) (*primitive.PullResult, error) {
-
-	brokerResult := dc.tryFindBroker(queue)
-	if brokerResult == nil {
-		rlog.Warning("no broker found for mq", map[string]interface{}{
-			rlog.LogKeyMessageQueue: queue,
-		})
-		return nil, errors.ErrBrokerNotFound
-	}
-
-	if brokerResult.Slave {
-		sysFlag = clearCommitOffsetFlag(sysFlag)
-	}
-
-	if (data.ExpType == string(TAG)) && brokerResult.BrokerVersion < internal.V4_1_0 {
-		return nil, fmt.Errorf("the broker [%s, %v] does not upgrade to support for filter message by %v",
-			queue.BrokerName, brokerResult.BrokerVersion, data.ExpType)
-	}
-
-	pullRequest := &internal.PullMessageRequestHeader{
-		ConsumerGroup: dc.consumerGroup,
-		Topic:         queue.Topic,
-		QueueId:       int32(queue.QueueId),
-		QueueOffset:   offset,
-		MaxMsgNums:    int32(numbers),
-		SysFlag:       sysFlag,
-		CommitOffset:  commitOffsetValue,
-		// TODO: 和java对齐
-		SuspendTimeoutMillis: _BrokerSuspendMaxTime,
-		SubExpression:        data.SubString,
-		// TODO: add subversion
-		ExpressionType: string(data.ExpType),
-	}
-
-	if data.ExpType == string(TAG) {
-		pullRequest.SubVersion = 0
-	} else {
-		pullRequest.SubVersion = data.SubVersion
-	}
-
-	// TODO: add computPullFromWhichFilterServer
-
-	return dc.client.PullMessage(context.Background(), brokerResult.BrokerAddr, pullRequest)
-}
-
-func (dc *defaultConsumer) processPullResult(mq *primitive.MessageQueue, result *primitive.PullResult, data *internal.SubscriptionData) {
-
-	dc.updatePullFromWhichNode(mq, result.SuggestWhichBrokerId)
-
-	switch result.Status {
-	case primitive.PullFound:
-		result.SetMessageExts(primitive.DecodeMessage(result.GetBody()))
-		msgs := result.GetMessageExts()
-
-		// filter message according to tags
-		msgListFilterAgain := msgs
-		if data.Tags.Len() > 0 && data.ClassFilterMode {
-			msgListFilterAgain = make([]*primitive.MessageExt, 0)
-			for _, msg := range msgs {
-				_, exist := data.Tags.Contains(msg.GetTags())
-				if exist {
-					msgListFilterAgain = append(msgListFilterAgain, msg)
-				}
-			}
-		}
-
-		// TODO: add filter message hook
-		for _, msg := range msgListFilterAgain {
-			traFlag, _ := strconv.ParseBool(msg.GetProperty(primitive.PropertyTransactionPrepared))
-			if traFlag {
-				msg.TransactionId = msg.GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex)
-			}
-
-			msg.WithProperty(primitive.PropertyMinOffset, strconv.FormatInt(result.MinOffset, 10))
-			msg.WithProperty(primitive.PropertyMaxOffset, strconv.FormatInt(result.MaxOffset, 10))
-		}
-
-		result.SetMessageExts(msgListFilterAgain)
-	}
-}
-
-func (dc *defaultConsumer) findConsumerList(topic string) []string {
-	brokerAddr := dc.client.GetNameSrv().FindBrokerAddrByTopic(topic)
-	if brokerAddr == "" {
-		dc.client.GetNameSrv().UpdateTopicRouteInfo(topic)
-		brokerAddr = dc.client.GetNameSrv().FindBrokerAddrByTopic(topic)
-	}
-
-	if brokerAddr != "" {
-		req := &internal.GetConsumerListRequestHeader{
-			ConsumerGroup: dc.consumerGroup,
-		}
-		cmd := remote.NewRemotingCommand(internal.ReqGetConsumerListByGroup, req, nil)
-		res, err := dc.client.InvokeSync(context.Background(), brokerAddr, cmd, 3*time.Second) // TODO 超时机制有问题
-		if err != nil {
-			rlog.Error("get consumer list of group from broker error", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: dc.consumerGroup,
-				rlog.LogKeyBroker:        brokerAddr,
-				rlog.LogKeyUnderlayError: err,
-			})
-			return nil
-		}
-		result := gjson.ParseBytes(res.Body)
-		list := make([]string, 0)
-		arr := result.Get("consumerIdList").Array()
-		for idx := range arr {
-			list = append(list, arr[idx].String())
-		}
-		return list
-	}
-	return nil
-}
-
-func (dc *defaultConsumer) sendBack(msg *primitive.MessageExt, level int) error {
-	return nil
-}
-
-// QueryMaxOffset with specific queueId and topic
-func (dc *defaultConsumer) queryMaxOffset(mq *primitive.MessageQueue) (int64, error) {
-	brokerAddr := dc.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-	if brokerAddr == "" {
-		dc.client.GetNameSrv().UpdateTopicRouteInfo(mq.Topic)
-		brokerAddr = dc.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-	}
-	if brokerAddr == "" {
-		return -1, fmt.Errorf("the broker [%s] does not exist", mq.BrokerName)
-	}
-
-	request := &internal.GetMaxOffsetRequestHeader{
-		Topic:   mq.Topic,
-		QueueId: mq.QueueId,
-	}
-
-	cmd := remote.NewRemotingCommand(internal.ReqGetMaxOffset, request, nil)
-	response, err := dc.client.InvokeSync(context.Background(), brokerAddr, cmd, 3*time.Second)
-	if err != nil {
-		return -1, err
-	}
-
-	return strconv.ParseInt(response.ExtFields["offset"], 10, 64)
-}
-
-func (dc *defaultConsumer) queryOffset(mq *primitive.MessageQueue) int64 {
-	return dc.storage.read(mq, _ReadMemoryThenStore)
-}
-
-// SearchOffsetByTimestamp with specific queueId and topic
-func (dc *defaultConsumer) searchOffsetByTimestamp(mq *primitive.MessageQueue, timestamp int64) (int64, error) {
-	brokerAddr := dc.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-	if brokerAddr == "" {
-		dc.client.GetNameSrv().UpdateTopicRouteInfo(mq.Topic)
-		brokerAddr = dc.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-	}
-	if brokerAddr == "" {
-		return -1, fmt.Errorf("the broker [%s] does not exist", mq.BrokerName)
-	}
-
-	request := &internal.SearchOffsetRequestHeader{
-		Topic:     mq.Topic,
-		QueueId:   mq.QueueId,
-		Timestamp: timestamp,
-	}
-
-	cmd := remote.NewRemotingCommand(internal.ReqSearchOffsetByTimestamp, request, nil)
-	response, err := dc.client.InvokeSync(context.Background(), brokerAddr, cmd, 3*time.Second)
-	if err != nil {
-		return -1, err
-	}
-
-	return strconv.ParseInt(response.ExtFields["offset"], 10, 64)
-}
-
-func buildSubscriptionData(topic string, selector MessageSelector) *internal.SubscriptionData {
-	subData := &internal.SubscriptionData{
-		Topic:     topic,
-		SubString: selector.Expression,
-		ExpType:   string(selector.Type),
-	}
-	subData.SubVersion = time.Now().UnixNano()
-
-	if selector.Type != "" && selector.Type != TAG {
-		return subData
-	}
-
-	if selector.Expression == "" || selector.Expression == _SubAll {
-		subData.ExpType = string(TAG)
-		subData.SubString = _SubAll
-	} else {
-		tags := strings.Split(selector.Expression, "||")
-		subData.Tags = utils.NewSet()
-		subData.Codes = utils.NewSet()
-		for idx := range tags {
-			trimString := strings.Trim(tags[idx], " ")
-			if trimString != "" {
-				if _, ok := subData.Tags.Contains(trimString); !ok {
-					subData.Tags.AddKV(trimString, trimString)
-				}
-				hCode := utils.HashString(trimString)
-				v := strconv.Itoa(hCode)
-				if _, ok := subData.Codes.Contains(v); !ok {
-					subData.Codes.AddKV(v, v)
-				}
-			}
-		}
-	}
-	return subData
-}
-
-func buildSysFlag(commitOffset, suspend, subscription, classFilter bool) int32 {
-	var flag int32 = 0
-	if commitOffset {
-		flag |= 0x1 << 0
-	}
-
-	if suspend {
-		flag |= 0x1 << 1
-	}
-
-	if subscription {
-		flag |= 0x1 << 2
-	}
-
-	if classFilter {
-		flag |= 0x1 << 3
-	}
-
-	return flag
-}
-
-func clearCommitOffsetFlag(sysFlag int32) int32 {
-	return sysFlag & (^0x1 << 0)
-}
-
-func (dc *defaultConsumer) tryFindBroker(mq *primitive.MessageQueue) *internal.FindBrokerResult {
-	result := dc.client.GetNameSrv().FindBrokerAddressInSubscribe(mq.BrokerName, dc.recalculatePullFromWhichNode(mq), false)
-	if result != nil {
-		return result
-	}
-	dc.client.GetNameSrv().UpdateTopicRouteInfo(mq.Topic)
-	return dc.client.GetNameSrv().FindBrokerAddressInSubscribe(mq.BrokerName, dc.recalculatePullFromWhichNode(mq), false)
-}
-
-func (dc *defaultConsumer) updatePullFromWhichNode(mq *primitive.MessageQueue, brokerId int64) {
-	dc.pullFromWhichNodeTable.Store(*mq, brokerId)
-}
-
-func (dc *defaultConsumer) recalculatePullFromWhichNode(mq *primitive.MessageQueue) int64 {
-	v, exist := dc.pullFromWhichNodeTable.Load(*mq)
-	if exist {
-		return v.(int64)
-	}
-	return internal.MasterId
-}
diff --git a/consumer/consumer_test.go b/consumer/consumer_test.go
deleted file mode 100644
index 12ccd18..0000000
--- a/consumer/consumer_test.go
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"sync"
-	"testing"
-	"time"
-
-	"github.com/golang/mock/gomock"
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/stretchr/testify/assert"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func TestParseTimestamp(t *testing.T) {
-	layout := "20060102150405"
-	timestamp, err := time.ParseInLocation(layout, "20190430193409", time.UTC)
-	assert.Nil(t, err)
-	assert.Equal(t, int64(1556652849), timestamp.Unix())
-}
-
-func TestDoRebalance(t *testing.T) {
-	Convey("Given a defaultConsumer", t, func() {
-		dc := &defaultConsumer{
-			model: Clustering,
-		}
-
-		topic := "test"
-		broker := "127.0.0.1:8889"
-		clientID := "clientID"
-		mqs := []*primitive.MessageQueue{
-			{
-				Topic:      topic,
-				BrokerName: "",
-				QueueId:    0,
-			},
-			{
-				Topic:      topic,
-				BrokerName: "",
-				QueueId:    1,
-			},
-		}
-		dc.topicSubscribeInfoTable.Store(topic, mqs)
-		sub := &internal.SubscriptionData{}
-		dc.subscriptionDataTable.Store(topic, sub)
-
-		ctrl := gomock.NewController(t)
-		defer ctrl.Finish()
-		namesrvCli := internal.NewMockNamesrvs(ctrl)
-		namesrvCli.EXPECT().FindBrokerAddrByTopic(gomock.Any()).Return(broker)
-
-		rmqCli := internal.NewMockRMQClient(ctrl)
-		rmqCli.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
-			Return(&remote.RemotingCommand{
-				Body: []byte("{\"consumerIdList\": [\"a1\", \"a2\", \"a3\"] }"),
-			}, nil)
-		rmqCli.EXPECT().ClientID().Return(clientID)
-		rmqCli.SetNameSrv(namesrvCli)
-
-		dc.client = rmqCli
-
-		var wg sync.WaitGroup
-		wg.Add(1)
-		dc.allocate = func(cg string, clientID string, mqAll []*primitive.MessageQueue, cidAll []string) []*primitive.MessageQueue {
-			assert.Equal(t, cidAll, []string{"a1", "a2", "a3"})
-			wg.Done()
-			return nil
-		}
-
-		dc.doBalance()
-
-		wg.Wait()
-	})
-}
-
-func TestComputePullFromWhere(t *testing.T) {
-	Convey("Given a defaultConsumer", t, func() {
-		dc := &defaultConsumer{
-			model: Clustering,
-			cType: _PushConsume,
-		}
-
-		ctrl := gomock.NewController(t)
-		defer ctrl.Finish()
-
-		offsetStore := NewMockOffsetStore(ctrl)
-		dc.storage = offsetStore
-
-		mq := &primitive.MessageQueue{
-			Topic: "test",
-		}
-
-		namesrvCli := internal.NewMockNamesrvs(ctrl)
-
-		rmqCli := internal.NewMockRMQClient(ctrl)
-		dc.client = rmqCli
-		rmqCli.SetNameSrv(namesrvCli)
-
-		Convey("get effective offset", func() {
-			offsetStore.EXPECT().read(gomock.Any(), gomock.Any()).Return(int64(10))
-			res := dc.computePullFromWhere(mq)
-			assert.Equal(t, int64(10), res)
-		})
-
-		Convey("ConsumeFromLastOffset for normal topic", func() {
-			offsetStore.EXPECT().read(gomock.Any(), gomock.Any()).Return(int64(-1))
-			dc.option.FromWhere = ConsumeFromLastOffset
-
-			broker := "a"
-			namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return(broker)
-
-			rmqCli.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
-				Return(&remote.RemotingCommand{
-					ExtFields: map[string]string{
-						"offset": "20",
-					},
-				}, nil)
-
-			res := dc.computePullFromWhere(mq)
-			assert.Equal(t, int64(20), res)
-		})
-
-		Convey("ConsumeFromFirstOffset for normal topic", func() {
-			offsetStore.EXPECT().read(gomock.Any(), gomock.Any()).Return(int64(-1))
-			dc.option.FromWhere = ConsumeFromFirstOffset
-
-			res := dc.computePullFromWhere(mq)
-			assert.Equal(t, int64(0), res)
-		})
-
-		Convey("ConsumeFromTimestamp for normal topic", func() {
-			offsetStore.EXPECT().read(gomock.Any(), gomock.Any()).Return(int64(-1))
-			dc.option.FromWhere = ConsumeFromTimestamp
-
-			dc.option.ConsumeTimestamp = "20060102150405"
-
-			broker := "a"
-			namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return(broker)
-
-			rmqCli.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
-				Return(&remote.RemotingCommand{
-					ExtFields: map[string]string{
-						"offset": "30",
-					},
-				}, nil)
-
-			res := dc.computePullFromWhere(mq)
-			assert.Equal(t, int64(30), res)
-		})
-
-	})
-}
diff --git a/consumer/interceptor.go b/consumer/interceptor.go
deleted file mode 100644
index 05ff94a..0000000
--- a/consumer/interceptor.go
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-// WithTrace support rocketmq trace: https://github.com/apache/rocketmq/wiki/RIP-6-Message-Trace.
-func WithTrace(traceCfg *primitive.TraceConfig) Option {
-	return func(options *consumerOptions) {
-
-		ori := options.Interceptors
-		options.Interceptors = make([]primitive.Interceptor, 0)
-		options.Interceptors = append(options.Interceptors, newTraceInterceptor(traceCfg))
-		options.Interceptors = append(options.Interceptors, ori...)
-	}
-}
-
-func newTraceInterceptor(traceCfg *primitive.TraceConfig) primitive.Interceptor {
-	dispatcher := internal.NewTraceDispatcher(traceCfg)
-	if dispatcher != nil {
-		dispatcher.Start()
-	}
-
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		if dispatcher == nil {
-			return fmt.Errorf("GetOrNewRocketMQClient faild")
-		}
-		consumerCtx, exist := primitive.GetConsumerCtx(ctx)
-		if !exist || len(consumerCtx.Msgs) == 0 {
-			return next(ctx, req, reply)
-		}
-
-		beginT := time.Now()
-		// before traceCtx
-		traceCx := internal.TraceContext{
-			RequestId: primitive.CreateUniqID(),
-			TimeStamp: time.Now().UnixNano() / int64(time.Millisecond),
-			TraceType: internal.SubBefore,
-			GroupName: consumerCtx.ConsumerGroup,
-			IsSuccess: true,
-		}
-		beans := make([]internal.TraceBean, 0)
-		for _, msg := range consumerCtx.Msgs {
-			if msg == nil {
-				continue
-			}
-			regionID := msg.GetRegionID()
-			traceOn := msg.IsTraceOn()
-			if traceOn == "false" {
-				continue
-			}
-			bean := internal.TraceBean{
-				Topic:      msg.Topic,
-				MsgId:      msg.MsgId,
-				Tags:       msg.GetTags(),
-				Keys:       msg.GetKeys(),
-				StoreTime:  msg.StoreTimestamp,
-				BodyLength: int(msg.StoreSize),
-				RetryTimes: int(msg.ReconsumeTimes),
-				ClientHost: utils.LocalIP,
-				StoreHost:  utils.LocalIP,
-			}
-			beans = append(beans, bean)
-			traceCx.RegionId = regionID
-		}
-		if len(beans) > 0 {
-			traceCx.TraceBeans = beans
-			traceCx.TimeStamp = time.Now().UnixNano() / int64(time.Millisecond)
-			dispatcher.Append(traceCx)
-		}
-
-		err := next(ctx, req, reply)
-
-		// after traceCtx
-		costTime := time.Since(beginT).Nanoseconds() / int64(time.Millisecond)
-		ctxType := consumerCtx.Properties[primitive.PropCtxType]
-		afterCtx := internal.TraceContext{
-			TimeStamp: time.Now().UnixNano() / int64(time.Millisecond),
-
-			TraceType:   internal.SubAfter,
-			RegionId:    traceCx.RegionId,
-			GroupName:   traceCx.GroupName,
-			RequestId:   traceCx.RequestId,
-			IsSuccess:   consumerCtx.Success,
-			CostTime:    costTime,
-			TraceBeans:  traceCx.TraceBeans,
-			ContextCode: primitive.ConsumeReturnType(ctxType).Ordinal(),
-		}
-		dispatcher.Append(afterCtx)
-		return err
-	}
-}
diff --git a/consumer/lock.go b/consumer/lock.go
deleted file mode 100644
index 6fb17cd..0000000
--- a/consumer/lock.go
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"sync"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-type QueueLock struct {
-	lockTable sync.Map
-}
-
-func newQueueLock() *QueueLock {
-	return &QueueLock{}
-}
-
-func (ql QueueLock) fetchLock(queue primitive.MessageQueue) sync.Locker {
-	v, _ := ql.lockTable.LoadOrStore(queue, new(sync.Mutex))
-	return v.(*sync.Mutex)
-}
diff --git a/consumer/mock_offset_store.go b/consumer/mock_offset_store.go
deleted file mode 100644
index bac1cdb..0000000
--- a/consumer/mock_offset_store.go
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by MockGen. DO NOT EDIT.
-// Source: offset_store.go
-
-// Package consumer is a generated GoMock package.
-package consumer
-
-import (
-	reflect "reflect"
-
-	primitive "github.com/apache/rocketmq-client-go/v2/primitive"
-	gomock "github.com/golang/mock/gomock"
-)
-
-// MockOffsetStore is a mock of OffsetStore interface
-type MockOffsetStore struct {
-	ctrl     *gomock.Controller
-	recorder *MockOffsetStoreMockRecorder
-}
-
-// MockOffsetStoreMockRecorder is the mock recorder for MockOffsetStore
-type MockOffsetStoreMockRecorder struct {
-	mock *MockOffsetStore
-}
-
-// NewMockOffsetStore creates a new mock instance
-func NewMockOffsetStore(ctrl *gomock.Controller) *MockOffsetStore {
-	mock := &MockOffsetStore{ctrl: ctrl}
-	mock.recorder = &MockOffsetStoreMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockOffsetStore) EXPECT() *MockOffsetStoreMockRecorder {
-	return m.recorder
-}
-
-// persist mocks base method
-func (m *MockOffsetStore) persist(mqs []*primitive.MessageQueue) {
-	m.ctrl.Call(m, "persist", mqs)
-}
-
-// persist indicates an expected call of persist
-func (mr *MockOffsetStoreMockRecorder) persist(mqs interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "persist", reflect.TypeOf((*MockOffsetStore)(nil).persist), mqs)
-}
-
-// remove mocks base method
-func (m *MockOffsetStore) remove(mq *primitive.MessageQueue) {
-	m.ctrl.Call(m, "remove", mq)
-}
-
-// remove indicates an expected call of remove
-func (mr *MockOffsetStoreMockRecorder) remove(mq interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "remove", reflect.TypeOf((*MockOffsetStore)(nil).remove), mq)
-}
-
-// read mocks base method
-func (m *MockOffsetStore) read(mq *primitive.MessageQueue, t readType) int64 {
-	ret := m.ctrl.Call(m, "read", mq, t)
-	ret0, _ := ret[0].(int64)
-	return ret0
-}
-
-// read indicates an expected call of read
-func (mr *MockOffsetStoreMockRecorder) read(mq, t interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "read", reflect.TypeOf((*MockOffsetStore)(nil).read), mq, t)
-}
-
-// update mocks base method
-func (m *MockOffsetStore) update(mq *primitive.MessageQueue, offset int64, increaseOnly bool) {
-	m.ctrl.Call(m, "update", mq, offset, increaseOnly)
-}
-
-// update indicates an expected call of update
-func (mr *MockOffsetStoreMockRecorder) update(mq, offset, increaseOnly interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "update", reflect.TypeOf((*MockOffsetStore)(nil).update), mq, offset, increaseOnly)
-}
diff --git a/consumer/offset_store.go b/consumer/offset_store.go
deleted file mode 100644
index 5ecfd14..0000000
--- a/consumer/offset_store.go
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"path/filepath"
-	"strconv"
-	"sync"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	jsoniter "github.com/json-iterator/go"
-)
-
-type readType int
-
-const (
-	_ReadFromMemory readType = iota
-	_ReadFromStore
-	_ReadMemoryThenStore
-)
-
-var (
-	_LocalOffsetStorePath = os.Getenv("rocketmq.client.localOffsetStoreDir")
-)
-
-func init() {
-	if _LocalOffsetStorePath == "" {
-		_LocalOffsetStorePath = filepath.Join(os.Getenv("HOME"), ".rocketmq_client_go")
-	}
-}
-
-//go:generate mockgen -source offset_store.go -destination mock_offset_store.go -self_package github.com/apache/rocketmq-client-go/v2/consumer  --package consumer OffsetStore
-type OffsetStore interface {
-	persist(mqs []*primitive.MessageQueue)
-	remove(mq *primitive.MessageQueue)
-	read(mq *primitive.MessageQueue, t readType) int64
-	update(mq *primitive.MessageQueue, offset int64, increaseOnly bool)
-}
-
-type OffsetSerializeWrapper struct {
-	OffsetTable map[MessageQueueKey]int64 `json:"offsetTable"`
-}
-
-type MessageQueueKey primitive.MessageQueue
-
-func (mq MessageQueueKey) MarshalText() (text []byte, err error) {
-	repr := struct {
-		Topic      string `json:"topic"`
-		BrokerName string `json:"brokerName"`
-		QueueId    int    `json:"queueId"`
-	}{
-		Topic:      mq.Topic,
-		BrokerName: mq.BrokerName,
-		QueueId:    mq.QueueId,
-	}
-	text, err = jsoniter.Marshal(repr)
-	return
-}
-
-func (mq *MessageQueueKey) UnmarshalText(text []byte) error {
-	repr := struct {
-		Topic      string `json:"topic"`
-		BrokerName string `json:"brokerName"`
-		QueueId    int    `json:"queueId"`
-	}{}
-	err := jsoniter.Unmarshal(text, &repr)
-	if err != nil {
-		return err
-	}
-	mq.Topic = repr.Topic
-	mq.QueueId = repr.QueueId
-	mq.BrokerName = repr.BrokerName
-
-	return nil
-}
-
-type localFileOffsetStore struct {
-	group       string
-	path        string
-	OffsetTable *sync.Map // concurrent safe , map[MessageQueueKey]int64
-	// mutex for offset file
-	mutex sync.Mutex
-}
-
-func NewLocalFileOffsetStore(clientID, group string) OffsetStore {
-	store := &localFileOffsetStore{
-		group:       group,
-		path:        filepath.Join(_LocalOffsetStorePath, clientID, group, "offset.json"),
-		OffsetTable: new(sync.Map),
-	}
-	store.load()
-	return store
-}
-
-func (local *localFileOffsetStore) load() {
-	local.mutex.Lock()
-	defer local.mutex.Unlock()
-	data, err := utils.FileReadAll(local.path)
-	if os.IsNotExist(err) {
-		return
-	}
-	if err != nil {
-		rlog.Info("read from local store error, try to use bak file", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-		data, err = utils.FileReadAll(filepath.Join(local.path, ".bak"))
-	}
-	if err != nil {
-		rlog.Info("read from local store bak file error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-		return
-	}
-	datas := make(map[MessageQueueKey]int64)
-
-	wrapper := OffsetSerializeWrapper{
-		OffsetTable: datas,
-	}
-
-	err = jsoniter.Unmarshal(data, &wrapper)
-	if err != nil {
-		rlog.Warning("unmarshal local offset error", map[string]interface{}{
-			"local_path":             local.path,
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		return
-	}
-
-	if datas != nil {
-		for k, v := range datas {
-			local.OffsetTable.Store(k, v)
-		}
-	}
-}
-
-func (local *localFileOffsetStore) read(mq *primitive.MessageQueue, t readType) int64 {
-	switch t {
-	case _ReadFromMemory, _ReadMemoryThenStore:
-		off := readFromMemory(local.OffsetTable, mq)
-		if off >= 0 || (off == -1 && t == _ReadFromMemory) {
-			return off
-		}
-		fallthrough
-	case _ReadFromStore:
-		local.load()
-		return readFromMemory(local.OffsetTable, mq)
-	default:
-
-	}
-	return -1
-}
-
-func (local *localFileOffsetStore) update(mq *primitive.MessageQueue, offset int64, increaseOnly bool) {
-	local.mutex.Lock()
-	defer local.mutex.Unlock()
-	rlog.Debug("update offset", map[string]interface{}{
-		rlog.LogKeyMessageQueue: mq,
-		"new_offset":            offset,
-	})
-	key := MessageQueueKey(*mq)
-	localOffset, exist := local.OffsetTable.Load(key)
-	if !exist {
-		local.OffsetTable.Store(key, offset)
-		return
-	}
-	if increaseOnly {
-		if localOffset.(int64) < offset {
-			local.OffsetTable.Store(key, offset)
-		}
-	} else {
-		local.OffsetTable.Store(key, offset)
-	}
-}
-
-func (local *localFileOffsetStore) persist(mqs []*primitive.MessageQueue) {
-	if len(mqs) == 0 {
-		return
-	}
-	local.mutex.Lock()
-	defer local.mutex.Unlock()
-
-	datas := make(map[MessageQueueKey]int64)
-	local.OffsetTable.Range(func(key, value interface{}) bool {
-		k := key.(MessageQueueKey)
-		v := value.(int64)
-		datas[k] = v
-		return true
-	})
-
-	wrapper := OffsetSerializeWrapper{
-		OffsetTable: datas,
-	}
-	data, _ := jsoniter.Marshal(wrapper)
-	utils.CheckError(fmt.Sprintf("persist offset to %s", local.path), utils.WriteToFile(local.path, data))
-}
-
-func (local *localFileOffsetStore) remove(mq *primitive.MessageQueue) {
-	// nothing to do
-}
-
-type remoteBrokerOffsetStore struct {
-	group       string
-	OffsetTable map[primitive.MessageQueue]int64 `json:"OffsetTable"`
-	client      internal.RMQClient
-	namesrv     internal.Namesrvs
-	mutex       sync.RWMutex
-}
-
-func NewRemoteOffsetStore(group string, client internal.RMQClient, namesrv internal.Namesrvs) OffsetStore {
-	return &remoteBrokerOffsetStore{
-		group:       group,
-		client:      client,
-		namesrv:     namesrv,
-		OffsetTable: make(map[primitive.MessageQueue]int64),
-	}
-}
-
-func (r *remoteBrokerOffsetStore) persist(mqs []*primitive.MessageQueue) {
-	r.mutex.Lock()
-	defer r.mutex.Unlock()
-	if len(mqs) == 0 {
-		return
-	}
-
-	used := make(map[primitive.MessageQueue]struct{}, 0)
-	for _, mq := range mqs {
-		used[*mq] = struct{}{}
-	}
-
-	for mq, off := range r.OffsetTable {
-		if _, ok := used[mq]; !ok {
-			delete(r.OffsetTable, mq)
-			continue
-		}
-		err := r.updateConsumeOffsetToBroker(r.group, mq, off)
-		if err != nil {
-			rlog.Warning("update offset to broker error", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: r.group,
-				rlog.LogKeyMessageQueue:  mq.String(),
-				rlog.LogKeyUnderlayError: err.Error(),
-				"offset":                 off,
-			})
-		} else {
-			rlog.Info("update offset to broker success", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: r.group,
-				rlog.LogKeyMessageQueue:  mq.String(),
-				"offset":                 off,
-			})
-		}
-	}
-}
-
-func (r *remoteBrokerOffsetStore) remove(mq *primitive.MessageQueue) {
-	r.mutex.Lock()
-	defer r.mutex.Unlock()
-
-	delete(r.OffsetTable, *mq)
-	rlog.Warning("delete mq from offset table", map[string]interface{}{
-		rlog.LogKeyConsumerGroup: r.group,
-		rlog.LogKeyMessageQueue:  mq,
-	})
-}
-
-func (r *remoteBrokerOffsetStore) read(mq *primitive.MessageQueue, t readType) int64 {
-	r.mutex.RLock()
-	switch t {
-	case _ReadFromMemory, _ReadMemoryThenStore:
-		off, exist := r.OffsetTable[*mq]
-		if exist {
-			r.mutex.RUnlock()
-			return off
-		}
-		if t == _ReadFromMemory {
-			r.mutex.RUnlock()
-			return -1
-		}
-		fallthrough
-	case _ReadFromStore:
-		off, err := r.fetchConsumeOffsetFromBroker(r.group, mq)
-		if err != nil {
-			rlog.Error("fetch offset of mq from broker error", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: r.group,
-				rlog.LogKeyMessageQueue:  mq.String(),
-				rlog.LogKeyUnderlayError: err,
-			})
-			r.mutex.RUnlock()
-			return -1
-		}
-		rlog.Warning("fetch offset of mq from broker success", map[string]interface{}{
-			rlog.LogKeyConsumerGroup: r.group,
-			rlog.LogKeyMessageQueue:  mq.String(),
-			"offset":                 off,
-		})
-		r.mutex.RUnlock()
-		r.update(mq, off, true)
-		return off
-	default:
-	}
-
-	return -1
-}
-
-func (r *remoteBrokerOffsetStore) update(mq *primitive.MessageQueue, offset int64, increaseOnly bool) {
-	r.mutex.Lock()
-	defer r.mutex.Unlock()
-	localOffset, exist := r.OffsetTable[*mq]
-	if !exist {
-		r.OffsetTable[*mq] = offset
-		return
-	}
-	if increaseOnly {
-		if localOffset < offset {
-			r.OffsetTable[*mq] = offset
-		}
-	} else {
-		r.OffsetTable[*mq] = offset
-	}
-}
-
-func (r *remoteBrokerOffsetStore) fetchConsumeOffsetFromBroker(group string, mq *primitive.MessageQueue) (int64, error) {
-	broker := r.namesrv.FindBrokerAddrByName(mq.BrokerName)
-	if broker == "" {
-		r.namesrv.UpdateTopicRouteInfo(mq.Topic)
-		broker = r.namesrv.FindBrokerAddrByName(mq.BrokerName)
-	}
-	if broker == "" {
-		return int64(-1), fmt.Errorf("broker: %s address not found", mq.BrokerName)
-	}
-	queryOffsetRequest := &internal.QueryConsumerOffsetRequestHeader{
-		ConsumerGroup: group,
-		Topic:         mq.Topic,
-		QueueId:       mq.QueueId,
-	}
-	cmd := remote.NewRemotingCommand(internal.ReqQueryConsumerOffset, queryOffsetRequest, nil)
-	res, err := r.client.InvokeSync(context.Background(), broker, cmd, 3*time.Second)
-	if err != nil {
-		return -1, err
-	}
-	if res.Code != internal.ResSuccess {
-		return -2, fmt.Errorf("broker response code: %d, remarks: %s", res.Code, res.Remark)
-	}
-
-	off, err := strconv.ParseInt(res.ExtFields["offset"], 10, 64)
-
-	if err != nil {
-		return -1, err
-	}
-
-	return off, nil
-}
-
-func (r *remoteBrokerOffsetStore) updateConsumeOffsetToBroker(group string, mq primitive.MessageQueue, off int64) error {
-	broker := r.namesrv.FindBrokerAddrByName(mq.BrokerName)
-	if broker == "" {
-		r.namesrv.UpdateTopicRouteInfo(mq.Topic)
-		broker = r.namesrv.FindBrokerAddrByName(mq.BrokerName)
-	}
-	if broker == "" {
-		return fmt.Errorf("broker: %s address not found", mq.BrokerName)
-	}
-
-	updateOffsetRequest := &internal.UpdateConsumerOffsetRequestHeader{
-		ConsumerGroup: group,
-		Topic:         mq.Topic,
-		QueueId:       mq.QueueId,
-		CommitOffset:  off,
-	}
-	cmd := remote.NewRemotingCommand(internal.ReqUpdateConsumerOffset, updateOffsetRequest, nil)
-	return r.client.InvokeOneWay(context.Background(), broker, cmd, 5*time.Second)
-}
-
-func readFromMemory(table *sync.Map, mq *primitive.MessageQueue) int64 {
-	localOffset, exist := table.Load(MessageQueueKey(*mq))
-	if !exist {
-		return -1
-	}
-
-	return localOffset.(int64)
-}
diff --git a/consumer/offset_store_test.go b/consumer/offset_store_test.go
deleted file mode 100644
index cfa0eaa..0000000
--- a/consumer/offset_store_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"path/filepath"
-	"testing"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/golang/mock/gomock"
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestNewLocalFileOffsetStore(t *testing.T) {
-	Convey("Given some test cases", t, func() {
-		type testCase struct {
-			clientId       string
-			group          string
-			expectedResult *localFileOffsetStore
-		}
-		cases := []testCase{
-			{
-				clientId: "",
-				group:    "testGroup",
-				expectedResult: &localFileOffsetStore{
-					group: "testGroup",
-					path:  filepath.Join(_LocalOffsetStorePath, "/testGroup/offset.json"),
-				},
-			}, {
-				clientId: "192.168.24.1@default",
-				group:    "",
-				expectedResult: &localFileOffsetStore{
-					group: "",
-					path:  filepath.Join(_LocalOffsetStorePath, "/192.168.24.1@default/offset.json"),
-				},
-			}, {
-				clientId: "192.168.24.1@default",
-				group:    "testGroup",
-				expectedResult: &localFileOffsetStore{
-					group: "testGroup",
-					path:  filepath.Join(_LocalOffsetStorePath, "/192.168.24.1@default/testGroup/offset.json"),
-				},
-			},
-		}
-
-		for _, value := range cases {
-			result := NewLocalFileOffsetStore(value.clientId, value.group).(*localFileOffsetStore)
-			value.expectedResult.OffsetTable = result.OffsetTable
-			So(result, ShouldResemble, value.expectedResult)
-		}
-	})
-}
-
-func TestLocalFileOffsetStore(t *testing.T) {
-	Convey("Given a local store with a starting value", t, func() {
-		localStore := NewLocalFileOffsetStore("192.168.24.1@default", "testGroup")
-
-		type offsetCase struct {
-			queue          *primitive.MessageQueue
-			setOffset      int64
-			expectedOffset int64
-		}
-		mq := &primitive.MessageQueue{
-			Topic:      "testTopic",
-			BrokerName: "default",
-			QueueId:    1,
-		}
-
-		Convey("test update", func() {
-			Convey("when increaseOnly is false", func() {
-				cases := []offsetCase{
-					{
-						queue:          mq,
-						setOffset:      3,
-						expectedOffset: 3,
-					}, {
-						queue:          mq,
-						setOffset:      1,
-						expectedOffset: 1,
-					},
-				}
-				for _, value := range cases {
-					localStore.update(value.queue, value.setOffset, false)
-					offset := localStore.read(value.queue, _ReadFromMemory)
-					So(offset, ShouldEqual, value.expectedOffset)
-				}
-			})
-
-			Convey("when increaseOnly is true", func() {
-				localStore.update(mq, 0, false)
-
-				cases := []offsetCase{
-					{
-						queue:          mq,
-						setOffset:      3,
-						expectedOffset: 3,
-					}, {
-						queue:          mq,
-						setOffset:      1,
-						expectedOffset: 3,
-					},
-				}
-				for _, value := range cases {
-					localStore.update(value.queue, value.setOffset, true)
-					offset := localStore.read(value.queue, _ReadFromMemory)
-					So(offset, ShouldEqual, value.expectedOffset)
-				}
-			})
-		})
-
-		Convey("test persist", func() {
-			localStore.update(mq, 1, false)
-			offset := localStore.read(mq, _ReadFromMemory)
-			So(offset, ShouldEqual, 1)
-
-			queues := []*primitive.MessageQueue{mq}
-			localStore.persist(queues)
-			offset = localStore.read(mq, _ReadFromStore)
-			So(offset, ShouldEqual, 1)
-
-			localStore.(*localFileOffsetStore).OffsetTable.Delete(MessageQueueKey(*mq))
-			offset = localStore.read(mq, _ReadMemoryThenStore)
-			So(offset, ShouldEqual, 1)
-		})
-	})
-}
-
-func TestRemoteBrokerOffsetStore(t *testing.T) {
-	Convey("Given a remote store with a starting value", t, func() {
-		ctrl := gomock.NewController(t)
-		defer ctrl.Finish()
-
-		namesrv := internal.NewMockNamesrvs(ctrl)
-
-		rmqClient := internal.NewMockRMQClient(ctrl)
-		remoteStore := NewRemoteOffsetStore("testGroup", rmqClient, namesrv)
-
-		type offsetCase struct {
-			queue          *primitive.MessageQueue
-			setOffset      int64
-			expectedOffset int64
-		}
-		mq := &primitive.MessageQueue{
-			Topic:      "testTopic",
-			BrokerName: "default",
-			QueueId:    1,
-		}
-
-		Convey("test update", func() {
-			Convey("when increaseOnly is false", func() {
-				cases := []offsetCase{
-					{
-						queue:          mq,
-						setOffset:      3,
-						expectedOffset: 3,
-					}, {
-						queue:          mq,
-						setOffset:      1,
-						expectedOffset: 1,
-					},
-				}
-				for _, value := range cases {
-					remoteStore.update(value.queue, value.setOffset, false)
-					offset := remoteStore.read(value.queue, _ReadFromMemory)
-					So(offset, ShouldEqual, value.expectedOffset)
-				}
-			})
-
-			Convey("when increaseOnly is true", func() {
-				remoteStore.update(mq, 0, false)
-
-				cases := []offsetCase{
-					{
-						queue:          mq,
-						setOffset:      3,
-						expectedOffset: 3,
-					}, {
-						queue:          mq,
-						setOffset:      1,
-						expectedOffset: 3,
-					},
-				}
-				for _, value := range cases {
-					remoteStore.update(value.queue, value.setOffset, true)
-					offset := remoteStore.read(value.queue, _ReadFromMemory)
-					So(offset, ShouldEqual, value.expectedOffset)
-				}
-			})
-		})
-
-		Convey("test persist", func() {
-			queues := []*primitive.MessageQueue{mq}
-
-			namesrv.EXPECT().FindBrokerAddrByName(gomock.Any()).Return("192.168.24.1:10911").MaxTimes(2)
-
-			ret := &remote.RemotingCommand{
-				Code: internal.ResSuccess,
-				ExtFields: map[string]string{
-					"offset": "1",
-				},
-			}
-			rmqClient.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(ret, nil).MaxTimes(2)
-
-			remoteStore.persist(queues)
-			offset := remoteStore.read(mq, _ReadFromStore)
-			So(offset, ShouldEqual, 1)
-
-			remoteStore.remove(mq)
-			offset = remoteStore.read(mq, _ReadFromMemory)
-			So(offset, ShouldEqual, -1)
-			offset = remoteStore.read(mq, _ReadMemoryThenStore)
-			So(offset, ShouldEqual, 1)
-
-		})
-
-		Convey("test remove", func() {
-			remoteStore.update(mq, 1, false)
-			offset := remoteStore.read(mq, _ReadFromMemory)
-			So(offset, ShouldEqual, 1)
-
-			remoteStore.remove(mq)
-			offset = remoteStore.read(mq, _ReadFromMemory)
-			So(offset, ShouldEqual, -1)
-		})
-	})
-}
diff --git a/consumer/option.go b/consumer/option.go
deleted file mode 100644
index 330f6c4..0000000
--- a/consumer/option.go
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-type consumerOptions struct {
-	internal.ClientOptions
-
-	/**
-	 * Backtracking consumption time with second precision. Time format is
-	 * 20131223171201<br>
-	 * Implying Seventeen twelve and 01 seconds on December 23, 2013 year<br>
-	 * Default backtracking consumption time Half an hour ago.
-	 */
-	ConsumeTimestamp string
-
-	// The socket timeout in milliseconds
-	ConsumerPullTimeout time.Duration
-
-	// Concurrently max span offset.it has no effect on sequential consumption
-	ConsumeConcurrentlyMaxSpan int
-
-	// Flow control threshold on queue level, each message queue will cache at most 1000 messages by default,
-	// Consider the {PullBatchSize}, the instantaneous value may exceed the limit
-	PullThresholdForQueue int64
-
-	// Limit the cached message size on queue level, each message queue will cache at most 100 MiB messages by default,
-	// Consider the {@code pullBatchSize}, the instantaneous value may exceed the limit
-	//
-	// The size of a message only measured by message body, so it's not accurate
-	PullThresholdSizeForQueue int
-
-	// Flow control threshold on topic level, default value is -1(Unlimited)
-	//
-	// The value of {@code pullThresholdForQueue} will be overwrote and calculated based on
-	// {@code pullThresholdForTopic} if it is't unlimited
-	//
-	// For example, if the value of pullThresholdForTopic is 1000 and 10 message queues are assigned to this consumer,
-	// then pullThresholdForQueue will be set to 100
-	PullThresholdForTopic int
-
-	// Limit the cached message size on topic level, default value is -1 MiB(Unlimited)
-	//
-	// The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated based on
-	// {@code pullThresholdSizeForTopic} if it is't unlimited
-	//
-	// For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10 message queues are
-	// assigned to this consumer, then pullThresholdSizeForQueue will be set to 100 MiB
-	PullThresholdSizeForTopic int
-
-	// Message pull Interval
-	PullInterval time.Duration
-
-	// Batch consumption size
-	ConsumeMessageBatchMaxSize int
-
-	// Batch pull size
-	PullBatchSize int32
-
-	// Whether update subscription relationship when every pull
-	PostSubscriptionWhenPull bool
-
-	// Max re-consume times. -1 means 16 times.
-	//
-	// If messages are re-consumed more than {@link #maxReconsumeTimes} before Success, it's be directed to a deletion
-	// queue waiting.
-	MaxReconsumeTimes int32
-
-	// Suspending pulling time for cases requiring slow pulling like flow-control scenario.
-	SuspendCurrentQueueTimeMillis time.Duration
-
-	// Maximum amount of time a message may block the consuming thread.
-	ConsumeTimeout time.Duration
-
-	ConsumerModel  MessageModel
-	Strategy       AllocateStrategy
-	ConsumeOrderly bool
-	FromWhere      ConsumeFromWhere
-
-	Interceptors []primitive.Interceptor
-	// TODO traceDispatcher
-	MaxTimeConsumeContinuously time.Duration
-	//
-	AutoCommit            bool
-	RebalanceLockInterval time.Duration
-
-	Resolver primitive.NsResolver
-}
-
-func defaultPushConsumerOptions() consumerOptions {
-	opts := consumerOptions{
-		ClientOptions:              internal.DefaultClientOptions(),
-		Strategy:                   AllocateByAveragely,
-		MaxTimeConsumeContinuously: time.Duration(60 * time.Second),
-		RebalanceLockInterval:      20 * time.Second,
-		MaxReconsumeTimes:          -1,
-		ConsumerModel:              Clustering,
-		AutoCommit:                 true,
-		Resolver:                   primitive.NewHttpResolver("DEFAULT"),
-	}
-	opts.ClientOptions.GroupName = "DEFAULT_CONSUMER"
-	return opts
-}
-
-type Option func(*consumerOptions)
-
-func defaultPullConsumerOptions() consumerOptions {
-	opts := consumerOptions{
-		ClientOptions: internal.DefaultClientOptions(),
-		Resolver:      primitive.NewHttpResolver("DEFAULT"),
-	}
-	opts.ClientOptions.GroupName = "DEFAULT_CONSUMER"
-	return opts
-}
-
-func WithConsumerModel(m MessageModel) Option {
-	return func(options *consumerOptions) {
-		options.ConsumerModel = m
-	}
-}
-
-func WithConsumeFromWhere(w ConsumeFromWhere) Option {
-	return func(options *consumerOptions) {
-		options.FromWhere = w
-	}
-}
-
-func WithConsumerOrder(order bool) Option {
-	return func(options *consumerOptions) {
-		options.ConsumeOrderly = order
-	}
-}
-
-func WithConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize int) Option {
-	return func(options *consumerOptions) {
-		options.ConsumeMessageBatchMaxSize = consumeMessageBatchMaxSize
-	}
-}
-
-// WithChainConsumerInterceptor returns a ConsumerOption that specifies the chained interceptor for consumer.
-// The first interceptor will be the outer most, while the last interceptor will be the inner most wrapper
-// around the real call.
-func WithInterceptor(fs ...primitive.Interceptor) Option {
-	return func(options *consumerOptions) {
-		options.Interceptors = append(options.Interceptors, fs...)
-	}
-}
-
-// WithGroupName set group name address
-func WithGroupName(group string) Option {
-	return func(opts *consumerOptions) {
-		if group == "" {
-			return
-		}
-		opts.GroupName = group
-	}
-}
-
-func WithInstance(name string) Option {
-	return func(options *consumerOptions) {
-		options.InstanceName = name
-	}
-}
-
-// WithNamespace set the namespace of consumer
-func WithNamespace(namespace string) Option {
-	return func(opts *consumerOptions) {
-		opts.Namespace = namespace
-	}
-}
-
-func WithVIPChannel(enable bool) Option {
-	return func(opts *consumerOptions) {
-		opts.VIPChannelEnabled = enable
-	}
-}
-
-// WithRetry return a Option that specifies the retry times when send failed.
-// TODO: use retry middleware instead
-func WithRetry(retries int) Option {
-	return func(opts *consumerOptions) {
-		opts.RetryTimes = retries
-	}
-}
-
-func WithCredentials(c primitive.Credentials) Option {
-	return func(options *consumerOptions) {
-		options.ClientOptions.Credentials = c
-	}
-}
-
-// WithMaxReconsumeTimes set MaxReconsumeTimes of options, if message reconsume greater than MaxReconsumeTimes, it will
-// be sent to retry or dlq topic. more info reference by examples/consumer/retry.
-func WithMaxReconsumeTimes(times int32) Option {
-	return func(opts *consumerOptions) {
-		opts.MaxReconsumeTimes = times
-	}
-}
-
-func WithStrategy(strategy AllocateStrategy) Option {
-	return func(opts *consumerOptions) {
-		opts.Strategy = strategy
-	}
-}
-
-func WithPullBatchSize(batchSize int32) Option {
-	return func(options *consumerOptions) {
-		options.PullBatchSize = batchSize
-	}
-}
-
-func WithRebalanceLockInterval(interval time.Duration) Option {
-	return func(options *consumerOptions) {
-		options.RebalanceLockInterval = interval
-	}
-}
-
-func WithAutoCommit(auto bool) Option {
-	return func(options *consumerOptions) {
-		options.AutoCommit = auto
-	}
-}
-
-func WithSuspendCurrentQueueTimeMillis(suspendT time.Duration) Option {
-	return func(options *consumerOptions) {
-		options.SuspendCurrentQueueTimeMillis = suspendT
-	}
-}
-
-func WithPullInterval(interval time.Duration) Option {
-	return func(options *consumerOptions) {
-		options.PullInterval = interval
-	}
-}
-
-// WithNsResolver set nameserver resolver to fetch nameserver addr
-func WithNsResolver(resolver primitive.NsResolver) Option {
-	return func(options *consumerOptions) {
-		options.Resolver = resolver
-	}
-}
-
-// WithNameServer set NameServer address, only support one NameServer cluster in alpha2
-func WithNameServer(nameServers primitive.NamesrvAddr) Option {
-	return func(options *consumerOptions) {
-		options.Resolver = primitive.NewPassthroughResolver(nameServers)
-	}
-}
-
-// WithNameServerDomain set NameServer domain
-func WithNameServerDomain(nameServerUrl string) Option {
-	return func(opts *consumerOptions) {
-		opts.Resolver = primitive.NewHttpResolver("DEFAULT", nameServerUrl)
-	}
-}
diff --git a/consumer/process_queue.go b/consumer/process_queue.go
deleted file mode 100644
index 76a9236..0000000
--- a/consumer/process_queue.go
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"strconv"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/emirpasic/gods/maps/treemap"
-	"github.com/emirpasic/gods/utils"
-	gods_util "github.com/emirpasic/gods/utils"
-	uatomic "go.uber.org/atomic"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-const (
-	_RebalanceLockMaxTime = 30 * time.Second
-	_RebalanceInterval    = 20 * time.Second
-	_PullMaxIdleTime      = 120 * time.Second
-)
-
-type processQueue struct {
-	cachedMsgCount             int64
-	cachedMsgSize              int64
-	tryUnlockTimes             int64
-	queueOffsetMax             int64
-	msgAccCnt                  int64
-	msgCache                   *treemap.Map
-	mutex                      sync.RWMutex
-	consumeLock                sync.Mutex
-	consumingMsgOrderlyTreeMap *treemap.Map
-	dropped                    *uatomic.Bool
-	lastPullTime               atomic.Value
-	lastConsumeTime            atomic.Value
-	locked                     *uatomic.Bool
-	lastLockTime               atomic.Value
-	consuming                  bool
-	lockConsume                sync.Mutex
-	msgCh                      chan []*primitive.MessageExt
-	order                      bool
-}
-
-func newProcessQueue(order bool) *processQueue {
-	consumingMsgOrderlyTreeMap := treemap.NewWith(gods_util.Int64Comparator)
-
-	lastConsumeTime := atomic.Value{}
-	lastConsumeTime.Store(time.Now())
-
-	lastLockTime := atomic.Value{}
-	lastLockTime.Store(time.Now())
-
-	lastPullTime := atomic.Value{}
-	lastPullTime.Store(time.Now())
-
-	pq := &processQueue{
-		msgCache:                   treemap.NewWith(utils.Int64Comparator),
-		lastPullTime:               lastPullTime,
-		lastConsumeTime:            lastConsumeTime,
-		lastLockTime:               lastLockTime,
-		msgCh:                      make(chan []*primitive.MessageExt, 32),
-		consumingMsgOrderlyTreeMap: consumingMsgOrderlyTreeMap,
-		order:                      order,
-		locked:                     uatomic.NewBool(false),
-		dropped:                    uatomic.NewBool(false),
-	}
-	return pq
-}
-
-func (pq *processQueue) putMessage(messages ...*primitive.MessageExt) {
-	if len(messages) == 0 {
-		return
-	}
-	pq.mutex.Lock()
-	if pq.IsDroppd() {
-		pq.mutex.Unlock()
-		return
-	}
-	if !pq.order {
-		pq.msgCh <- messages
-	}
-	validMessageCount := 0
-	for idx := range messages {
-		msg := messages[idx]
-		_, found := pq.msgCache.Get(msg.QueueOffset)
-		if found {
-			continue
-		}
-		_, found = pq.consumingMsgOrderlyTreeMap.Get(msg.QueueOffset)
-		if found {
-			continue
-		}
-		pq.msgCache.Put(msg.QueueOffset, msg)
-		validMessageCount++
-		pq.queueOffsetMax = msg.QueueOffset
-		atomic.AddInt64(&pq.cachedMsgSize, int64(len(msg.Body)))
-	}
-	pq.mutex.Unlock()
-
-	atomic.AddInt64(&pq.cachedMsgCount, int64(validMessageCount))
-
-	if pq.msgCache.Size() > 0 && !pq.consuming {
-		pq.consuming = true
-	}
-
-	msg := messages[len(messages)-1]
-	maxOffset, err := strconv.ParseInt(msg.GetProperty(primitive.PropertyMaxOffset), 10, 64)
-	if err != nil {
-		acc := maxOffset - msg.QueueOffset
-		if acc > 0 {
-			pq.msgAccCnt = acc
-		}
-	}
-}
-
-func (pq *processQueue) WithLock(lock bool) {
-	pq.locked.Store(lock)
-}
-
-func (pq *processQueue) IsLock() bool {
-	return pq.locked.Load()
-}
-
-func (pq *processQueue) WithDropped(dropped bool) {
-	pq.dropped.Store(dropped)
-}
-
-func (pq *processQueue) IsDroppd() bool {
-	return pq.dropped.Load()
-}
-
-func (pq *processQueue) UpdateLastConsumeTime() {
-	pq.lastConsumeTime.Store(time.Now())
-}
-
-func (pq *processQueue) LastConsumeTime() time.Time {
-	return pq.lastConsumeTime.Load().(time.Time)
-}
-
-func (pq *processQueue) UpdateLastLockTime() {
-	pq.lastLockTime.Store(time.Now())
-}
-
-func (pq *processQueue) LastLockTime() time.Time {
-	return pq.lastLockTime.Load().(time.Time)
-}
-
-func (pq *processQueue) LastPullTime() time.Time {
-	return pq.lastPullTime.Load().(time.Time)
-}
-
-func (pq *processQueue) UpdateLastPullTime() {
-	pq.lastPullTime.Store(time.Now())
-}
-
-func (pq *processQueue) makeMessageToCosumeAgain(messages ...*primitive.MessageExt) {
-	pq.mutex.Lock()
-	for _, msg := range messages {
-		pq.consumingMsgOrderlyTreeMap.Remove(msg.QueueOffset)
-		pq.msgCache.Put(msg.QueueOffset, msg)
-	}
-
-	pq.mutex.Unlock()
-}
-
-func (pq *processQueue) removeMessage(messages ...*primitive.MessageExt) int64 {
-	result := int64(-1)
-	pq.mutex.Lock()
-	pq.UpdateLastConsumeTime()
-	if !pq.msgCache.Empty() {
-		result = pq.queueOffsetMax + 1
-		removedCount := 0
-		for idx := range messages {
-			msg := messages[idx]
-			_, found := pq.msgCache.Get(msg.QueueOffset)
-			if !found {
-				continue
-			}
-			pq.msgCache.Remove(msg.QueueOffset)
-			removedCount++
-			atomic.AddInt64(&pq.cachedMsgSize, int64(-len(msg.Body)))
-		}
-		atomic.AddInt64(&pq.cachedMsgCount, int64(-removedCount))
-	}
-	if !pq.msgCache.Empty() {
-		first, _ := pq.msgCache.Min()
-		result = first.(int64)
-	}
-	pq.mutex.Unlock()
-	return result
-}
-
-func (pq *processQueue) isLockExpired() bool {
-	return time.Now().Sub(pq.LastLockTime()) > _RebalanceLockMaxTime
-}
-
-func (pq *processQueue) isPullExpired() bool {
-	return time.Now().Sub(pq.LastPullTime()) > _PullMaxIdleTime
-}
-
-func (pq *processQueue) cleanExpiredMsg(consumer defaultConsumer) {
-	if consumer.option.ConsumeOrderly {
-		return
-	}
-	var loop = 16
-	if pq.msgCache.Size() < 16 {
-		loop = pq.msgCache.Size()
-	}
-
-	for i := 0; i < loop; i++ {
-		pq.mutex.RLock()
-		if pq.msgCache.Empty() {
-			pq.mutex.RLock()
-			return
-		}
-		_, firstValue := pq.msgCache.Min()
-		msg := firstValue.(*primitive.MessageExt)
-		startTime := msg.GetProperty(primitive.PropertyConsumeStartTime)
-		if startTime != "" {
-			st, err := strconv.ParseInt(startTime, 10, 64)
-			if err != nil {
-				rlog.Warning("parse message start consume time error", map[string]interface{}{
-					"time":                   startTime,
-					rlog.LogKeyUnderlayError: err,
-				})
-				continue
-			}
-			if time.Now().Unix()-st <= int64(consumer.option.ConsumeTimeout) {
-				pq.mutex.RLock()
-				return
-			}
-		}
-		pq.mutex.RLock()
-
-		err := consumer.sendBack(msg, 3)
-		if err != nil {
-			rlog.Error("send message back to broker error when clean expired messages", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err,
-			})
-			continue
-		}
-		pq.removeMessage(msg)
-	}
-}
-
-func (pq *processQueue) getMaxSpan() int {
-	pq.mutex.RLock()
-	defer pq.mutex.RUnlock()
-	if pq.msgCache.Size() == 0 {
-		return 0
-	}
-	firstKey, _ := pq.msgCache.Min()
-	lastKey, _ := pq.msgCache.Max()
-	return int(lastKey.(int64) - firstKey.(int64))
-}
-
-func (pq *processQueue) getMessages() []*primitive.MessageExt {
-	return <-pq.msgCh
-}
-
-func (pq *processQueue) takeMessages(number int) []*primitive.MessageExt {
-	for pq.msgCache.Empty() {
-		time.Sleep(10 * time.Millisecond)
-	}
-	result := make([]*primitive.MessageExt, number)
-	i := 0
-	pq.mutex.Lock()
-	for ; i < number; i++ {
-		k, v := pq.msgCache.Min()
-		if v == nil {
-			break
-		}
-		result[i] = v.(*primitive.MessageExt)
-		pq.consumingMsgOrderlyTreeMap.Put(k, v)
-		pq.msgCache.Remove(k)
-	}
-	pq.mutex.Unlock()
-	return result[:i]
-}
-
-func (pq *processQueue) Min() int64 {
-	if pq.msgCache.Empty() {
-		return -1
-	}
-	k, _ := pq.msgCache.Min()
-	if k != nil {
-		return k.(int64)
-	}
-	return -1
-}
-
-func (pq *processQueue) Max() int64 {
-	if pq.msgCache.Empty() {
-		return -1
-	}
-	k, _ := pq.msgCache.Max()
-	if k != nil {
-		return k.(int64)
-	}
-	return -1
-}
-
-func (pq *processQueue) MinOrderlyCache() int64 {
-	if pq.consumingMsgOrderlyTreeMap.Empty() {
-		return -1
-	}
-	k, _ := pq.consumingMsgOrderlyTreeMap.Min()
-	if k != nil {
-		return k.(int64)
-	}
-	return -1
-}
-
-func (pq *processQueue) MaxOrderlyCache() int64 {
-	if pq.consumingMsgOrderlyTreeMap.Empty() {
-		return -1
-	}
-	k, _ := pq.consumingMsgOrderlyTreeMap.Max()
-	if k != nil {
-		return k.(int64)
-	}
-	return -1
-}
-
-func (pq *processQueue) clear() {
-	pq.mutex.Lock()
-	defer pq.mutex.Unlock()
-	pq.msgCache.Clear()
-	pq.cachedMsgCount = 0
-	pq.cachedMsgSize = 0
-	pq.queueOffsetMax = 0
-}
-
-func (pq *processQueue) commit() int64 {
-	pq.mutex.Lock()
-	defer pq.mutex.Unlock()
-
-	var offset int64
-	iter, _ := pq.consumingMsgOrderlyTreeMap.Max()
-	if iter != nil {
-		offset = iter.(int64)
-	}
-	pq.cachedMsgCount -= int64(pq.consumingMsgOrderlyTreeMap.Size())
-	pq.consumingMsgOrderlyTreeMap.Each(func(key interface{}, value interface{}) {
-		msg := value.(*primitive.MessageExt)
-		pq.cachedMsgSize -= int64(len(msg.Body))
-	})
-	pq.consumingMsgOrderlyTreeMap.Clear()
-	return offset + 1
-}
-
-func (pq *processQueue) currentInfo() internal.ProcessQueueInfo {
-	pq.mutex.RLock()
-	defer pq.mutex.RUnlock()
-	info := internal.ProcessQueueInfo{
-		Locked:               pq.locked.Load(),
-		TryUnlockTimes:       pq.tryUnlockTimes,
-		LastLockTimestamp:    pq.LastLockTime().UnixNano() / int64(time.Millisecond),
-		Dropped:              pq.dropped.Load(),
-		LastPullTimestamp:    pq.LastPullTime().UnixNano() / int64(time.Millisecond),
-		LastConsumeTimestamp: pq.LastConsumeTime().UnixNano() / int64(time.Millisecond),
-	}
-
-	if !pq.msgCache.Empty() {
-		info.CachedMsgMinOffset = pq.Min()
-		info.CachedMsgMaxOffset = pq.Max()
-		info.CachedMsgCount = pq.msgCache.Size()
-		info.CachedMsgSizeInMiB = pq.cachedMsgSize / int64(1024*1024)
-	}
-
-	if !pq.consumingMsgOrderlyTreeMap.Empty() {
-		info.TransactionMsgMinOffset = pq.MinOrderlyCache()
-		info.TransactionMsgMaxOffset = pq.MaxOrderlyCache()
-		info.TransactionMsgCount = pq.consumingMsgOrderlyTreeMap.Size()
-	}
-
-	return info
-}
diff --git a/consumer/pull_consumer.go b/consumer/pull_consumer.go
deleted file mode 100644
index 874973b..0000000
--- a/consumer/pull_consumer.go
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"fmt"
-	errors2 "github.com/apache/rocketmq-client-go/v2/errors"
-	"sync"
-	"sync/atomic"
-
-	"github.com/pkg/errors"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type PullConsumer interface {
-	// Start
-	Start()
-
-	// Shutdown refuse all new pull operation, finish all submitted.
-	Shutdown()
-
-	// Pull pull message of topic,  selector indicate which queue to pull.
-	Pull(ctx context.Context, topic string, selector MessageSelector, numbers int) (*primitive.PullResult, error)
-
-	// PullFrom pull messages of queue from the offset to offset + numbers
-	PullFrom(ctx context.Context, queue *primitive.MessageQueue, offset int64, numbers int) (*primitive.PullResult, error)
-
-	// updateOffset update offset of queue in mem
-	UpdateOffset(queue *primitive.MessageQueue, offset int64) error
-
-	// PersistOffset persist all offset in mem.
-	PersistOffset(ctx context.Context) error
-
-	// CurrentOffset return the current offset of queue in mem.
-	CurrentOffset(queue *primitive.MessageQueue) (int64, error)
-}
-
-var (
-	queueCounterTable sync.Map
-)
-
-type defaultPullConsumer struct {
-	*defaultConsumer
-
-	option    consumerOptions
-	client    internal.RMQClient
-	GroupName string
-	Model     MessageModel
-	UnitMode  bool
-
-	interceptor primitive.Interceptor
-}
-
-func NewPullConsumer(options ...Option) (*defaultPullConsumer, error) {
-	defaultOpts := defaultPullConsumerOptions()
-	for _, apply := range options {
-		apply(&defaultOpts)
-	}
-
-	srvs, err := internal.NewNamesrv(defaultOpts.Resolver)
-	if err != nil {
-		return nil, errors.Wrap(err, "new Namesrv failed.")
-	}
-
-	defaultOpts.Namesrv = srvs
-	dc := &defaultConsumer{
-		client:        internal.GetOrNewRocketMQClient(defaultOpts.ClientOptions, nil),
-		consumerGroup: defaultOpts.GroupName,
-		cType:         _PullConsume,
-		state:         int32(internal.StateCreateJust),
-		prCh:          make(chan PullRequest, 4),
-		model:         defaultOpts.ConsumerModel,
-		option:        defaultOpts,
-	}
-	if dc.client == nil {
-		return nil, fmt.Errorf("GetOrNewRocketMQClient faild")
-	}
-	defaultOpts.Namesrv = dc.client.GetNameSrv()
-
-	c := &defaultPullConsumer{
-		defaultConsumer: dc,
-	}
-	return c, nil
-}
-
-func (c *defaultPullConsumer) Start() error {
-	atomic.StoreInt32(&c.state, int32(internal.StateRunning))
-
-	var err error
-	c.once.Do(func() {
-		err = c.start()
-		if err != nil {
-			return
-		}
-	})
-
-	return err
-}
-
-func (c *defaultPullConsumer) Pull(ctx context.Context, topic string, selector MessageSelector, numbers int) (*primitive.PullResult, error) {
-	mq := c.getNextQueueOf(topic)
-	if mq == nil {
-		return nil, fmt.Errorf("prepard to pull topic: %s, but no queue is founded", topic)
-	}
-
-	data := buildSubscriptionData(mq.Topic, selector)
-	result, err := c.pull(context.Background(), mq, data, c.nextOffsetOf(mq), numbers)
-
-	if err != nil {
-		return nil, err
-	}
-
-	c.processPullResult(mq, result, data)
-	return result, nil
-}
-
-func (c *defaultPullConsumer) getNextQueueOf(topic string) *primitive.MessageQueue {
-	queues, err := c.defaultConsumer.client.GetNameSrv().FetchSubscribeMessageQueues(topic)
-	if err != nil && len(queues) > 0 {
-		rlog.Error("get next mq error", map[string]interface{}{
-			rlog.LogKeyTopic:         topic,
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-		return nil
-	}
-	var index int64
-	v, exist := queueCounterTable.Load(topic)
-	if !exist {
-		index = -1
-		queueCounterTable.Store(topic, int64(0))
-	} else {
-		index = v.(int64)
-	}
-
-	return queues[int(atomic.AddInt64(&index, 1))%len(queues)]
-}
-
-// SubscribeWithChan ack manually
-func (c *defaultPullConsumer) SubscribeWithChan(topic, selector MessageSelector) (chan *primitive.Message, error) {
-	return nil, nil
-}
-
-// SubscribeWithFunc ack automatic
-func (c *defaultPullConsumer) SubscribeWithFunc(topic, selector MessageSelector,
-	f func(msg *primitive.Message) ConsumeResult) error {
-	return nil
-}
-
-func (c *defaultPullConsumer) ACK(msg *primitive.Message, result ConsumeResult) {
-
-}
-
-func (dc *defaultConsumer) checkPull(ctx context.Context, mq *primitive.MessageQueue, offset int64, numbers int) error {
-	err := dc.makeSureStateOK()
-	if err != nil {
-		return err
-	}
-
-	if mq == nil {
-		return errors2.ErrMQEmpty
-	}
-
-	if offset < 0 {
-		return errors2.ErrOffset
-	}
-
-	if numbers <= 0 {
-		return errors2.ErrNumbers
-	}
-	return nil
-}
-
-// TODO: add timeout limit
-// TODO: add hook
-func (c *defaultPullConsumer) pull(ctx context.Context, mq *primitive.MessageQueue, data *internal.SubscriptionData,
-	offset int64, numbers int) (*primitive.PullResult, error) {
-
-	if err := c.checkPull(ctx, mq, offset, numbers); err != nil {
-		return nil, err
-	}
-
-	c.subscriptionAutomatically(mq.Topic)
-
-	sysFlag := buildSysFlag(false, true, true, false)
-
-	pullResp, err := c.pullInner(ctx, mq, data, offset, numbers, sysFlag, 0)
-	if err != nil {
-		return nil, err
-	}
-	c.processPullResult(mq, pullResp, data)
-
-	return pullResp, err
-}
-
-func (c *defaultPullConsumer) makeSureStateOK() error {
-	if atomic.LoadInt32(&c.state) != int32(internal.StateRunning) {
-		return fmt.Errorf("the consumer state is [%d], not running", c.state)
-	}
-	return nil
-}
-
-func (c *defaultPullConsumer) nextOffsetOf(queue *primitive.MessageQueue) int64 {
-	return c.computePullFromWhere(queue)
-}
-
-// PullFrom pull messages of queue from the offset to offset + numbers
-func (c *defaultPullConsumer) PullFrom(ctx context.Context, queue *primitive.MessageQueue, offset int64, numbers int) (*primitive.PullResult, error) {
-	if err := c.checkPull(ctx, queue, offset, numbers); err != nil {
-		return nil, err
-	}
-
-	selector := MessageSelector{}
-	data := buildSubscriptionData(queue.Topic, selector)
-
-	return c.pull(ctx, queue, data, offset, numbers)
-}
-
-// updateOffset update offset of queue in mem
-func (c *defaultPullConsumer) UpdateOffset(queue *primitive.MessageQueue, offset int64) error {
-	return c.updateOffset(queue, offset)
-}
-
-// PersistOffset persist all offset in mem.
-func (c *defaultPullConsumer) PersistOffset(ctx context.Context) error {
-	return c.persistConsumerOffset()
-}
-
-// CurrentOffset return the current offset of queue in mem.
-func (c *defaultPullConsumer) CurrentOffset(queue *primitive.MessageQueue) (int64, error) {
-	v := c.queryOffset(queue)
-	return v, nil
-}
-
-// Shutdown close defaultConsumer, refuse new request.
-func (c *defaultPullConsumer) Shutdown() error {
-	return c.defaultConsumer.shutdown()
-}
diff --git a/consumer/pull_consumer_test.go b/consumer/pull_consumer_test.go
deleted file mode 100644
index f7bc454..0000000
--- a/consumer/pull_consumer_test.go
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
diff --git a/consumer/push_consumer.go b/consumer/push_consumer.go
deleted file mode 100644
index 8642aa4..0000000
--- a/consumer/push_consumer.go
+++ /dev/null
@@ -1,1254 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"fmt"
-	errors2 "github.com/apache/rocketmq-client-go/v2/errors"
-	"math"
-	"strconv"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/pkg/errors"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-// In most scenarios, this is the mostly recommended usage to consume messages.
-//
-// Technically speaking, this push client is virtually a wrapper of the underlying pull service. Specifically, on
-// arrival of messages pulled from brokers, it roughly invokes the registered callback handler to feed the messages.
-//
-// See quick start/Consumer in the example module for a typical usage.
-//
-// <strong>Thread Safety:</strong> After initialization, the instance can be regarded as thread-safe.
-
-const (
-	Mb = 1024 * 1024
-)
-
-type PushConsumerCallback struct {
-	topic string
-	f     func(context.Context, ...*primitive.MessageExt) (ConsumeResult, error)
-}
-
-func (callback PushConsumerCallback) UniqueID() string {
-	return callback.topic
-}
-
-type pushConsumer struct {
-	*defaultConsumer
-	queueFlowControlTimes        int
-	queueMaxSpanFlowControlTimes int
-	consumeFunc                  utils.Set
-	submitToConsume              func(*processQueue, *primitive.MessageQueue)
-	subscribedTopic              map[string]string
-	interceptor                  primitive.Interceptor
-	queueLock                    *QueueLock
-	done                         chan struct{}
-	closeOnce                    sync.Once
-}
-
-func NewPushConsumer(opts ...Option) (*pushConsumer, error) {
-	defaultOpts := defaultPushConsumerOptions()
-	for _, apply := range opts {
-		apply(&defaultOpts)
-	}
-	srvs, err := internal.NewNamesrv(defaultOpts.Resolver)
-	if err != nil {
-		return nil, errors.Wrap(err, "new Namesrv failed.")
-	}
-	if !defaultOpts.Credentials.IsEmpty() {
-		srvs.SetCredentials(defaultOpts.Credentials)
-	}
-	defaultOpts.Namesrv = srvs
-
-	if defaultOpts.Namespace != "" {
-		defaultOpts.GroupName = defaultOpts.Namespace + "%" + defaultOpts.GroupName
-	}
-
-	dc := &defaultConsumer{
-		client:         internal.GetOrNewRocketMQClient(defaultOpts.ClientOptions, nil),
-		consumerGroup:  defaultOpts.GroupName,
-		cType:          _PushConsume,
-		state:          int32(internal.StateCreateJust),
-		prCh:           make(chan PullRequest, 4),
-		model:          defaultOpts.ConsumerModel,
-		consumeOrderly: defaultOpts.ConsumeOrderly,
-		fromWhere:      defaultOpts.FromWhere,
-		allocate:       defaultOpts.Strategy,
-		option:         defaultOpts,
-	}
-	if dc.client == nil {
-		return nil, fmt.Errorf("GetOrNewRocketMQClient faild")
-	}
-	defaultOpts.Namesrv = dc.client.GetNameSrv()
-
-	p := &pushConsumer{
-		defaultConsumer: dc,
-		subscribedTopic: make(map[string]string, 0),
-		queueLock:       newQueueLock(),
-		done:            make(chan struct{}, 1),
-		consumeFunc:     utils.NewSet(),
-	}
-	dc.mqChanged = p.messageQueueChanged
-	if p.consumeOrderly {
-		p.submitToConsume = p.consumeMessageOrderly
-	} else {
-		p.submitToConsume = p.consumeMessageCurrently
-	}
-
-	p.interceptor = primitive.ChainInterceptors(p.option.Interceptors...)
-
-	return p, nil
-}
-
-func (pc *pushConsumer) Start() error {
-	var err error
-	pc.once.Do(func() {
-		rlog.Info("the consumer start beginning", map[string]interface{}{
-			rlog.LogKeyConsumerGroup: pc.consumerGroup,
-			"messageModel":           pc.model,
-			"unitMode":               pc.unitMode,
-		})
-		atomic.StoreInt32(&pc.state, int32(internal.StateStartFailed))
-		pc.validate()
-
-		err = pc.client.RegisterConsumer(pc.consumerGroup, pc)
-		if err != nil {
-			rlog.Error("the consumer group has been created, specify another one", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: pc.consumerGroup,
-			})
-			err = errors2.ErrCreated
-			return
-		}
-
-		err = pc.defaultConsumer.start()
-		if err != nil {
-			return
-		}
-
-		go func() {
-			// todo start clean msg expired
-			for {
-				select {
-				case pr := <-pc.prCh:
-					go func() {
-						pc.pullMessage(&pr)
-					}()
-				case <-pc.done:
-					rlog.Info("push consumer close pullConsumer listener.", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: pc.consumerGroup,
-					})
-					return
-				}
-			}
-		}()
-
-		go primitive.WithRecover(func() {
-			// initial lock.
-			if !pc.consumeOrderly {
-				return
-			}
-
-			time.Sleep(1000 * time.Millisecond)
-			pc.lockAll()
-
-			lockTicker := time.NewTicker(pc.option.RebalanceLockInterval)
-			defer lockTicker.Stop()
-			for {
-				select {
-				case <-lockTicker.C:
-					pc.lockAll()
-				case <-pc.done:
-					rlog.Info("push consumer close tick.", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: pc.consumerGroup,
-					})
-					return
-				}
-			}
-		})
-	})
-
-	if err != nil {
-		return err
-	}
-
-	pc.client.UpdateTopicRouteInfo()
-	for k := range pc.subscribedTopic {
-		_, exist := pc.topicSubscribeInfoTable.Load(k)
-		if !exist {
-			pc.client.Shutdown()
-			return fmt.Errorf("the topic=%s route info not found, it may not exist", k)
-		}
-	}
-	pc.client.CheckClientInBroker()
-	pc.client.SendHeartbeatToAllBrokerWithLock()
-	pc.client.RebalanceImmediately()
-
-	return err
-}
-
-func (pc *pushConsumer) Shutdown() error {
-	var err error
-	pc.closeOnce.Do(func() {
-		close(pc.done)
-
-		pc.client.UnregisterConsumer(pc.consumerGroup)
-		err = pc.defaultConsumer.shutdown()
-	})
-
-	return err
-}
-
-func (pc *pushConsumer) Subscribe(topic string, selector MessageSelector,
-	f func(context.Context, ...*primitive.MessageExt) (ConsumeResult, error)) error {
-	if atomic.LoadInt32(&pc.state) == int32(internal.StateStartFailed) ||
-		atomic.LoadInt32(&pc.state) == int32(internal.StateShutdown) {
-		return errors2.ErrStartTopic
-	}
-
-	if pc.option.Namespace != "" {
-		topic = pc.option.Namespace + "%" + topic
-	}
-	data := buildSubscriptionData(topic, selector)
-	pc.subscriptionDataTable.Store(topic, data)
-	pc.subscribedTopic[topic] = ""
-
-	pc.consumeFunc.Add(&PushConsumerCallback{
-		f:     f,
-		topic: topic,
-	})
-	return nil
-}
-
-func (pc *pushConsumer) Unsubscribe(topic string) error {
-	if pc.option.Namespace != "" {
-		topic = pc.option.Namespace + "%" + topic
-	}
-	pc.subscriptionDataTable.Delete(topic)
-	return nil
-}
-
-func (pc *pushConsumer) Rebalance() {
-	pc.defaultConsumer.doBalance()
-}
-
-func (pc *pushConsumer) PersistConsumerOffset() error {
-	return pc.defaultConsumer.persistConsumerOffset()
-}
-
-func (pc *pushConsumer) UpdateTopicSubscribeInfo(topic string, mqs []*primitive.MessageQueue) {
-	pc.defaultConsumer.updateTopicSubscribeInfo(topic, mqs)
-}
-
-func (pc *pushConsumer) IsSubscribeTopicNeedUpdate(topic string) bool {
-	return pc.defaultConsumer.isSubscribeTopicNeedUpdate(topic)
-}
-
-func (pc *pushConsumer) SubscriptionDataList() []*internal.SubscriptionData {
-	return pc.defaultConsumer.SubscriptionDataList()
-}
-
-func (pc *pushConsumer) IsUnitMode() bool {
-	return pc.unitMode
-}
-
-func (pc *pushConsumer) GetcType() string {
-	return string(pc.cType)
-}
-
-func (pc *pushConsumer) GetModel() string {
-	return pc.model.String()
-}
-
-func (pc *pushConsumer) GetWhere() string {
-	switch pc.fromWhere {
-	case ConsumeFromLastOffset:
-		return "CONSUME_FROM_LAST_OFFSET"
-	case ConsumeFromFirstOffset:
-		return "CONSUME_FROM_FIRST_OFFSET"
-	case ConsumeFromTimestamp:
-		return "CONSUME_FROM_TIMESTAMP"
-	default:
-		return "UNKOWN"
-	}
-
-}
-
-func (pc *pushConsumer) ConsumeMessageDirectly(msg *primitive.MessageExt, brokerName string) *internal.ConsumeMessageDirectlyResult {
-	var msgs = []*primitive.MessageExt{msg}
-	var mq = &primitive.MessageQueue{
-		Topic:      msg.Topic,
-		BrokerName: brokerName,
-		QueueId:    msg.Queue.QueueId,
-	}
-
-	beginTime := time.Now()
-	pc.resetRetryAndNamespace(msgs)
-	var result ConsumeResult
-
-	var err error
-	msgCtx := &primitive.ConsumeMessageContext{
-		Properties:    make(map[string]string),
-		ConsumerGroup: pc.consumerGroup,
-		MQ:            mq,
-		Msgs:          msgs,
-	}
-	ctx := context.Background()
-	ctx = primitive.WithConsumerCtx(ctx, msgCtx)
-	ctx = primitive.WithMethod(ctx, primitive.ConsumerPush)
-	concurrentCtx := primitive.NewConsumeConcurrentlyContext()
-	concurrentCtx.MQ = *mq
-	ctx = primitive.WithConcurrentlyCtx(ctx, concurrentCtx)
-
-	result, err = pc.consumeInner(ctx, msgs)
-
-	consumeRT := time.Now().Sub(beginTime)
-
-	res := &internal.ConsumeMessageDirectlyResult{
-		Order:          false,
-		AutoCommit:     true,
-		SpentTimeMills: int64(consumeRT / time.Millisecond),
-	}
-
-	if err != nil {
-		msgCtx.Properties[primitive.PropCtxType] = string(primitive.ExceptionReturn)
-		res.ConsumeResult = internal.ThrowException
-		res.Remark = err.Error()
-	} else if result == ConsumeSuccess {
-		msgCtx.Properties[primitive.PropCtxType] = string(primitive.SuccessReturn)
-		res.ConsumeResult = internal.ConsumeSuccess
-	} else if result == ConsumeRetryLater {
-		msgCtx.Properties[primitive.PropCtxType] = string(primitive.FailedReturn)
-		res.ConsumeResult = internal.ConsumeRetryLater
-	}
-
-	pc.stat.increaseConsumeRT(pc.consumerGroup, mq.Topic, int64(consumeRT/time.Millisecond))
-
-	return res
-}
-
-func (pc *pushConsumer) GetConsumerRunningInfo() *internal.ConsumerRunningInfo {
-	info := internal.NewConsumerRunningInfo()
-
-	pc.subscriptionDataTable.Range(func(key, value interface{}) bool {
-		topic := key.(string)
-		info.SubscriptionData[value.(*internal.SubscriptionData)] = true
-		status := internal.ConsumeStatus{
-			PullRT:            pc.stat.getPullRT(topic, pc.consumerGroup).avgpt,
-			PullTPS:           pc.stat.getPullTPS(topic, pc.consumerGroup).tps,
-			ConsumeRT:         pc.stat.getConsumeRT(topic, pc.consumerGroup).avgpt,
-			ConsumeOKTPS:      pc.stat.getConsumeOKTPS(topic, pc.consumerGroup).tps,
-			ConsumeFailedTPS:  pc.stat.getConsumeFailedTPS(topic, pc.consumerGroup).tps,
-			ConsumeFailedMsgs: pc.stat.topicAndGroupConsumeFailedTPS.getStatsDataInHour(topic + "@" + pc.consumerGroup).sum,
-		}
-		info.StatusTable[topic] = status
-		return true
-	})
-
-	pc.processQueueTable.Range(func(key, value interface{}) bool {
-		mq := key.(primitive.MessageQueue)
-		pq := value.(*processQueue)
-		pInfo := pq.currentInfo()
-		pInfo.CommitOffset = pc.storage.read(&mq, _ReadMemoryThenStore)
-		info.MQTable[mq] = pInfo
-		return true
-	})
-
-	nsAddr := ""
-	for _, value := range pc.client.GetNameSrv().AddrList() {
-		nsAddr += fmt.Sprintf("%s;", value)
-	}
-	info.Properties[internal.PropNameServerAddr] = nsAddr
-	info.Properties[internal.PropConsumeType] = string(pc.cType)
-	info.Properties[internal.PropConsumeOrderly] = strconv.FormatBool(pc.consumeOrderly)
-	info.Properties[internal.PropThreadPoolCoreSize] = "-1"
-	info.Properties[internal.PropConsumerStartTimestamp] = strconv.FormatInt(pc.consumerStartTimestamp, 10)
-	return info
-}
-
-func (pc *pushConsumer) messageQueueChanged(topic string, mqAll, mqDivided []*primitive.MessageQueue) {
-	v, exit := pc.subscriptionDataTable.Load(topic)
-	if !exit {
-		return
-	}
-	data := v.(*internal.SubscriptionData)
-	newVersion := time.Now().UnixNano()
-	rlog.Info("the MessageQueue changed, version also updated", map[string]interface{}{
-		rlog.LogKeyValueChangedFrom: data.SubVersion,
-		rlog.LogKeyValueChangedTo:   newVersion,
-	})
-	data.SubVersion = newVersion
-
-	// TODO: optimize
-	count := 0
-	pc.processQueueTable.Range(func(key, value interface{}) bool {
-		count++
-		return true
-	})
-	if count > 0 {
-		if pc.option.PullThresholdForTopic != -1 {
-			newVal := pc.option.PullThresholdForTopic / count
-			if newVal == 0 {
-				newVal = 1
-			}
-			rlog.Info("The PullThresholdForTopic is changed", map[string]interface{}{
-				rlog.LogKeyValueChangedFrom: pc.option.PullThresholdForTopic,
-				rlog.LogKeyValueChangedTo:   newVal,
-			})
-			pc.option.PullThresholdForTopic = newVal
-		}
-
-		if pc.option.PullThresholdSizeForTopic != -1 {
-			newVal := pc.option.PullThresholdSizeForTopic / count
-			if newVal == 0 {
-				newVal = 1
-			}
-			rlog.Info("The PullThresholdSizeForTopic is changed", map[string]interface{}{
-				rlog.LogKeyValueChangedFrom: pc.option.PullThresholdSizeForTopic,
-				rlog.LogKeyValueChangedTo:   newVal,
-			})
-		}
-	}
-	pc.client.SendHeartbeatToAllBrokerWithLock()
-}
-
-func (pc *pushConsumer) validate() {
-	internal.ValidateGroup(pc.consumerGroup)
-
-	if pc.consumerGroup == internal.DefaultConsumerGroup {
-		// TODO FQA
-		rlog.Error(fmt.Sprintf("consumerGroup can't equal [%s], please specify another one.", internal.DefaultConsumerGroup), nil)
-	}
-
-	if len(pc.subscribedTopic) == 0 {
-		rlog.Error("number of subscribed topics is 0.", nil)
-	}
-
-	if pc.option.ConsumeConcurrentlyMaxSpan < 1 || pc.option.ConsumeConcurrentlyMaxSpan > 65535 {
-		if pc.option.ConsumeConcurrentlyMaxSpan == 0 {
-			pc.option.ConsumeConcurrentlyMaxSpan = 1000
-		} else {
-			rlog.Error("option.ConsumeConcurrentlyMaxSpan out of range [1, 65535]", nil)
-		}
-	}
-
-	if pc.option.PullThresholdForQueue < 1 || pc.option.PullThresholdForQueue > 65535 {
-		if pc.option.PullThresholdForQueue == 0 {
-			pc.option.PullThresholdForQueue = 1024
-		} else {
-			rlog.Error("option.PullThresholdForQueue out of range [1, 65535]", nil)
-		}
-	}
-
-	if pc.option.PullThresholdForTopic < 1 || pc.option.PullThresholdForTopic > 6553500 {
-		if pc.option.PullThresholdForTopic == 0 {
-			pc.option.PullThresholdForTopic = 102400
-		} else {
-			rlog.Error("option.PullThresholdForTopic out of range [1, 6553500]", nil)
-		}
-	}
-
-	if pc.option.PullThresholdSizeForQueue < 1 || pc.option.PullThresholdSizeForQueue > 1024 {
-		if pc.option.PullThresholdSizeForQueue == 0 {
-			pc.option.PullThresholdSizeForQueue = 512
-		} else {
-			rlog.Error("option.PullThresholdSizeForQueue out of range [1, 1024]", nil)
-		}
-	}
-
-	if pc.option.PullThresholdSizeForTopic < 1 || pc.option.PullThresholdSizeForTopic > 102400 {
-		if pc.option.PullThresholdSizeForTopic == 0 {
-			pc.option.PullThresholdSizeForTopic = 51200
-		} else {
-			rlog.Error("option.PullThresholdSizeForTopic out of range [1, 102400]", nil)
-		}
-	}
-
-	if pc.option.PullInterval < 0 || pc.option.PullInterval > 65535*time.Millisecond {
-		rlog.Error("option.PullInterval out of range [0, 65535]", nil)
-	}
-
-	if pc.option.ConsumeMessageBatchMaxSize < 1 || pc.option.ConsumeMessageBatchMaxSize > 1024 {
-		if pc.option.ConsumeMessageBatchMaxSize == 0 {
-			pc.option.ConsumeMessageBatchMaxSize = 1
-		} else {
-			rlog.Error("option.ConsumeMessageBatchMaxSize out of range [1, 1024]", nil)
-		}
-	}
-
-	if pc.option.PullBatchSize < 1 || pc.option.PullBatchSize > 1024 {
-		if pc.option.PullBatchSize == 0 {
-			pc.option.PullBatchSize = 32
-		} else {
-			rlog.Error("option.PullBatchSize out of range [1, 1024]", nil)
-		}
-	}
-}
-
-func (pc *pushConsumer) pullMessage(request *PullRequest) {
-	rlog.Debug("start a new Pull Message task for PullRequest", map[string]interface{}{
-		rlog.LogKeyPullRequest: request.String(),
-	})
-	var sleepTime time.Duration
-	pq := request.pq
-	go primitive.WithRecover(func() {
-		for {
-			select {
-			case <-pc.done:
-				rlog.Info("push consumer close pullMessage.", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: pc.consumerGroup,
-				})
-				return
-			default:
-				pc.submitToConsume(request.pq, request.mq)
-				if request.pq.IsDroppd() {
-					rlog.Info("push consumer quit pullMessage for dropped queue.", map[string]interface{}{
-						rlog.LogKeyConsumerGroup: pc.consumerGroup,
-					})
-					return
-				}
-			}
-		}
-	})
-
-	for {
-	NEXT:
-		select {
-		case <-pc.done:
-			rlog.Info("push consumer close message handle.", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: pc.consumerGroup,
-			})
-			return
-		default:
-		}
-
-		if pq.IsDroppd() {
-			rlog.Debug("the request was dropped, so stop task", map[string]interface{}{
-				rlog.LogKeyPullRequest: request.String(),
-			})
-			return
-		}
-		if sleepTime > 0 {
-			rlog.Debug(fmt.Sprintf("pull MessageQueue: %d sleep %d ms for mq: %v", request.mq.QueueId, sleepTime/time.Millisecond, request.mq), nil)
-			time.Sleep(sleepTime)
-		}
-		// reset time
-		sleepTime = pc.option.PullInterval
-		pq.lastPullTime.Store(time.Now())
-		err := pc.makeSureStateOK()
-		if err != nil {
-			rlog.Warning("consumer state error", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err.Error(),
-			})
-			sleepTime = _PullDelayTimeWhenError
-			goto NEXT
-		}
-
-		if pc.pause {
-			rlog.Debug(fmt.Sprintf("consumer [%s] of [%s] was paused, execute pull request [%s] later",
-				pc.option.InstanceName, pc.consumerGroup, request.String()), nil)
-			sleepTime = _PullDelayTimeWhenSuspend
-			goto NEXT
-		}
-
-		cachedMessageSizeInMiB := int(pq.cachedMsgSize / Mb)
-		if pq.cachedMsgCount > pc.option.PullThresholdForQueue {
-			if pc.queueFlowControlTimes%1000 == 0 {
-				rlog.Warning("the cached message count exceeds the threshold, so do flow control", map[string]interface{}{
-					"PullThresholdForQueue": pc.option.PullThresholdForQueue,
-					"minOffset":             pq.Min(),
-					"maxOffset":             pq.Max(),
-					"count":                 pq.cachedMsgCount,
-					"size(MiB)":             cachedMessageSizeInMiB,
-					"flowControlTimes":      pc.queueFlowControlTimes,
-					rlog.LogKeyPullRequest:  request.String(),
-				})
-			}
-			pc.queueFlowControlTimes++
-			sleepTime = _PullDelayTimeWhenFlowControl
-			goto NEXT
-		}
-
-		if cachedMessageSizeInMiB > pc.option.PullThresholdSizeForQueue {
-			if pc.queueFlowControlTimes%1000 == 0 {
-				rlog.Warning("the cached message size exceeds the threshold, so do flow control", map[string]interface{}{
-					"PullThresholdSizeForQueue": pc.option.PullThresholdSizeForQueue,
-					"minOffset":                 pq.Min(),
-					"maxOffset":                 pq.Max(),
-					"count":                     pq.cachedMsgCount,
-					"size(MiB)":                 cachedMessageSizeInMiB,
-					"flowControlTimes":          pc.queueFlowControlTimes,
-					rlog.LogKeyPullRequest:      request.String(),
-				})
-			}
-			pc.queueFlowControlTimes++
-			sleepTime = _PullDelayTimeWhenFlowControl
-			goto NEXT
-		}
-
-		if !pc.consumeOrderly {
-			if pq.getMaxSpan() > pc.option.ConsumeConcurrentlyMaxSpan {
-				if pc.queueMaxSpanFlowControlTimes%1000 == 0 {
-					rlog.Warning("the queue's messages span too long, so do flow control", map[string]interface{}{
-						"ConsumeConcurrentlyMaxSpan": pc.option.ConsumeConcurrentlyMaxSpan,
-						"minOffset":                  pq.Min(),
-						"maxOffset":                  pq.Max(),
-						"maxSpan":                    pq.getMaxSpan(),
-						"flowControlTimes":           pc.queueFlowControlTimes,
-						rlog.LogKeyPullRequest:       request.String(),
-					})
-				}
-				sleepTime = _PullDelayTimeWhenFlowControl
-				goto NEXT
-			}
-		} else {
-			if pq.IsLock() {
-				if !request.lockedFirst {
-					offset := pc.computePullFromWhere(request.mq)
-					brokerBusy := offset < request.nextOffset
-					rlog.Info("the first time to pull message, so fix offset from broker, offset maybe changed", map[string]interface{}{
-						rlog.LogKeyPullRequest:      request.String(),
-						rlog.LogKeyValueChangedFrom: request.nextOffset,
-						rlog.LogKeyValueChangedTo:   offset,
-						"brokerBusy":                brokerBusy,
-					})
-					if brokerBusy {
-						rlog.Info("[NOTIFY_ME] the first time to pull message, but pull request offset larger than "+
-							"broker consume offset", map[string]interface{}{"offset": offset})
-					}
-					request.lockedFirst = true
-					request.nextOffset = offset
-				}
-			} else {
-				rlog.Info("pull message later because not locked in broker", map[string]interface{}{
-					rlog.LogKeyPullRequest: request.String(),
-				})
-				sleepTime = _PullDelayTimeWhenError
-				goto NEXT
-			}
-		}
-
-		v, exist := pc.subscriptionDataTable.Load(request.mq.Topic)
-		if !exist {
-			rlog.Info("find the consumer's subscription failed", map[string]interface{}{
-				rlog.LogKeyPullRequest: request.String(),
-			})
-			sleepTime = _PullDelayTimeWhenError
-			goto NEXT
-		}
-		beginTime := time.Now()
-		var (
-			commitOffsetEnable bool
-			commitOffsetValue  int64
-			subExpression      string
-		)
-
-		if pc.model == Clustering {
-			commitOffsetValue = pc.storage.read(request.mq, _ReadFromMemory)
-			if commitOffsetValue > 0 {
-				commitOffsetEnable = true
-			}
-		}
-
-		sd := v.(*internal.SubscriptionData)
-		classFilter := sd.ClassFilterMode
-		if pc.option.PostSubscriptionWhenPull && classFilter {
-			subExpression = sd.SubString
-		}
-
-		sysFlag := buildSysFlag(commitOffsetEnable, true, subExpression != "", classFilter)
-
-		pullRequest := &internal.PullMessageRequestHeader{
-			ConsumerGroup:        pc.consumerGroup,
-			Topic:                request.mq.Topic,
-			QueueId:              int32(request.mq.QueueId),
-			QueueOffset:          request.nextOffset,
-			MaxMsgNums:           pc.option.PullBatchSize,
-			SysFlag:              sysFlag,
-			CommitOffset:         commitOffsetValue,
-			SubExpression:        _SubAll,
-			ExpressionType:       string(TAG),
-			SuspendTimeoutMillis: 20 * time.Second,
-		}
-		//
-		//if data.ExpType == string(TAG) {
-		//	pullRequest.SubVersion = 0
-		//} else {
-		//	pullRequest.SubVersion = data.SubVersion
-		//}
-
-		brokerResult := pc.defaultConsumer.tryFindBroker(request.mq)
-		if brokerResult == nil {
-			rlog.Warning("no broker found for mq", map[string]interface{}{
-				rlog.LogKeyPullRequest: request.mq.String(),
-			})
-			sleepTime = _PullDelayTimeWhenError
-			goto NEXT
-		}
-
-		if brokerResult.Slave {
-			pullRequest.SysFlag = clearCommitOffsetFlag(pullRequest.SysFlag)
-		}
-
-		result, err := pc.client.PullMessage(context.Background(), brokerResult.BrokerAddr, pullRequest)
-		if err != nil {
-			rlog.Warning("pull message from broker error", map[string]interface{}{
-				rlog.LogKeyBroker:        brokerResult.BrokerAddr,
-				rlog.LogKeyUnderlayError: err.Error(),
-			})
-			sleepTime = _PullDelayTimeWhenError
-			goto NEXT
-		}
-
-		if result.Status == primitive.PullBrokerTimeout {
-			rlog.Warning("pull broker timeout", map[string]interface{}{
-				rlog.LogKeyBroker: brokerResult.BrokerAddr,
-			})
-			sleepTime = _PullDelayTimeWhenError
-			goto NEXT
-		}
-
-		switch result.Status {
-		case primitive.PullFound:
-			rlog.Debug(fmt.Sprintf("Topic: %s, QueueId: %d found messages.", request.mq.Topic, request.mq.QueueId), nil)
-			prevRequestOffset := request.nextOffset
-			request.nextOffset = result.NextBeginOffset
-
-			rt := time.Now().Sub(beginTime) / time.Millisecond
-			pc.stat.increasePullRT(pc.consumerGroup, request.mq.Topic, int64(rt))
-
-			pc.processPullResult(request.mq, result, sd)
-
-			msgFounded := result.GetMessageExts()
-			firstMsgOffset := int64(math.MaxInt64)
-			if msgFounded != nil && len(msgFounded) != 0 {
-				firstMsgOffset = msgFounded[0].QueueOffset
-				pc.stat.increasePullTPS(pc.consumerGroup, request.mq.Topic, len(msgFounded))
-				pq.putMessage(msgFounded...)
-			}
-			if result.NextBeginOffset < prevRequestOffset || firstMsgOffset < prevRequestOffset {
-				rlog.Warning("[BUG] pull message result maybe data wrong", map[string]interface{}{
-					"nextBeginOffset":   result.NextBeginOffset,
-					"firstMsgOffset":    firstMsgOffset,
-					"prevRequestOffset": prevRequestOffset,
-				})
-			}
-		case primitive.PullNoNewMsg, primitive.PullNoMsgMatched:
-			request.nextOffset = result.NextBeginOffset
-			pc.correctTagsOffset(request)
-		case primitive.PullOffsetIllegal:
-			rlog.Warning("the pull request offset illegal", map[string]interface{}{
-				rlog.LogKeyPullRequest: request.String(),
-				"result":               result.String(),
-			})
-			request.nextOffset = result.NextBeginOffset
-			pq.WithDropped(true)
-			time.Sleep(10 * time.Second)
-			pc.storage.update(request.mq, request.nextOffset, false)
-			pc.storage.persist([]*primitive.MessageQueue{request.mq})
-			pc.processQueueTable.Delete(*request.mq)
-			rlog.Warning(fmt.Sprintf("fix the pull request offset: %s", request.String()), nil)
-		default:
-			rlog.Warning(fmt.Sprintf("unknown pull status: %v", result.Status), nil)
-			sleepTime = _PullDelayTimeWhenError
-		}
-	}
-}
-
-func (pc *pushConsumer) correctTagsOffset(pr *PullRequest) {
-	if pr.pq.cachedMsgCount <= 0 {
-		pc.storage.update(pr.mq, pr.nextOffset, true)
-	}
-}
-
-func (pc *pushConsumer) sendMessageBack(brokerName string, msg *primitive.MessageExt, delayLevel int) bool {
-	var brokerAddr string
-	if len(brokerName) != 0 {
-		brokerAddr = pc.defaultConsumer.client.GetNameSrv().FindBrokerAddrByName(brokerName)
-	} else {
-		brokerAddr = msg.StoreHost
-	}
-	_, err := pc.client.InvokeSync(context.Background(), brokerAddr, pc.buildSendBackRequest(msg, delayLevel), 3*time.Second)
-	if err != nil {
-		return false
-	}
-	return true
-}
-
-func (pc *pushConsumer) buildSendBackRequest(msg *primitive.MessageExt, delayLevel int) *remote.RemotingCommand {
-	req := &internal.ConsumerSendMsgBackRequestHeader{
-		Group:             pc.consumerGroup,
-		OriginTopic:       msg.Topic,
-		Offset:            msg.CommitLogOffset,
-		DelayLevel:        delayLevel,
-		OriginMsgId:       msg.MsgId,
-		MaxReconsumeTimes: pc.getMaxReconsumeTimes(),
-	}
-
-	return remote.NewRemotingCommand(internal.ReqConsumerSendMsgBack, req, msg.Body)
-}
-
-func (pc *pushConsumer) suspend() {
-	pc.pause = true
-	rlog.Info(fmt.Sprintf("suspend consumer: %s", pc.consumerGroup), nil)
-}
-
-func (pc *pushConsumer) resume() {
-	pc.pause = false
-	pc.doBalance()
-	rlog.Info(fmt.Sprintf("resume consumer: %s", pc.consumerGroup), nil)
-}
-
-func (pc *pushConsumer) ResetOffset(topic string, table map[primitive.MessageQueue]int64) {
-	//topic := cmd.ExtFields["topic"]
-	//group := cmd.ExtFields["group"]
-	//if topic == "" || group == "" {
-	//	rlog.Warning("received reset offset command from: %s, but missing params.", from)
-	//	return
-	//}
-	//t, err := strconv.ParseInt(cmd.ExtFields["timestamp"], 10, 64)
-	//if err != nil {
-	//	rlog.Warning("received reset offset command from: %s, but parse time error: %s", err.Error())
-	//	return
-	//}
-	//rlog.Infof("invoke reset offset operation from broker. brokerAddr=%s, topic=%s, group=%s, timestamp=%v",
-	//	from, topic, group, t)
-	//
-	//offsetTable := make(map[MessageQueue]int64, 0)
-	//err = json.Unmarshal(cmd.Body, &offsetTable)
-	//if err != nil {
-	//	rlog.Warning("received reset offset command from: %s, but parse offset table: %s", err.Error())
-	//	return
-	//}
-	//v, exist := c.consumerMap.Load(group)
-	//if !exist {
-	//	rlog.Infof("[reset-offset] consumer dose not exist. group=%s", group)
-	//	return
-	//}
-	pc.suspend()
-	defer pc.resume()
-
-	pc.processQueueTable.Range(func(key, value interface{}) bool {
-		mq := key.(primitive.MessageQueue)
-		pq := value.(*processQueue)
-		if _, ok := table[mq]; ok && mq.Topic == topic {
-			pq.WithDropped(true)
-			pq.clear()
-		}
-		return true
-	})
-	time.Sleep(10 * time.Second)
-	v, exist := pc.topicSubscribeInfoTable.Load(topic)
-	if !exist {
-		return
-	}
-	queuesOfTopic := v.([]*primitive.MessageQueue)
-	for _, k := range queuesOfTopic {
-		if _, ok := table[*k]; ok {
-			pc.storage.update(k, table[*k], false)
-			v, exist := pc.processQueueTable.Load(k)
-			if !exist {
-				continue
-			}
-			pq := v.(*processQueue)
-			pc.removeUnnecessaryMessageQueue(k, pq)
-			pc.processQueueTable.Delete(k)
-		}
-	}
-}
-
-func (pc *pushConsumer) removeUnnecessaryMessageQueue(mq *primitive.MessageQueue, pq *processQueue) bool {
-	pc.defaultConsumer.removeUnnecessaryMessageQueue(mq, pq)
-	if !pc.consumeOrderly || Clustering != pc.model {
-		return true
-	}
-	// TODO orderly
-	return true
-}
-
-func (pc *pushConsumer) consumeInner(ctx context.Context, subMsgs []*primitive.MessageExt) (ConsumeResult, error) {
-	if len(subMsgs) == 0 {
-		return ConsumeRetryLater, errors.New("msg list empty")
-	}
-
-	f, exist := pc.consumeFunc.Contains(subMsgs[0].Topic)
-
-	// fix lost retry message
-	if !exist && strings.HasPrefix(subMsgs[0].Topic, internal.RetryGroupTopicPrefix) {
-		f, exist = pc.consumeFunc.Contains(subMsgs[0].GetProperty(primitive.PropertyRetryTopic))
-	}
-
-	if !exist {
-		return ConsumeRetryLater, fmt.Errorf("the consume callback missing for topic: %s", subMsgs[0].Topic)
-	}
-
-	callback, ok := f.(*PushConsumerCallback)
-	if !ok {
-		return ConsumeRetryLater, fmt.Errorf("the consume callback assert failed for topic: %s", subMsgs[0].Topic)
-	}
-	if pc.interceptor == nil {
-		return callback.f(ctx, subMsgs...)
-	} else {
-		var container ConsumeResultHolder
-		err := pc.interceptor(ctx, subMsgs, &container, func(ctx context.Context, req, reply interface{}) error {
-			msgs := req.([]*primitive.MessageExt)
-			r, e := callback.f(ctx, msgs...)
-
-			realReply := reply.(*ConsumeResultHolder)
-			realReply.ConsumeResult = r
-
-			msgCtx, _ := primitive.GetConsumerCtx(ctx)
-			msgCtx.Success = realReply.ConsumeResult == ConsumeSuccess
-			if realReply.ConsumeResult == ConsumeSuccess {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.SuccessReturn)
-			} else {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.FailedReturn)
-			}
-			return e
-		})
-		return container.ConsumeResult, err
-	}
-}
-
-// resetRetryAndNamespace modify retry message.
-func (pc *pushConsumer) resetRetryAndNamespace(subMsgs []*primitive.MessageExt) {
-	groupTopic := internal.RetryGroupTopicPrefix + pc.consumerGroup
-	beginTime := time.Now()
-	for idx := range subMsgs {
-		msg := subMsgs[idx]
-		retryTopic := msg.GetProperty(primitive.PropertyRetryTopic)
-		if retryTopic == "" && groupTopic == msg.Topic {
-			msg.Topic = retryTopic
-		}
-		subMsgs[idx].WithProperty(primitive.PropertyConsumeStartTime, strconv.FormatInt(
-			beginTime.UnixNano()/int64(time.Millisecond), 10))
-	}
-}
-
-func (pc *pushConsumer) consumeMessageCurrently(pq *processQueue, mq *primitive.MessageQueue) {
-	msgs := pq.getMessages()
-	if msgs == nil {
-		return
-	}
-	for count := 0; count < len(msgs); count++ {
-		var subMsgs []*primitive.MessageExt
-		if count+pc.option.ConsumeMessageBatchMaxSize > len(msgs) {
-			subMsgs = msgs[count:]
-			count = len(msgs)
-		} else {
-			next := count + pc.option.ConsumeMessageBatchMaxSize
-			subMsgs = msgs[count:next]
-			count = next - 1
-		}
-		go primitive.WithRecover(func() {
-		RETRY:
-			if pq.IsDroppd() {
-				rlog.Info("the message queue not be able to consume, because it was dropped", map[string]interface{}{
-					rlog.LogKeyMessageQueue:  mq.String(),
-					rlog.LogKeyConsumerGroup: pc.consumerGroup,
-				})
-				return
-			}
-
-			beginTime := time.Now()
-			pc.resetRetryAndNamespace(subMsgs)
-			var result ConsumeResult
-
-			var err error
-			msgCtx := &primitive.ConsumeMessageContext{
-				Properties:    make(map[string]string),
-				ConsumerGroup: pc.consumerGroup,
-				MQ:            mq,
-				Msgs:          subMsgs,
-			}
-			ctx := context.Background()
-			ctx = primitive.WithConsumerCtx(ctx, msgCtx)
-			ctx = primitive.WithMethod(ctx, primitive.ConsumerPush)
-			concurrentCtx := primitive.NewConsumeConcurrentlyContext()
-			concurrentCtx.MQ = *mq
-			ctx = primitive.WithConcurrentlyCtx(ctx, concurrentCtx)
-
-			result, err = pc.consumeInner(ctx, subMsgs)
-
-			consumeRT := time.Now().Sub(beginTime)
-			if err != nil {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.ExceptionReturn)
-			} else if consumeRT >= pc.option.ConsumeTimeout {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.TimeoutReturn)
-			} else if result == ConsumeSuccess {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.SuccessReturn)
-			} else if result == ConsumeRetryLater {
-				msgCtx.Properties[primitive.PropCtxType] = string(primitive.FailedReturn)
-			}
-
-			pc.stat.increaseConsumeRT(pc.consumerGroup, mq.Topic, int64(consumeRT/time.Millisecond))
-
-			if !pq.IsDroppd() {
-				msgBackFailed := make([]*primitive.MessageExt, 0)
-				if result == ConsumeSuccess {
-					pc.stat.increaseConsumeOKTPS(pc.consumerGroup, mq.Topic, len(subMsgs))
-				} else {
-					pc.stat.increaseConsumeFailedTPS(pc.consumerGroup, mq.Topic, len(subMsgs))
-					if pc.model == BroadCasting {
-						for i := 0; i < len(subMsgs); i++ {
-							rlog.Warning("BROADCASTING, the message consume failed, drop it", map[string]interface{}{
-								"message": subMsgs[i],
-							})
-						}
-					} else {
-						for i := 0; i < len(subMsgs); i++ {
-							msg := subMsgs[i]
-							if !pc.sendMessageBack(mq.BrokerName, msg, concurrentCtx.DelayLevelWhenNextConsume) {
-								msg.ReconsumeTimes += 1
-								msgBackFailed = append(msgBackFailed, msg)
-							}
-						}
-					}
-				}
-
-				offset := pq.removeMessage(subMsgs...)
-
-				if offset >= 0 && !pq.IsDroppd() {
-					pc.storage.update(mq, int64(offset), true)
-				}
-				if len(msgBackFailed) > 0 {
-					subMsgs = msgBackFailed
-					time.Sleep(5 * time.Second)
-					goto RETRY
-				}
-			} else {
-				rlog.Warning("processQueue is dropped without process consume result.", map[string]interface{}{
-					rlog.LogKeyMessageQueue: mq,
-					"message":               subMsgs,
-				})
-			}
-		})
-	}
-}
-
-func (pc *pushConsumer) consumeMessageOrderly(pq *processQueue, mq *primitive.MessageQueue) {
-	if pq.IsDroppd() {
-		rlog.Warning("the message queue not be able to consume, because it's dropped.", map[string]interface{}{
-			rlog.LogKeyMessageQueue: mq.String(),
-		})
-		return
-	}
-
-	lock := pc.queueLock.fetchLock(*mq)
-	lock.Lock()
-	defer lock.Unlock()
-	if pc.model == BroadCasting || (pq.IsLock() && !pq.isLockExpired()) {
-		beginTime := time.Now()
-
-		continueConsume := true
-		for continueConsume {
-			if pq.IsDroppd() {
-				rlog.Warning("the message queue not be able to consume, because it's dropped.", map[string]interface{}{
-					rlog.LogKeyMessageQueue: mq.String(),
-				})
-				break
-			}
-			if pc.model == Clustering {
-				if !pq.IsLock() {
-					rlog.Warning("the message queue not locked, so consume later", map[string]interface{}{
-						rlog.LogKeyMessageQueue: mq.String(),
-					})
-					pc.tryLockLaterAndReconsume(mq, 10)
-					return
-				}
-				if pq.isLockExpired() {
-					rlog.Warning("the message queue lock expired, so consume later", map[string]interface{}{
-						rlog.LogKeyMessageQueue: mq.String(),
-					})
-					pc.tryLockLaterAndReconsume(mq, 10)
-					return
-				}
-			}
-			interval := time.Now().Sub(beginTime)
-			if interval > pc.option.MaxTimeConsumeContinuously {
-				time.Sleep(10 * time.Millisecond)
-				return
-			}
-			batchSize := pc.option.ConsumeMessageBatchMaxSize
-			msgs := pq.takeMessages(batchSize)
-
-			pc.resetRetryAndNamespace(msgs)
-
-			if len(msgs) == 0 {
-				continueConsume = false
-				break
-			}
-
-			// TODO: add message consumer hook
-			beginTime = time.Now()
-
-			ctx := context.Background()
-			msgCtx := &primitive.ConsumeMessageContext{
-				Properties:    make(map[string]string),
-				ConsumerGroup: pc.consumerGroup,
-				MQ:            mq,
-				Msgs:          msgs,
-			}
-			ctx = primitive.WithConsumerCtx(ctx, msgCtx)
-			ctx = primitive.WithMethod(ctx, primitive.ConsumerPush)
-
-			orderlyCtx := primitive.NewConsumeOrderlyContext()
-			orderlyCtx.MQ = *mq
-			ctx = primitive.WithOrderlyCtx(ctx, orderlyCtx)
-
-			pq.lockConsume.Lock()
-			result, _ := pc.consumeInner(ctx, msgs)
-			pq.lockConsume.Unlock()
-
-			if result == Rollback || result == SuspendCurrentQueueAMoment {
-				rlog.Warning("consumeMessage Orderly return not OK", map[string]interface{}{
-					rlog.LogKeyConsumerGroup: pc.consumerGroup,
-					"messages":               msgs,
-					rlog.LogKeyMessageQueue:  mq,
-				})
-			}
-
-			// jsut put consumeResult in consumerMessageCtx
-			//interval = time.Now().Sub(beginTime)
-			//consumeReult := SuccessReturn
-			//if interval > pc.option.ConsumeTimeout {
-			//	consumeReult = TimeoutReturn
-			//} else if SuspendCurrentQueueAMoment == result {
-			//	consumeReult = FailedReturn
-			//} else if ConsumeSuccess == result {
-			//	consumeReult = SuccessReturn
-			//}
-
-			// process result
-			commitOffset := int64(-1)
-			if pc.option.AutoCommit {
-				switch result {
-				case Commit, Rollback:
-					rlog.Warning("the message queue consume result is illegal, we think you want to ack these message: %v", map[string]interface{}{
-						rlog.LogKeyMessageQueue: mq,
-					})
-				case ConsumeSuccess:
-					commitOffset = pq.commit()
-				case SuspendCurrentQueueAMoment:
-					if pc.checkReconsumeTimes(msgs) {
-						pq.makeMessageToCosumeAgain(msgs...)
-						time.Sleep(time.Duration(orderlyCtx.SuspendCurrentQueueTimeMillis) * time.Millisecond)
-						continueConsume = false
-					} else {
-						commitOffset = pq.commit()
-					}
-				default:
-				}
-			} else {
-				switch result {
-				case ConsumeSuccess:
-				case Commit:
-					commitOffset = pq.commit()
-				case Rollback:
-					// pq.rollback
-					time.Sleep(time.Duration(orderlyCtx.SuspendCurrentQueueTimeMillis) * time.Millisecond)
-					continueConsume = false
-				case SuspendCurrentQueueAMoment:
-					if pc.checkReconsumeTimes(msgs) {
-						time.Sleep(time.Duration(orderlyCtx.SuspendCurrentQueueTimeMillis) * time.Millisecond)
-						continueConsume = false
-					}
-				default:
-				}
-			}
-			if commitOffset > 0 && !pq.IsDroppd() {
-				_ = pc.updateOffset(mq, commitOffset)
-			}
-		}
-	} else {
-		if pq.IsDroppd() {
-			rlog.Warning("the message queue not be able to consume, because it's dropped.", map[string]interface{}{
-				rlog.LogKeyMessageQueue: mq.String(),
-			})
-		}
-		pc.tryLockLaterAndReconsume(mq, 100)
-	}
-}
-
-func (pc *pushConsumer) checkReconsumeTimes(msgs []*primitive.MessageExt) bool {
-	suspend := false
-	if len(msgs) != 0 {
-		maxReconsumeTimes := pc.getOrderlyMaxReconsumeTimes()
-		for _, msg := range msgs {
-			if msg.ReconsumeTimes > maxReconsumeTimes {
-				rlog.Warning(fmt.Sprintf("msg will be send to retry topic due to ReconsumeTimes > %d, \n", maxReconsumeTimes), nil)
-				msg.WithProperty("RECONSUME_TIME", strconv.Itoa(int(msg.ReconsumeTimes)))
-				if !pc.sendMessageBack("", msg, -1) {
-					suspend = true
-					msg.ReconsumeTimes += 1
-				}
-			} else {
-				suspend = true
-				msg.ReconsumeTimes += 1
-			}
-		}
-	}
-	return suspend
-}
-
-func (pc *pushConsumer) getOrderlyMaxReconsumeTimes() int32 {
-	if pc.option.MaxReconsumeTimes == -1 {
-		return math.MaxInt32
-	} else {
-		return pc.option.MaxReconsumeTimes
-	}
-}
-
-func (pc *pushConsumer) getMaxReconsumeTimes() int32 {
-	if pc.option.MaxReconsumeTimes == -1 {
-		return 16
-	} else {
-		return pc.option.MaxReconsumeTimes
-	}
-}
-
-func (pc *pushConsumer) tryLockLaterAndReconsume(mq *primitive.MessageQueue, delay int64) {
-	time.Sleep(time.Duration(delay) * time.Millisecond)
-	if pc.lock(mq) == true {
-		pc.submitConsumeRequestLater(10)
-	} else {
-		pc.submitConsumeRequestLater(3000)
-	}
-}
-
-func (pc *pushConsumer) submitConsumeRequestLater(suspendTimeMillis int64) {
-	if suspendTimeMillis == -1 {
-		suspendTimeMillis = int64(pc.option.SuspendCurrentQueueTimeMillis / time.Millisecond)
-	}
-	if suspendTimeMillis < 10 {
-		suspendTimeMillis = 10
-	} else if suspendTimeMillis > 30000 {
-		suspendTimeMillis = 30000
-	}
-	time.Sleep(time.Duration(suspendTimeMillis) * time.Millisecond)
-}
diff --git a/consumer/push_consumer_test.go b/consumer/push_consumer_test.go
deleted file mode 100644
index 78bc1f7..0000000
--- a/consumer/push_consumer_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"testing"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/golang/mock/gomock"
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func mockB4Start(c *pushConsumer) {
-	c.topicSubscribeInfoTable.Store("TopicTest", []*primitive.MessageQueue{})
-}
-
-func TestStart(t *testing.T) {
-	Convey("test Start method", t, func() {
-		c, _ := NewPushConsumer(
-			WithGroupName("testGroup"),
-			WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-			WithConsumerModel(BroadCasting),
-		)
-
-		ctrl := gomock.NewController(t)
-		defer ctrl.Finish()
-
-		client := internal.NewMockRMQClient(ctrl)
-		c.client = client
-
-		err := c.Subscribe("TopicTest", MessageSelector{}, func(ctx context.Context,
-			msgs ...*primitive.MessageExt) (ConsumeResult, error) {
-			rlog.Info("Subscribe Callback", map[string]interface{}{
-				"msgs": msgs,
-			})
-			return ConsumeSuccess, nil
-		})
-
-		_, exists := c.subscriptionDataTable.Load("TopicTest")
-		So(exists, ShouldBeTrue)
-
-		err = c.Unsubscribe("TopicTest")
-		So(err, ShouldBeNil)
-		_, exists = c.subscriptionDataTable.Load("TopicTest")
-		So(exists, ShouldBeFalse)
-
-		err = c.Subscribe("TopicTest", MessageSelector{}, func(ctx context.Context,
-			msgs ...*primitive.MessageExt) (ConsumeResult, error) {
-			rlog.Info("Subscribe Callback", map[string]interface{}{
-				"msgs": msgs,
-			})
-			return ConsumeSuccess, nil
-		})
-
-		_, exists = c.subscriptionDataTable.Load("TopicTest")
-		So(exists, ShouldBeTrue)
-
-		client.EXPECT().ClientID().Return("127.0.0.1@DEFAULT")
-		client.EXPECT().Start().Return()
-		client.EXPECT().RegisterConsumer(gomock.Any(), gomock.Any()).Return(nil)
-		client.EXPECT().UpdateTopicRouteInfo().AnyTimes().Return()
-
-		Convey("test topic route info not found", func() {
-			client.EXPECT().Shutdown().Return()
-			err = c.Start()
-			So(err.Error(), ShouldContainSubstring, "route info not found")
-		})
-
-		Convey("test topic route info found", func() {
-			client.EXPECT().RebalanceImmediately().Return()
-			client.EXPECT().CheckClientInBroker().Return()
-			client.EXPECT().SendHeartbeatToAllBrokerWithLock().Return()
-			mockB4Start(c)
-			err = c.Start()
-			So(err, ShouldBeNil)
-		})
-	})
-}
diff --git a/consumer/statistics.go b/consumer/statistics.go
deleted file mode 100644
index e9d5d79..0000000
--- a/consumer/statistics.go
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"container/list"
-	"fmt"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type StatsManager struct {
-	startOnce                     sync.Once
-	closeOnce                     sync.Once
-	topicAndGroupConsumeOKTPS     *statsItemSet
-	topicAndGroupConsumeRT        *statsItemSet
-	topicAndGroupConsumeFailedTPS *statsItemSet
-	topicAndGroupPullTPS          *statsItemSet
-	topicAndGroupPullRT           *statsItemSet
-}
-
-func NewStatsManager() *StatsManager {
-	mgr := &StatsManager{}
-	mgr.topicAndGroupConsumeOKTPS = newStatsItemSet("CONSUME_OK_TPS")
-	mgr.topicAndGroupConsumeRT = newStatsItemSet("CONSUME_RT")
-	mgr.topicAndGroupConsumeFailedTPS = newStatsItemSet("CONSUME_FAILED_TPS")
-	mgr.topicAndGroupPullTPS = newStatsItemSet("PULL_TPS")
-	mgr.topicAndGroupPullRT = newStatsItemSet("PULL_RT")
-	return mgr
-}
-
-type ConsumeStatus struct {
-	PullRT            float64
-	PullTPS           float64
-	ConsumeRT         float64
-	ConsumeOKTPS      float64
-	ConsumeFailedTPS  float64
-	ConsumeFailedMsgs int64
-}
-
-func (mgr *StatsManager) increasePullRT(group, topic string, rt int64) {
-	mgr.topicAndGroupPullRT.addValue(topic+"@"+group, rt, 1)
-}
-
-func (mgr *StatsManager) increasePullTPS(group, topic string, msgs int) {
-	mgr.topicAndGroupPullTPS.addValue(topic+"@"+group, int64(msgs), 1)
-}
-
-func (mgr *StatsManager) increaseConsumeRT(group, topic string, rt int64) {
-	mgr.topicAndGroupConsumeRT.addValue(topic+"@"+group, rt, 1)
-}
-
-func (mgr *StatsManager) increaseConsumeOKTPS(group, topic string, msgs int) {
-	mgr.topicAndGroupConsumeOKTPS.addValue(topic+"@"+group, int64(msgs), 1)
-}
-
-func (mgr *StatsManager) increaseConsumeFailedTPS(group, topic string, msgs int) {
-	mgr.topicAndGroupConsumeFailedTPS.addValue(topic+"@"+group, int64(msgs), 1)
-}
-
-func (mgr *StatsManager) GetConsumeStatus(group, topic string) ConsumeStatus {
-	cs := ConsumeStatus{}
-	ss := mgr.getPullRT(group, topic)
-	cs.PullTPS = ss.tps
-
-	ss = mgr.getPullTPS(group, topic)
-	cs.PullTPS = ss.tps
-
-	ss = mgr.getConsumeRT(group, topic)
-	cs.ConsumeRT = ss.avgpt
-
-	ss = mgr.getConsumeOKTPS(group, topic)
-	cs.ConsumeOKTPS = ss.tps
-
-	ss = mgr.getConsumeFailedTPS(group, topic)
-
-	cs.ConsumeFailedTPS = ss.tps
-
-	ss = mgr.topicAndGroupConsumeFailedTPS.getStatsDataInHour(topic + "@" + group)
-	cs.ConsumeFailedMsgs = ss.sum
-	return cs
-}
-
-func (mgr *StatsManager) ShutDownStat() {
-	mgr.closeOnce.Do(func() {
-		close(mgr.topicAndGroupConsumeOKTPS.closed)
-		close(mgr.topicAndGroupConsumeRT.closed)
-		close(mgr.topicAndGroupConsumeFailedTPS.closed)
-		close(mgr.topicAndGroupPullTPS.closed)
-		close(mgr.topicAndGroupPullRT.closed)
-	})
-}
-
-func (mgr *StatsManager) getPullRT(group, topic string) statsSnapshot {
-	return mgr.topicAndGroupPullRT.getStatsDataInMinute(topic + "@" + group)
-}
-
-func (mgr *StatsManager) getPullTPS(group, topic string) statsSnapshot {
-	return mgr.topicAndGroupPullTPS.getStatsDataInMinute(topic + "@" + group)
-}
-
-func (mgr *StatsManager) getConsumeRT(group, topic string) statsSnapshot {
-	ss := mgr.topicAndGroupPullRT.getStatsDataInMinute(topic + "@" + group)
-	if ss.sum == 0 {
-		return mgr.topicAndGroupConsumeRT.getStatsDataInHour(topic + "@" + group)
-	}
-	return ss
-}
-
-func (mgr *StatsManager) getConsumeOKTPS(group, topic string) statsSnapshot {
-	return mgr.topicAndGroupConsumeOKTPS.getStatsDataInMinute(topic + "@" + group)
-}
-
-func (mgr *StatsManager) getConsumeFailedTPS(group, topic string) statsSnapshot {
-	return mgr.topicAndGroupConsumeFailedTPS.getStatsDataInMinute(topic + "@" + group)
-}
-
-var csListLock sync.Mutex
-
-func computeStatsData(csList *list.List) statsSnapshot {
-	csListLock.Lock()
-	defer csListLock.Unlock()
-	tps, avgpt, sum := 0.0, 0.0, int64(0)
-	if csList.Len() > 0 {
-		first := csList.Front().Value.(callSnapshot)
-		last := csList.Back().Value.(callSnapshot)
-		sum = last.value - first.value
-		tps = float64(sum*1000.0) / float64(last.timestamp-first.timestamp)
-		timesDiff := last.time - first.time
-		if timesDiff > 0 {
-			avgpt = float64(sum*1.0) / float64(timesDiff)
-		}
-	}
-	return statsSnapshot{
-		tps:   tps,
-		avgpt: avgpt,
-		sum:   sum,
-	}
-}
-
-type statsItemSet struct {
-	statsName      string
-	statsItemTable sync.Map
-	closed         chan struct{}
-}
-
-func newStatsItemSet(statsName string) *statsItemSet {
-	sis := &statsItemSet{
-		statsName: statsName,
-		closed:    make(chan struct{}),
-	}
-	sis.init()
-	return sis
-}
-
-func (sis *statsItemSet) init() {
-	go primitive.WithRecover(func() {
-		ticker := time.NewTicker(10 * time.Second)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.samplingInSeconds()
-			}
-		}
-	})
-
-	go primitive.WithRecover(func() {
-		ticker := time.NewTicker(10 * time.Minute)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.samplingInMinutes()
-			}
-		}
-	})
-
-	go primitive.WithRecover(func() {
-		ticker := time.NewTicker(time.Hour)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.samplingInHour()
-			}
-		}
-	})
-
-	go primitive.WithRecover(func() {
-		time.Sleep(nextMinutesTime().Sub(time.Now()))
-		ticker := time.NewTicker(time.Minute)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.printAtMinutes()
-			}
-		}
-	})
-
-	go primitive.WithRecover(func() {
-		time.Sleep(nextHourTime().Sub(time.Now()))
-		ticker := time.NewTicker(time.Hour)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.printAtHour()
-			}
-		}
-	})
-
-	go primitive.WithRecover(func() {
-		time.Sleep(nextMonthTime().Sub(time.Now()))
-		ticker := time.NewTicker(24 * time.Hour)
-		defer ticker.Stop()
-		for {
-			select {
-			case <-sis.closed:
-				return
-			case <-ticker.C:
-				sis.printAtDay()
-			}
-		}
-	})
-}
-
-func (sis *statsItemSet) samplingInSeconds() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.samplingInSeconds()
-		return true
-	})
-}
-
-func (sis *statsItemSet) samplingInMinutes() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.samplingInMinutes()
-		return true
-	})
-}
-
-func (sis *statsItemSet) samplingInHour() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.samplingInHour()
-		return true
-	})
-}
-
-func (sis *statsItemSet) printAtMinutes() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.printAtMinutes()
-		return true
-	})
-}
-
-func (sis *statsItemSet) printAtHour() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.printAtHour()
-		return true
-	})
-}
-
-func (sis *statsItemSet) printAtDay() {
-	sis.statsItemTable.Range(func(key, value interface{}) bool {
-		si := value.(*statsItem)
-		si.printAtDay()
-		return true
-	})
-}
-
-func (sis *statsItemSet) addValue(key string, incValue, incTimes int64) {
-	si := sis.getAndCreateStateItem(key)
-	atomic.AddInt64(&si.value, incValue)
-	atomic.AddInt64(&si.times, incTimes)
-}
-
-func (sis *statsItemSet) getAndCreateStateItem(key string) *statsItem {
-	if val, ok := sis.statsItemTable.Load(key); ok {
-		return val.(*statsItem)
-	} else {
-		si := newStatsItem(sis.statsName, key)
-		sis.statsItemTable.Store(key, si)
-		return si
-	}
-}
-
-func (sis *statsItemSet) getStatsDataInMinute(key string) statsSnapshot {
-	if val, ok := sis.statsItemTable.Load(key); ok {
-		si := val.(*statsItem)
-		return si.getStatsDataInMinute()
-	}
-	return statsSnapshot{}
-}
-
-func (sis *statsItemSet) getStatsDataInHour(key string) statsSnapshot {
-	if val, ok := sis.statsItemTable.Load(key); ok {
-		si := val.(*statsItem)
-		return si.getStatsDataInHour()
-	}
-	return statsSnapshot{}
-}
-
-func (sis *statsItemSet) getStatsDataInDay(key string) statsSnapshot {
-	if val, ok := sis.statsItemTable.Load(key); ok {
-		si := val.(*statsItem)
-		return si.getStatsDataInDay()
-	}
-	return statsSnapshot{}
-}
-
-func (sis *statsItemSet) getStatsItem(key string) *statsItem {
-	val, _ := sis.statsItemTable.Load(key)
-	return val.(*statsItem)
-}
-
-type statsItem struct {
-	value            int64
-	times            int64
-	csListMinute     *list.List
-	csListHour       *list.List
-	csListDay        *list.List
-	statsName        string
-	statsKey         string
-	csListMinuteLock sync.Mutex
-	csListHourLock   sync.Mutex
-	csListDayLock    sync.Mutex
-}
-
-func (si *statsItem) getStatsDataInMinute() statsSnapshot {
-	return computeStatsData(si.csListMinute)
-}
-
-func (si *statsItem) getStatsDataInHour() statsSnapshot {
-	return computeStatsData(si.csListHour)
-}
-
-func (si *statsItem) getStatsDataInDay() statsSnapshot {
-	return computeStatsData(si.csListDay)
-}
-
-func newStatsItem(statsName, statsKey string) *statsItem {
-	return &statsItem{
-		statsName:    statsName,
-		statsKey:     statsKey,
-		csListMinute: list.New(),
-		csListHour:   list.New(),
-		csListDay:    list.New(),
-	}
-}
-
-func (si *statsItem) samplingInSeconds() {
-	si.csListMinuteLock.Lock()
-	defer si.csListMinuteLock.Unlock()
-	si.csListMinute.PushBack(callSnapshot{
-		timestamp: time.Now().Unix() * 1000,
-		time:      atomic.LoadInt64(&si.times),
-		value:     atomic.LoadInt64(&si.value),
-	})
-	if si.csListMinute.Len() > 7 {
-		si.csListMinute.Remove(si.csListMinute.Front())
-	}
-}
-
-func (si *statsItem) samplingInMinutes() {
-	si.csListHourLock.Lock()
-	defer si.csListHourLock.Unlock()
-	si.csListHour.PushBack(callSnapshot{
-		timestamp: time.Now().Unix() * 1000,
-		time:      atomic.LoadInt64(&si.times),
-		value:     atomic.LoadInt64(&si.value),
-	})
-	if si.csListHour.Len() > 7 {
-		si.csListHour.Remove(si.csListHour.Front())
-	}
-}
-
-func (si *statsItem) samplingInHour() {
-	si.csListDayLock.Lock()
-	defer si.csListDayLock.Unlock()
-	si.csListDay.PushBack(callSnapshot{
-		timestamp: time.Now().Unix() * 1000,
-		time:      atomic.LoadInt64(&si.times),
-		value:     atomic.LoadInt64(&si.value),
-	})
-	if si.csListDay.Len() > 25 {
-		si.csListHour.Remove(si.csListDay.Front())
-	}
-}
-
-func (si *statsItem) printAtMinutes() {
-	ss := computeStatsData(si.csListMinute)
-	rlog.Info("Stats In One Minute, SUM: %d TPS:  AVGPT: %.2f", map[string]interface{}{
-		"statsName": si.statsName,
-		"statsKey":  si.statsKey,
-		"SUM":       ss.sum,
-		"TPS":       fmt.Sprintf("%.2f", ss.tps),
-		"AVGPT":     ss.avgpt,
-	})
-}
-
-func (si *statsItem) printAtHour() {
-	ss := computeStatsData(si.csListHour)
-	rlog.Info("Stats In One Hour, SUM: %d TPS:  AVGPT: %.2f", map[string]interface{}{
-		"statsName": si.statsName,
-		"statsKey":  si.statsKey,
-		"SUM":       ss.sum,
-		"TPS":       fmt.Sprintf("%.2f", ss.tps),
-		"AVGPT":     ss.avgpt,
-	})
-}
-
-func (si *statsItem) printAtDay() {
-	ss := computeStatsData(si.csListDay)
-	rlog.Info("Stats In One Day, SUM: %d TPS:  AVGPT: %.2f", map[string]interface{}{
-		"statsName": si.statsName,
-		"statsKey":  si.statsKey,
-		"SUM":       ss.sum,
-		"TPS":       fmt.Sprintf("%.2f", ss.tps),
-		"AVGPT":     ss.avgpt,
-	})
-}
-
-func nextMinutesTime() time.Time {
-	now := time.Now()
-	m, _ := time.ParseDuration("1m")
-	return now.Add(m)
-}
-
-func nextHourTime() time.Time {
-	now := time.Now()
-	m, _ := time.ParseDuration("1h")
-	return now.Add(m)
-}
-
-func nextMonthTime() time.Time {
-	now := time.Now()
-	return now.AddDate(0, 1, 0)
-}
-
-type callSnapshot struct {
-	timestamp int64
-	time      int64
-	value     int64
-}
-
-type statsSnapshot struct {
-	sum   int64
-	tps   float64
-	avgpt float64
-}
diff --git a/consumer/statistics_test.go b/consumer/statistics_test.go
deleted file mode 100644
index 4836141..0000000
--- a/consumer/statistics_test.go
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"testing"
-	"time"
-)
-
-func almostEqual(a, b float64) bool {
-	diff := abs(a - b)
-	return diff/a < 0.01
-}
-
-func abs(a float64) float64 {
-	if a > 0 {
-		return a
-	}
-	return -a
-}
-
-func TestNextMinuteTime(t *testing.T) {
-	nextMinute := nextMinutesTime()
-	minuteElapse := nextMinute.Sub(time.Now()).Minutes()
-	if !almostEqual(minuteElapse, 1.0) {
-		t.Errorf("wrong next one minute. want=%f, got=%f", 1.0, minuteElapse)
-	}
-}
-
-func TestNextHourTime(t *testing.T) {
-	nextHour := nextHourTime()
-	hourElapse := nextHour.Sub(time.Now()).Hours()
-	if !almostEqual(hourElapse, 1.0) {
-		t.Errorf("wrong next one hour. want=%f, got=%f", 1.0, hourElapse)
-	}
-}
-
-func TestIncreasePullRTGetPullRT(t *testing.T) {
-	mgr := NewStatsManager()
-	mgr.ShutDownStat()
-
-	tests := []struct {
-		RT        int64
-		ExpectSum int64
-	}{
-		{1, 0},
-		{1, 1},
-		{1, 2},
-		{1, 3},
-		{1, 4},
-		{1, 5},
-		{1, 6},
-		{1, 6},
-	}
-	for _, tt := range tests {
-		mgr.increasePullRT("rocketmq", "default", tt.RT)
-		mgr.topicAndGroupPullRT.samplingInSeconds()
-		snapshot := mgr.getPullRT("rocketmq", "default")
-		if snapshot.sum != tt.ExpectSum {
-			t.Errorf("wrong Pull RT sum. want=%d, got=%d", tt.ExpectSum, snapshot.sum)
-		}
-	}
-}
-
-//func TestIncreaseConsumeRTGetConsumeRT(t *testing.T) {
-//	ShutDownStat()
-//	tests := []struct {
-//		RT        int64
-//		ExpectSum int64
-//	}{
-//		{1, 0},
-//		{1, 1},
-//		{1, 2},
-//		{1, 3},
-//		{1, 4},
-//		{1, 5},
-//		{1, 6},
-//		{1, 6},
-//	}
-//	for _, tt := range tests {
-//		increaseConsumeRT("rocketmq", "default", tt.RT)
-//		topicAndGroupConsumeRT.samplingInMinutes()
-//		snapshot := getConsumeRT("rocketmq", "default")
-//		if snapshot.sum != tt.ExpectSum {
-//			t.Errorf("wrong consume RT sum. want=%d, got=%d", tt.ExpectSum, snapshot.sum)
-//		}
-//	}
-//}
-
-func TestIncreasePullTPSGetPullTPS(t *testing.T) {
-	mgr := NewStatsManager()
-	mgr.ShutDownStat()
-	tests := []struct {
-		RT        int
-		ExpectSum int64
-	}{
-		{1, 0},
-		{1, 1},
-		{1, 2},
-		{1, 3},
-		{1, 4},
-		{1, 5},
-		{1, 6},
-		{1, 6},
-	}
-	for _, tt := range tests {
-		mgr.increasePullTPS("rocketmq", "default", tt.RT)
-		mgr.topicAndGroupPullTPS.samplingInSeconds()
-		snapshot := mgr.getPullTPS("rocketmq", "default")
-		if snapshot.sum != tt.ExpectSum {
-			t.Errorf("wrong Pull TPS sum. want=%d, got=%d", tt.ExpectSum, snapshot.sum)
-		}
-	}
-}
-
-func TestIncreaseConsumeOKTPSGetConsumeOKTPS(t *testing.T) {
-	mgr := NewStatsManager()
-	mgr.ShutDownStat()
-	tests := []struct {
-		RT        int
-		ExpectSum int64
-	}{
-		{1, 0},
-		{1, 1},
-		{1, 2},
-		{1, 3},
-		{1, 4},
-		{1, 5},
-		{1, 6},
-		{1, 6},
-	}
-	for _, tt := range tests {
-		mgr.increaseConsumeOKTPS("rocketmq", "default", tt.RT)
-		mgr.topicAndGroupConsumeOKTPS.samplingInSeconds()
-		snapshot := mgr.getConsumeOKTPS("rocketmq", "default")
-		if snapshot.sum != tt.ExpectSum {
-			t.Errorf("wrong Consume OK TPS sum. want=%d, got=%d", tt.ExpectSum, snapshot.sum)
-		}
-	}
-}
-
-func TestIncreaseConsumeFailedTPSGetConsumeFailedTPS(t *testing.T) {
-	mgr := NewStatsManager()
-	mgr.ShutDownStat()
-	tests := []struct {
-		RT        int
-		ExpectSum int64
-	}{
-		{1, 0},
-		{1, 1},
-		{1, 2},
-		{1, 3},
-		{1, 4},
-		{1, 5},
-		{1, 6},
-		{1, 6},
-	}
-	for _, tt := range tests {
-		mgr.increaseConsumeFailedTPS("rocketmq", "default", tt.RT)
-		mgr.topicAndGroupConsumeFailedTPS.samplingInSeconds()
-		snapshot := mgr.getConsumeFailedTPS("rocketmq", "default")
-		if snapshot.sum != tt.ExpectSum {
-			t.Errorf("wrong Consume Failed TPS sum. want=%d, got=%d", tt.ExpectSum, snapshot.sum)
-		}
-	}
-}
-
-func TestGetConsumeStatus(t *testing.T) {
-	mgr := NewStatsManager()
-	mgr.ShutDownStat()
-	group, topic := "rocketmq", "default"
-
-	tests := []struct {
-		RT                int
-		ExpectFailMessage int64
-	}{
-		{1, 0},
-		{1, 1},
-		{1, 2},
-		{1, 3},
-		{1, 4},
-	}
-	for _, tt := range tests {
-		mgr.increasePullRT(group, topic, int64(tt.RT))
-		mgr.increasePullTPS(group, topic, tt.RT)
-		mgr.increaseConsumeRT(group, topic, int64(tt.RT))
-		mgr.increaseConsumeOKTPS(group, topic, tt.RT)
-		mgr.increaseConsumeFailedTPS(group, topic, tt.RT)
-		mgr.topicAndGroupPullRT.samplingInSeconds()
-		mgr.topicAndGroupPullTPS.samplingInSeconds()
-		mgr.topicAndGroupConsumeRT.samplingInMinutes()
-		mgr.topicAndGroupConsumeOKTPS.samplingInSeconds()
-		mgr.topicAndGroupConsumeFailedTPS.samplingInMinutes()
-		status := mgr.GetConsumeStatus(group, topic)
-		if status.ConsumeFailedMsgs != tt.ExpectFailMessage {
-			t.Errorf("wrong ConsumeFailedMsg. want=0, got=%d", status.ConsumeFailedMsgs)
-		}
-	}
-}
diff --git a/consumer/strategy.go b/consumer/strategy.go
deleted file mode 100644
index 4a07928..0000000
--- a/consumer/strategy.go
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"strings"
-
-	"github.com/stathat/consistent"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-// Strategy Algorithm for message allocating between consumers
-// An allocate strategy proxy for based on machine room nearside priority. An actual allocate strategy can be
-// specified.
-//
-// If any consumer is alive in a machine room, the message queue of the broker which is deployed in the same machine
-// should only be allocated to those. Otherwise, those message queues can be shared along all consumers since there are
-// no alive consumer to monopolize them.
-//
-// Average Hashing queue algorithm
-// Cycle average Hashing queue algorithm
-// Use Message QueueID specified
-// Computer room Hashing queue algorithm, such as Alipay logic room
-// Consistent Hashing queue algorithm
-
-type AllocateStrategy func(string, string, []*primitive.MessageQueue, []string) []*primitive.MessageQueue
-
-func AllocateByAveragely(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue,
-	cidAll []string) []*primitive.MessageQueue {
-	if currentCID == "" || len(mqAll) == 0 || len(cidAll) == 0 {
-		return nil
-	}
-
-	var (
-		find  bool
-		index int
-	)
-	for idx := range cidAll {
-		if cidAll[idx] == currentCID {
-			find = true
-			index = idx
-			break
-		}
-	}
-	if !find {
-		rlog.Warning("[BUG] ConsumerId not in cidAll", map[string]interface{}{
-			rlog.LogKeyConsumerGroup: consumerGroup,
-			"consumerId":             currentCID,
-			"cidAll":                 cidAll,
-		})
-		return nil
-	}
-
-	mqSize := len(mqAll)
-	cidSize := len(cidAll)
-	mod := mqSize % cidSize
-
-	var averageSize int
-	if mqSize <= cidSize {
-		averageSize = 1
-	} else {
-		if mod > 0 && index < mod {
-			averageSize = mqSize/cidSize + 1
-		} else {
-			averageSize = mqSize / cidSize
-		}
-	}
-
-	var startIndex int
-	if mod > 0 && index < mod {
-		startIndex = index * averageSize
-	} else {
-		startIndex = index*averageSize + mod
-	}
-
-	num := utils.MinInt(averageSize, mqSize-startIndex)
-	result := make([]*primitive.MessageQueue, 0)
-	for i := 0; i < num; i++ {
-		result = append(result, mqAll[(startIndex+i)%mqSize])
-	}
-	return result
-}
-
-func AllocateByAveragelyCircle(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue,
-	cidAll []string) []*primitive.MessageQueue {
-	if currentCID == "" || len(mqAll) == 0 || len(cidAll) == 0 {
-		return nil
-	}
-
-	var (
-		find  bool
-		index int
-	)
-	for idx := range cidAll {
-		if cidAll[idx] == currentCID {
-			find = true
-			index = idx
-			break
-		}
-	}
-	if !find {
-		rlog.Warning("[BUG] ConsumerId not in cidAll", map[string]interface{}{
-			rlog.LogKeyConsumerGroup: consumerGroup,
-			"consumerId":             currentCID,
-			"cidAll":                 cidAll,
-		})
-		return nil
-	}
-
-	result := make([]*primitive.MessageQueue, 0)
-	for i := index; i < len(mqAll); i++ {
-		if i%len(cidAll) == index {
-			result = append(result, mqAll[i])
-		}
-	}
-	return result
-}
-
-// TODO
-func AllocateByMachineNearby(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue,
-	cidAll []string) []*primitive.MessageQueue {
-	return AllocateByAveragely(consumerGroup, currentCID, mqAll, cidAll)
-}
-
-func AllocateByConfig(list []*primitive.MessageQueue) AllocateStrategy {
-	return func(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue, cidAll []string) []*primitive.MessageQueue {
-		return list
-	}
-}
-
-func AllocateByMachineRoom(consumeridcs []string) AllocateStrategy {
-	return func(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue, cidAll []string) []*primitive.MessageQueue {
-		if currentCID == "" || len(mqAll) == 0 || len(cidAll) == 0 {
-			return nil
-		}
-
-		var (
-			find  bool
-			index int
-		)
-		for idx := range cidAll {
-			if cidAll[idx] == currentCID {
-				find = true
-				index = idx
-				break
-			}
-		}
-		if !find {
-			rlog.Warning("[BUG] ConsumerId not in cidAll", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: consumerGroup,
-				"consumerId":             currentCID,
-				"cidAll":                 cidAll,
-			})
-			return nil
-		}
-
-		var premqAll []*primitive.MessageQueue
-		for _, mq := range mqAll {
-			temp := strings.Split(mq.BrokerName, "@")
-			if len(temp) == 2 {
-				for _, idc := range consumeridcs {
-					if idc == temp[0] {
-						premqAll = append(premqAll, mq)
-					}
-				}
-			}
-		}
-
-		mod := len(premqAll) / len(cidAll)
-		rem := len(premqAll) % len(cidAll)
-		startIndex := mod * index
-		endIndex := startIndex + mod
-
-		result := make([]*primitive.MessageQueue, 0)
-		for i := startIndex; i < endIndex; i++ {
-			result = append(result, mqAll[i])
-		}
-		if rem > index {
-			result = append(result, premqAll[index+mod*len(cidAll)])
-		}
-		return result
-	}
-}
-
-func AllocateByConsistentHash(virtualNodeCnt int) AllocateStrategy {
-	return func(consumerGroup, currentCID string, mqAll []*primitive.MessageQueue, cidAll []string) []*primitive.MessageQueue {
-		if currentCID == "" || len(mqAll) == 0 || len(cidAll) == 0 {
-			return nil
-		}
-
-		var (
-			find bool
-		)
-		for idx := range cidAll {
-			if cidAll[idx] == currentCID {
-				find = true
-				break
-			}
-		}
-		if !find {
-			rlog.Warning("[BUG] ConsumerId not in cidAll", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: consumerGroup,
-				"consumerId":             currentCID,
-				"cidAll":                 cidAll,
-			})
-			return nil
-		}
-
-		c := consistent.New()
-		c.NumberOfReplicas = virtualNodeCnt
-		for _, cid := range cidAll {
-			c.Add(cid)
-		}
-
-		result := make([]*primitive.MessageQueue, 0)
-		for _, mq := range mqAll {
-			clientNode, err := c.Get(mq.String())
-			if err != nil {
-				rlog.Warning("[BUG] AllocateByConsistentHash err: %s", map[string]interface{}{
-					rlog.LogKeyUnderlayError: err,
-				})
-			}
-			if currentCID == clientNode {
-				result = append(result, mq)
-			}
-		}
-		return result
-	}
-}
diff --git a/consumer/strategy_test.go b/consumer/strategy_test.go
deleted file mode 100644
index d521b4b..0000000
--- a/consumer/strategy_test.go
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package consumer
-
-import (
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"testing"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestAllocateByAveragely(t *testing.T) {
-	Convey("Given message queues with a starting value", t, func() {
-		queues := []*primitive.MessageQueue{
-			{
-				QueueId: 0,
-			},
-			{
-				QueueId: 1,
-			},
-			{
-				QueueId: 2,
-			},
-			{
-				QueueId: 3,
-			},
-			{
-				QueueId: 4,
-			},
-			{
-				QueueId: 5,
-			},
-		}
-
-		Convey("When params is empty", func() {
-			result := AllocateByAveragely("testGroup", "", queues, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = AllocateByAveragely("testGroup", "192.168.24.1@default", nil, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = AllocateByAveragely("testGroup", "192.168.24.1@default", queues, nil)
-			So(result, ShouldBeNil)
-		})
-
-		type testCase struct {
-			currentCid    string
-			mqAll         []*primitive.MessageQueue
-			cidAll        []string
-			expectedQueue []*primitive.MessageQueue
-		}
-		cases := []testCase{
-			{
-				currentCid: "192.168.24.1@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 0,
-					},
-					{
-						QueueId: 1,
-					},
-					{
-						QueueId: 2,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 2,
-					},
-					{
-						QueueId: 3,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 2,
-					},
-					{
-						QueueId: 3,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.4@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 5,
-					},
-				},
-			},
-			{
-				currentCid:    "192.168.24.7@default",
-				mqAll:         queues,
-				cidAll:        []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default", "192.168.24.5@default", "192.168.24.6@default", "192.168.24.7@default"},
-				expectedQueue: []*primitive.MessageQueue{},
-			},
-		}
-
-		Convey("the result of AllocateByAveragely should be deep equal expectedQueue", func() {
-			for _, value := range cases {
-				result := AllocateByAveragely("testGroup", value.currentCid, value.mqAll, value.cidAll)
-				So(result, ShouldResemble, value.expectedQueue)
-			}
-		})
-	})
-}
-
-func TestAllocateByAveragelyCircle(t *testing.T) {
-	Convey("Given message queues with a starting value", t, func() {
-		queues := []*primitive.MessageQueue{
-			{
-				QueueId: 0,
-			},
-			{
-				QueueId: 1,
-			},
-			{
-				QueueId: 2,
-			},
-			{
-				QueueId: 3,
-			},
-			{
-				QueueId: 4,
-			},
-			{
-				QueueId: 5,
-			},
-		}
-
-		Convey("When params is empty", func() {
-			result := AllocateByAveragelyCircle("testGroup", "", queues, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = AllocateByAveragelyCircle("testGroup", "192.168.24.1@default", nil, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = AllocateByAveragelyCircle("testGroup", "192.168.24.1@default", queues, nil)
-			So(result, ShouldBeNil)
-		})
-
-		type testCase struct {
-			currentCid    string
-			mqAll         []*primitive.MessageQueue
-			cidAll        []string
-			expectedQueue []*primitive.MessageQueue
-		}
-		cases := []testCase{
-			{
-				currentCid: "192.168.24.1@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 0,
-					},
-					{
-						QueueId: 2,
-					},
-					{
-						QueueId: 4,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 1,
-					},
-					{
-						QueueId: 4,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 1,
-					},
-					{
-						QueueId: 5,
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.4@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId: 3,
-					},
-				},
-			},
-			{
-				currentCid:    "192.168.24.7@default",
-				mqAll:         queues,
-				cidAll:        []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default", "192.168.24.5@default", "192.168.24.6@default", "192.168.24.7@default"},
-				expectedQueue: []*primitive.MessageQueue{},
-			},
-		}
-
-		Convey("the result of AllocateByAveragelyCircle should be deep equal expectedQueue", func() {
-			for _, value := range cases {
-				result := AllocateByAveragelyCircle("testGroup", value.currentCid, value.mqAll, value.cidAll)
-				So(result, ShouldResemble, value.expectedQueue)
-			}
-		})
-	})
-}
-
-func TestAllocateByConfig(t *testing.T) {
-	Convey("Given message queues with a starting value", t, func() {
-		queues := []*primitive.MessageQueue{
-			{
-				QueueId: 0,
-			},
-			{
-				QueueId: 1,
-			},
-			{
-				QueueId: 2,
-			},
-			{
-				QueueId: 3,
-			},
-			{
-				QueueId: 4,
-			},
-			{
-				QueueId: 5,
-			},
-		}
-
-		strategy := AllocateByConfig(queues)
-		result := strategy("testGroup", "192.168.24.1@default", queues, []string{"192.168.24.1@default", "192.168.24.2@default"})
-		So(result, ShouldResemble, queues)
-	})
-}
-
-func TestAllocateByMachineRoom(t *testing.T) {
-	Convey("Given some consumer IDCs with a starting value", t, func() {
-		idcs := []string{"192.168.24.1", "192.168.24.2"}
-		strategy := AllocateByMachineRoom(idcs)
-
-		queues := []*primitive.MessageQueue{
-			{
-				QueueId:    0,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    1,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    2,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    3,
-				BrokerName: "192.168.24.2@defaultName",
-			},
-			{
-				QueueId:    4,
-				BrokerName: "192.168.24.2@defaultName",
-			},
-			{
-				QueueId:    5,
-				BrokerName: "192.168.24.3@defaultName",
-			},
-		}
-
-		Convey("When params is empty", func() {
-			result := strategy("testGroup", "", queues, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = strategy("testGroup", "192.168.24.1@default", nil, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = strategy("testGroup", "192.168.24.1@default", queues, nil)
-			So(result, ShouldBeNil)
-		})
-
-		type testCase struct {
-			currentCid    string
-			mqAll         []*primitive.MessageQueue
-			cidAll        []string
-			expectedQueue []*primitive.MessageQueue
-		}
-		cases := []testCase{
-			{
-				currentCid: "192.168.24.1@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId:    0,
-						BrokerName: "192.168.24.1@defaultName",
-					},
-					{
-						QueueId:    1,
-						BrokerName: "192.168.24.1@defaultName",
-					},
-					{
-						QueueId:    4,
-						BrokerName: "192.168.24.2@defaultName",
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId:    1,
-						BrokerName: "192.168.24.1@defaultName",
-					},
-					{
-						QueueId:    4,
-						BrokerName: "192.168.24.2@defaultName",
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId:    1,
-						BrokerName: "192.168.24.1@defaultName",
-					},
-				},
-			},
-			{
-				currentCid: "192.168.24.4@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default"},
-				expectedQueue: []*primitive.MessageQueue{
-					{
-						QueueId:    3,
-						BrokerName: "192.168.24.2@defaultName",
-					},
-				},
-			},
-			{
-				currentCid:    "192.168.24.7@default",
-				mqAll:         queues,
-				cidAll:        []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default", "192.168.24.4@default", "192.168.24.5@default", "192.168.24.6@default", "192.168.24.7@default"},
-				expectedQueue: []*primitive.MessageQueue{},
-			},
-		}
-
-		Convey("the result of AllocateByMachineRoom should be deep equal expectedQueue", func() {
-			for _, value := range cases {
-				result := strategy("testGroup", value.currentCid, value.mqAll, value.cidAll)
-				So(result, ShouldResemble, value.expectedQueue)
-			}
-		})
-	})
-}
-
-func TestAllocateByConsistentHash(t *testing.T) {
-	Convey("Given virtualNodeCnt with a starting value", t, func() {
-		virtualNodeCnt := 10
-		strategy := AllocateByConsistentHash(virtualNodeCnt)
-
-		queues := []*primitive.MessageQueue{
-			{
-				QueueId:    0,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    1,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    2,
-				BrokerName: "192.168.24.1@defaultName",
-			},
-			{
-				QueueId:    3,
-				BrokerName: "192.168.24.2@defaultName",
-			},
-			{
-				QueueId:    4,
-				BrokerName: "192.168.24.2@defaultName",
-			},
-			{
-				QueueId:    5,
-				BrokerName: "192.168.24.3@defaultName",
-			},
-		}
-
-		Convey("When params is empty", func() {
-			result := strategy("testGroup", "", queues, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = strategy("testGroup", "192.168.24.1@default", nil, []string{"192.168.24.1@default"})
-			So(result, ShouldBeNil)
-
-			result = strategy("testGroup", "192.168.24.1@default", queues, nil)
-			So(result, ShouldBeNil)
-		})
-
-		type testCase struct {
-			currentCid string
-			mqAll      []*primitive.MessageQueue
-			cidAll     []string
-		}
-		cases := []testCase{
-			{
-				currentCid: "192.168.24.1@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-			},
-			{
-				currentCid: "192.168.24.3@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default", "192.168.24.3@default"},
-			},
-			{
-				currentCid: "192.168.24.1@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default"},
-			},
-			{
-				currentCid: "192.168.24.2@default",
-				mqAll:      queues,
-				cidAll:     []string{"192.168.24.1@default", "192.168.24.2@default"},
-			},
-		}
-
-		Convey("observe the result of AllocateByMachineRoom", func() {
-			for _, value := range cases {
-				result := strategy("testGroup", value.currentCid, value.mqAll, value.cidAll)
-				rlog.Info("Result Of AllocateByMachineRoom", map[string]interface{}{
-					"currentCid": value.currentCid,
-					"cidAll": value.cidAll,
-					"allocateResult": result,
-				})
-			}
-		})
-	})
-}
diff --git a/docs/Introduction.md b/docs/Introduction.md
deleted file mode 100644
index 011603a..0000000
--- a/docs/Introduction.md
+++ /dev/null
@@ -1,130 +0,0 @@
-## How to use
-
-### go mod
-```
-require (
-    github.com/apache/rocketmq-client-go/v2 v2.1.0-rc3
-)
-```
-
-### Set Logger
-Go Client define the `Logger` interface for log output, user can specify implementation of private.
-in default, client use `logrus`.
-```
-rlog.SetLogger(Logger)
-```
-
-### Send message
-#### Interface
-```
-Producer interface {
-	Start() error
-	Shutdown() error
-	SendSync(context.Context, *primitive.Message) (*internal.SendResult, error)
-	SendOneWay(context.Context, *primitive.Message) error
-}
-```
-
-#### Examples
-- create a new `Producer` instance
-```
-p, err := rocketmq.NewProducer(
-		producer.WithNameServer(endPoint),
-		//producer.WithNsResolver(primitive.NewPassthroughResolver(endPoint)),
-		producer.WithRetry(2),
-		producer.WithGroupName("GID_xxxxxx"),
-	)
-```
-
-- start the producer
-```go 
-err := p.Start()
-```
-
-- send message with sync
-```
-result, err := p.SendSync(context.Background(), &primitive.Message{
-    Topic: "test",
-    Body:  []byte("Hello RocketMQ Go Client!"),
-})
-
-// do something with result
-```
-
-- or send message with oneway
-```
-err := p.SendOneWay(context.Background(), &primitive.Message{
-    Topic: "test",
-    Body:  []byte("Hello RocketMQ Go Client!"),
-})
-```
-Full examples: [producer](../examples/producer)
-
-### Consume Message
-now only support `PushConsumer`
-
-#### Interface
-```
-PushConsumer interface {
-	// Start the PullConsumer for consuming message
-	Start() error
-
-	// Shutdown the PullConsumer, all offset of MessageQueue will be sync to broker before process exit
-	Shutdown() error
-	// Subscribe a topic for consuming
-	Subscribe(topic string, selector consumer.MessageSelector,
-		f func(context.Context, ...*primitive.MessageExt) (consumer.ConsumeResult, error)) error
-}
-```
-
-#### Usage
-- Create a `PushConsumer` instance
-```
-c, err := rocketmq.NewPushConsumer(
-		consumer.WithNameServer(endPoint),
-        consumer.WithConsumerModel(consumer.Clustering),
-		consumer.WithGroupName("GID_XXXXXX"),
-	)
-```
-
-- Subscribe a topic(only support one topic now), and define your consuming function
-```
-err := c.Subscribe("test", consumer.MessageSelector{}, func(ctx *consumer.ConsumeMessageContext,
-    msgs []*primitive.MessageExt) (consumer.ConsumeResult, error) {
-    rlog.Info("Subscribe Callback", map[string]interface{}{
-        "msgs": msgs,
-    })
-    return consumer.ConsumeSuccess, nil
-})
-```
-- start the consumer(**NOTE: MUST after subscribe**)
-```
-err = c.Start()
-```
-
-Full examples: [consumer](../examples/consumer)
-
-
-### Admin: Topic Operation
-
-#### Examples
-- create topic
-```
-testAdmin, err := admin.NewAdmin(admin.WithResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})))
-err = testAdmin.CreateTopic(
-	context.Background(),
-	admin.WithTopicCreate("newTopic"),
-	admin.WithBrokerAddrCreate("127.0.0.1:10911"),
-)
-```
-
-- delete topic
-`ClusterName` not supported yet
-```
-err = testAdmin.DeleteTopic(
-	context.Background(),
-	admin.WithTopicDelete("newTopic"),
-	//admin.WithBrokerAddrDelete("127.0.0.1:10911"),	//optional
-	//admin.WithNameSrvAddr(nameSrvAddr),				//optional
-)
-```
\ No newline at end of file
diff --git a/docs/client-design.gliffy b/docs/client-design.gliffy
deleted file mode 100644
index 418f4d8..0000000
--- a/docs/client-design.gliffy
+++ /dev/null
@@ -1 +0,0 @@
-{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":31,"y":44,"rotation":0,"id":57,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":27,"lockAspectRatio":false,"lockShape":false,"order":57,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 24px; font-family: Arial; color: rgb(106, 168, 79); white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 27px;\">Architecture</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":0,"y":10,"rotation":0,"id":51,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":710,"height":360,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":1,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[],"linkMap":[]},{"x":420,"y":187,"rotation":0,"id":44,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":25,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":1,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-3,-2],[37,-2]],"lockSegments":{}}},"children":[],"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":11,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":13,"px":0,"py":0.5}}},"linkMap":[]},{"x":104,"y":171,"rotation":0,"id":42,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":28,"lockAspectRatio":false,"lockShape":false,"order":24,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">1. API wrapper\n</span></p><p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">2. connections manager</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":451,"y":61,"rotation":0,"id":37,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":23,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">3. offset storage</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":433,"y":46,"rotation":0,"id":36,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":22,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">2. balance</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":471,"y":30,"rotation":0,"id":35,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":180,"height":14,"lockAspectRatio":false,"lockShape":false,"order":21,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">1. push/pull(push based pull)</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":252,"y":61,"rotation":0,"id":28,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":20,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">2. muti-producers</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":251,"y":42,"rotation":0,"id":27,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":19,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">1. queue selector</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":154,"y":272,"rotation":0,"id":21,"uid":"com.gliffy.shape.uml.uml_v1.default.message","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":18,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[278,-52],[278,-45.33333333333334],[278,-38.66666666666666],[278,-32]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":7,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":0,"px":0.5,"py":0}}},"linkMap":[]},{"x":154,"y":272,"rotation":0,"id":20,"uid":"com.gliffy.shape.uml.uml_v1.default.message","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":17,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[388,-152],[388,-137],[352.5584412271571,-137],[352.5584412271571,-122]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":17,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":7,"px":0.7071067811865476,"py":0}}},"linkMap":[]},{"x":144,"y":262,"rotation":0,"id":19,"uid":"com.gliffy.shape.uml.uml_v1.default.message","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":16,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[183,-142],[183,-127],[213.44155877284288,-127],[213.44155877284288,-112]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":15,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":7,"px":0.2928932188134524,"py":0}}},"linkMap":[]},{"x":472,"y":80,"rotation":0,"id":17,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":140,"height":40,"lockAspectRatio":false,"lockShape":false,"order":14,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":1.9999999999999998,"y":0,"rotation":0,"id":18,"uid":null,"width":135.99999999999997,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">consumer</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":252,"y":80,"rotation":0,"id":15,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":150,"height":40,"lockAspectRatio":false,"lockShape":false,"order":12,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.142857142857143,"y":0,"rotation":0,"id":16,"uid":null,"width":145.71428571428572,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">producer</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":457,"y":165,"rotation":0,"id":13,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":140,"height":40,"lockAspectRatio":false,"lockShape":false,"order":10,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":1.9999999999999998,"y":0,"rotation":0,"id":14,"uid":null,"width":135.99999999999997,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">route</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":267,"y":165,"rotation":0,"id":11,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":150,"height":40,"lockAspectRatio":false,"lockShape":false,"order":8,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.142857142857143,"y":0,"rotation":0,"id":12,"uid":null,"width":145.71428571428572,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">manager</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":237,"y":248,"rotation":0,"id":9,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":7,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">remote</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":252.00000000000003,"y":150,"rotation":0,"id":7,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":359.99999999999994,"height":70,"lockAspectRatio":false,"lockShape":false,"order":6,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[],"linkMap":[]},{"x":342,"y":299,"rotation":0,"id":5,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":180,"height":40,"lockAspectRatio":false,"lockShape":false,"order":4,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.5714285714285716,"y":0,"rotation":0,"id":6,"uid":null,"width":174.8571428571429,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">codec</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":342,"y":248,"rotation":0,"id":2,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":180,"height":40,"lockAspectRatio":false,"lockShape":false,"order":2,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.5714285714285716,"y":0,"rotation":0,"id":4,"uid":null,"width":174.8571428571429,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">client</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":287,"y":240,"rotation":0,"id":0,"uid":"com.gliffy.shape.uml.uml_v1.default.simple_class","width":290,"height":110,"lockAspectRatio":false,"lockShape":false,"order":1,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[],"linkMap":[]}],"background":"#FFFFFF","width":710,"height":370,"maxWidth":5000,"maxHeight":5000,"nodeIndex":59,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{},"lineStyles":{"global":{"endArrow":1}},"textStyles":{},"themeData":null}}
\ No newline at end of file
diff --git a/docs/feature.md b/docs/feature.md
deleted file mode 100644
index eed3e17..0000000
--- a/docs/feature.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# Feature
-
-## Producer
-
-### MessageType
-- [x] NormalMessage
-- [ ] TransactionMessage
-- [ ] DelayMessage
-
-### SendWith    
-- [x] Sync
-- [ ] Async
-- [x] OneWay
-
-### Other    
-- [ ] Config
-- [ ] MessageId Generate
-- [ ] CompressMsg
-- [ ] LoadBalance
-- [ ] DefaultTopic
-- [ ] VipChannel
-- [ ] Retry
-- [ ] Hook
-- [ ] CheckRequestQueue
-- [ ] MQFaultStrategy
-
-## Consumer
-
-### ReceiveType
-- [x] Push
-- [ ] Pull
-
-### ConsumingType
-- [x] Concurrently
-- [ ] Orderly
-
-### MessageModel
-- [x] CLUSTERING
-- [x] BROADCASTING
-    
-### AllocateMessageQueueStrategy
-- [x] AllocateMessageQueueAveragely
-- [x] AllocateMessageQueueAveragelyByCircle
-- [X] AllocateMessageQueueByConfig
-- [X] AllocateMessageQueueByMachineRoom
-
-### Other
-- [x] Rebalance
-- [x] Flow Control
-- [ ] compress
-- [x] ConsumeFromWhere
-- [ ] Retry(sendMessageBack)
-- [ ] Hook
-
-## Common
-- [ ] PollNameServer
-- [x] Heartbeat
-- [x] UpdateTopicRouteInfoFromNameServer
-- [ ] CleanOfflineBroker
-- [ ] ClearExpiredMessage(form consumer consumeMessageService)
-    
-## Remoting
-- [x] API
-    - [x] InvokeSync
-    - [x] InvokeAsync
-    - [x] InvokeOneWay
-- [x] Serialize
-    - [x] JSON
-    - [x] ROCKETMQ
-- [ ] Other
-    - [ ] VIPChannel
-    - [ ] RPCHook
-    
-## Admin
-
-### Topic/Cluster
-- [x] updateTopic
-- [x] deleteTopic
-- [ ] updateSubGroup
-- [ ] deleteSubGroup
-- [ ] updateBrokerConfig
-- [ ] updateTopicPerm
-- [ ] listTopic
-- [ ] topicRoute
-- [ ] topicStatus
-- [ ] topicClusterList
\ No newline at end of file
diff --git a/docs/images/client-design.png b/docs/images/client-design.png
deleted file mode 100644
index 97b86ef..0000000
--- a/docs/images/client-design.png
+++ /dev/null
Binary files differ
diff --git a/docs/zh/native-design_zh.md b/docs/zh/native-design_zh.md
deleted file mode 100644
index dd407a4..0000000
--- a/docs/zh/native-design_zh.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# RocketMQ Go Client Design Draft
-
-## Architecture
-
-### Overview
-![client-design](../images/client-design.png)
-
-### Description
-在RocketMQ Java Client的实现里面,代码耦合了大量的admin方面的功能, 其为了尽可能的提高代码复用率,代码的依赖关系较为复杂、接口的设计比
-较重、语义的界限不够清晰。因此,为了避免简单的对Java代码进行翻译,故Go客户端进行了重新的设计,剥离了admin相关的逻辑。整体如上面的图所示,在逻辑层次上,按照请求
-顺序,从下到上总共分为三层:
-- remote层:client网络通信和私有协议层,将到每个到服务端(NameServer或Broker)的连接实体抽象为一个client结构,并在这里实现了网络数据的
-序列/反序列化。
-- 公共层:由于remote层对上层只暴露了`Sync/Async/Oneway`三个接口,所以对于特定的Request/Response、连接的管理、路由等信息的处理和维护、
-其它`producer/consumer`共用的逻辑,均在这里实现。
-- 业务逻辑层:在这里实现各种producer、consumer的语义。所有producer、consumer专有的逻辑,均放到这里实现,如`queue selector`,
-`consume balance`, `offset storage`等。除了基础的数据结构外,producer和consumer之间内部的代码不能进行复用。
-
-
-## 设计目标
-0. 兼容cgo版本已经暴露出去的API
-1. 实现语义清晰、轻量的API接口
-2. 依赖关系清晰简单,设计和实现要正交
-
-## 目录结构
-### 源码
-- producer:producer相关逻辑
-- consumer:consumer相关逻辑
-- common(可改名):连接管理和路由管理相关的通用逻辑
-- remote:网络通信和序列化
-
-### 其它
-- benchmark:压力测试相关代码
-- core:1.2版本cgo的代码库,该目录下的代码将会被移除,只保留API进行兼容,并会被标记为`Deprecated`
-- docs:文档,包括面向用户和开发者
-- examples:示例代码
-- test:集成测试代码
-
-## API
-
-### remote
-```go
-NewRemotingCommand(code int16, header CustomHeader) *RemotingCommand 
-
-// send a request to servers and return until response received.
-SendMessageSync(ctx context.Context, brokerAddrs, brokerName string, request *SendMessageRequest, msgs []*Message) (*SendResult, error)
-
-SendMessageAsync(ctx context.Context, brokerAddrs, brokerName string, request *SendMessageRequest, msgs []*Message, f func(result *SendResult)) error
-
-SendMessageOneWay(ctx context.Context, brokerAddrs string, request *SendMessageRequest, msgs []*Message) (*SendResult, error)
-```
-
-### common
-All struct needed has been defined in codebase.
-
-```go
-// PullMessage with sync
-SendMessage(topic string, msgs *[]Message) error 
-
-// SendMessageAsync send message with batch by async
-SendMessageAsync(topic string, msgs *[]Message, f func(result *SendResult)) error 
-
-// PullMessage with sync
-PullMessage(ctx context.Context, brokerAddrs string, request *PullMessageRequest) (*PullResult, error)
-
-// PullMessageAsync pull message async
-func PullMessageAsync(ctx context.Context, brokerAddrs string, request *PullMessageRequest, f func(result *PullResult)) error
-
-// QueryMaxOffset with specific queueId and topic
-QueryMaxOffset(topic string, queueId int) error 
-
-// QueryConsumerOffset with specific queueId and topic of consumerGroup
-QueryConsumerOffset(consumerGroup, topic string, queue int) (int64, error) 
-
-// SearchOffsetByTimestamp with specific queueId and topic
-SearchOffsetByTimestamp(topic string, queue int, timestamp int64) (int64, error) 
-
-// UpdateConsumerOffset with specific queueId and topic
-UpdateConsumerOffset(consumerGroup, topic string, queue int, offset int64) error 
-```
-
-## Road map
-for more details about features: [feature-list](../feature.md)
-
-### Milestone1(due: 2019.3.10)
-
-#### producer
-- [ ] normal message
-- [ ] order message
-
-#### consumer
-- [ ] normal message with pull/push
-- [ ] order message with pull/push
-- [ ] rebalance
-- [ ] offset manager
-
-#### common
-- [ ] API wrapper
-- [ ] connections manager
-- [ ] route
-
-#### remote
-- [ ] serializer
-- [ ] communication
-- [ ] processor
-- [ ] RPC
-
-### Milestone2 (2019.4.12)
-- Transaction Message
-- ACL
-- Message Tracing
-
-## sub project
-- RocketMQ Administration tools: JVM too heavy for command line tools
\ No newline at end of file
diff --git a/docs/zh/rocketmq-protocol_zh.md b/docs/zh/rocketmq-protocol_zh.md
deleted file mode 100644
index 818d2e1..0000000
--- a/docs/zh/rocketmq-protocol_zh.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# RocketMQ 通信协议
-
-在 RocketMQ 中,`RemotingCommand` 是 RocketMQ 通信的基本对象,Request/Response 最后均被包装成 `RemotingCommand`。一个 `RemotingCommand` 在被序列化后的格式如下:
-
-```
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-+ frame_size | header_length |         header_body        |     body     +
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-+   4bytes   |     4bytes    | (21 + r_len + e_len) bytes | remain bytes +
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-```
-
-| item | type | description |
-| :-: | :-: | :-: |
-| frame_size | `int32` | 一个 `RemotingCommand` 数据包大小 |
-| header_length | `int32` | 高8位表示数据的序列化方式,余下的表示真实 header 长度 |
-| header_body | `[]byte` | header 的 payload,长度由附带的 `remark` 和 `properties` 决定|
-| body | `[]byte` | 具体 Request/Response 的 payload |
-
-## Header
-
-RocketMQ 的 Header 序列化方式有两种:JSON 和 RocketMQ 私有的序列化方式。JSON 序列化方式不再赘述。具体可以参考 Java `RemotingCommand` 类。
-
-主要介绍 RocketMQ 的私有序列化方式。
-
-在序列化的时候,需要将序列化方式记录进数据包里面,即对 `header_length` 进行编码
-
-```go
-// 编码算法
-
-// 编码后的 header_length
-var header_length int32
-
-// 实际的 header 长度
-var headerDataLen int32
-
-// 序列化方式
-var SerializedType byte
-
-result := make([]byte, 4)
-result[0]|SerializedType
-result[1]|byte((headerDataLen >> 16) & 0xFF)
-result[2]|byte((headerDataLen >> 8) & 0xFF)
-result[3]|byte(headerDataLen & 0xFF)
-binary.Read(result, binary.BigEndian, &header_length)
-
-// 解码算法
-headerDataLen := header_length & 0xFFFFFF
-SerializedType := byte((header_length >> 24) & 0xFF)
-```
-
-### Header Frame
-
-```
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-+  request_code | l_flag | v_flag | opaque | request_flag |  r_len  |   r_body    |  e_len  |    e_body   +
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-+     2bytes    |  1byte | 2bytes | 4bytes |    4 bytes   | 4 bytes | r_len bytes | 4 bytes | e_len bytes +
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-```
-
-| item | type | description |
-| :-: | :-: | :-: |
-| request_code | `int16` | 哪一种 Request 或 ResponseCode,具体类别由 request_flag 决定 |
-| l_flag | `byte` | language 位,用来标识Request来源方的开发语言 |
-| v_flag | `int16` | 版本标记位 |
-| request_flag |`int32`| Header标记位,用来标记该 `RemotingCommand` 的类型和请求方式 |
-| opaque | `int32` | 标识 Request/Response 的 RequestID,Broker 返回的 Response 通过该值和 Client 缓存的 Request 一一对应 |
-| r_len | `int32` | length of remark, remark 是 Request/Response 的附带说明信息,一般在 Response 中用来说明具体的错误原因 |
-| r_body | `[]byte` | payload of remark |
-| e_len | `int32` | length of extended fields,即 properties,一些非标准字段会存储在这里,在 RocketMQ 的各种 feature 中均有广泛应用 |
-| e_body | `int32` | payload of extended fields |
-
-## Body
-
-`body` 是具体的 Request/Response 的数据,在 RocketMQ 中,有许多种 Request/Response。每个类有自己的序列化和反序列方式,由于种类过多,
-这里就不再展开。可以具体参考Java代码中对`CommandCustomHeader`的使用。下面列一些 Client 使用到的 Request 和 Response。
-
-### RequestCode
-
-| item | type | description |
-| :-: | :-: | :-: |
-| SEND_MESSAGE | 10 | 向broker发送消息 |
-| PULL_MESSAGE | 11 | 从broker拉取消息,client的push模式也是通过pull的长轮询来实现的 |
-| TODO... | | |
-
-### ResponseCode
-
-| item | type | description |
-| :-: | :-: | :-: |
-| FLUSH_DISK_TIMEOUT | 10 | broker 存储层刷盘超时 |
-| SLAVE_NOT_AVAILABLE | 11 | slave 节点无法服务 |
-| FLUSH_SLAVE_TIMEOUT | 12 | 数据同步到 slave 超时 |
-| MESSAGE_ILLEGAL | 13 | 消息格式不合格 |
-| SERVICE_NOT_AVAILABLE | 14 | broker 暂时不可用 |
-| VERSION_NOT_SUPPORTED | 15 | 不支持的请求,目前没有看到使用 |
-| NO_PERMISSION | 16 | 对 broker、topic 或 subscription 无访问权限 |
-| TOPIC_EXIST_ALREADY | 18 | topic 已存在,目前没看到使用 |
-| PULL_NOT_FOUND | 19 | 没拉到消息,大多为 offset 错误 |
-| PULL_RETRY_IMMEDIATELY | 20 | 建议 client 立即重新拉取消息 |
-| PULL_OFFSET_MOVED | 21 | offset 太小或太大 |
-| QUERY_NOT_FOUND | 22 | 管理面 Response,TODO |
-| SUBSCRIPTION_PARSE_FAILED | 23 | 订阅数据解析失败 |
-| SUBSCRIPTION_NOT_EXIST | 24 | 订阅不存在 |
-| SUBSCRIPTION_NOT_LATEST | 25 | 订阅数据版本和 request 数据版本不匹配 |
-| SUBSCRIPTION_GROUP_NOT_EXIST | 26 | 订阅组不存在 |
-| FILTER_DATA_NOT_EXIST | 27 | filter 数据不存在 |
-| FILTER_DATA_NOT_LATEST | 28 | filter 数据版本和 request 数据版本不匹配 |
-| TRANSACTION_SHOULD_COMMIT | 200 | 事务 Response,TODO |
-| TRANSACTION_SHOULD_ROLLBACK | 201 | 事务 Response,TODO |
-| TRANSACTION_STATE_UNKNOW | 202 | 事务 Response,TODO | |
-| TRANSACTION_STATE_GROUP_WRONG | 203 | 事务 Response,TODO |
-| NO_BUYER_ID | 204 | 不知道是什么,没看到 broker 端在使用 |
-| NOT_IN_CURRENT_UNIT | 205 | 不知道是什么,没看到 broker 端在使用 |
-| CONSUMER_NOT_ONLINE | 206 | consumer 不在线,控制面 response |
-| CONSUME_MSG_TIMEOUT | 207 | client request 等待 broker 相应超时 |
-| NO_MESSAGE | 208 | 控制面 response,由 client 自己设置,不清楚具体用途 |
diff --git a/errors/errors.go b/errors/errors.go
deleted file mode 100644
index 195984e..0000000
--- a/errors/errors.go
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package errors
-
-import "errors"
-
-var (
-	ErrRequestTimeout    = errors.New("request timeout")
-	ErrMQEmpty           = errors.New("MessageQueue is nil")
-	ErrOffset            = errors.New("offset < 0")
-	ErrNumbers           = errors.New("numbers < 0")
-	ErrEmptyTopic        = errors.New("empty topic")
-	ErrEmptyNameSrv      = errors.New("empty namesrv")
-	ErrEmptyGroupID      = errors.New("empty group id")
-	ErrTestMin           = errors.New("test minutes must be positive integer")
-	ErrOperationInterval = errors.New("operation interval must be positive integer")
-	ErrMessageBody       = errors.New("message body size must be positive integer")
-	ErrEmptyExpression   = errors.New("empty expression")
-	ErrCreated           = errors.New("consumer group has been created")
-	ErrBrokerNotFound    = errors.New("broker can not found")
-	ErrStartTopic        = errors.New("cannot subscribe topic since client either failed to start or has been shutdown.")
-	ErrResponse          = errors.New("response error")
-	ErrCompressLevel     = errors.New("unsupported compress level")
-	ErrUnknownIP         = errors.New("unknown IP address")
-	ErrService           = errors.New("service close is not running, please check")
-	ErrTopicNotExist     = errors.New("topic not exist")
-	ErrNotExisted        = errors.New("not existed")
-	ErrNoNameserver      = errors.New("nameServerAddrs can't be empty.")
-	ErrMultiIP           = errors.New("multiple IP addr does not support")
-	ErrIllegalIP         = errors.New("IP addr error")
-	ErrTopicEmpty        = errors.New("topic is nil")
-	ErrMessageEmpty      = errors.New("message is nil")
-	ErrNotRunning        = errors.New("producer not started")
-	ErrPullConsumer      = errors.New("pull consumer has not supported")
-	ErrMultipleTopics    = errors.New("the topic of the messages in one batch should be the same")
-)
diff --git a/examples/admin/topic/main.go b/examples/admin/topic/main.go
deleted file mode 100644
index ef9a536..0000000
--- a/examples/admin/topic/main.go
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-
-	"github.com/apache/rocketmq-client-go/v2/admin"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	topic := "newOne"
-	//clusterName := "DefaultCluster"
-	nameSrvAddr := []string{"127.0.0.1:9876"}
-	brokerAddr := "127.0.0.1:10911"
-
-	testAdmin, err := admin.NewAdmin(admin.WithResolver(primitive.NewPassthroughResolver(nameSrvAddr)))
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-
-	//create topic
-	err = testAdmin.CreateTopic(
-		context.Background(),
-		admin.WithTopicCreate(topic),
-		admin.WithBrokerAddrCreate(brokerAddr),
-	)
-	if err != nil {
-		fmt.Println("Create topic error:", err.Error())
-	}
-
-	//deletetopic
-	err = testAdmin.DeleteTopic(
-		context.Background(),
-		admin.WithTopicDelete(topic),
-		//admin.WithBrokerAddrDelete(brokerAddr),
-		//admin.WithNameSrvAddr(nameSrvAddr),
-	)
-	if err != nil {
-		fmt.Println("Delete topic error:", err.Error())
-	}
-
-	err = testAdmin.Close()
-	if err != nil {
-		fmt.Printf("Shutdown admin error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/acl/main.go b/examples/consumer/acl/main.go
deleted file mode 100644
index 96d0dd0..0000000
--- a/examples/consumer/acl/main.go
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, err := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithCredentials(primitive.Credentials{
-			AccessKey: "RocketMQ",
-			SecretKey: "12345678",
-		}),
-	)
-	if err != nil {
-		fmt.Println("init consumer error: " + err.Error())
-		os.Exit(0)
-	}
-
-	err = c.Subscribe("test", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/broadcast/main.go b/examples/consumer/broadcast/main.go
deleted file mode 100644
index 219ab3e..0000000
--- a/examples/consumer/broadcast/main.go
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithConsumeFromWhere(consumer.ConsumeFromFirstOffset),
-		consumer.WithConsumerModel(consumer.BroadCasting),
-	)
-	err := c.Subscribe("min", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/delay/main.go b/examples/consumer/delay/main.go
deleted file mode 100644
index 1bbe6ed..0000000
--- a/examples/consumer/delay/main.go
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-	)
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-
-		for _, msg := range msgs {
-			t := time.Now().UnixNano()/int64(time.Millisecond) - msg.BornTimestamp
-			fmt.Printf("Receive message[msgId=%s] %d ms later\n", msg.MsgId, t)
-		}
-
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/interceptor/main.go b/examples/consumer/interceptor/main.go
deleted file mode 100644
index 83f43b0..0000000
--- a/examples/consumer/interceptor/main.go
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithConsumerModel(consumer.Clustering),
-		consumer.WithConsumeFromWhere(consumer.ConsumeFromFirstOffset),
-		consumer.WithInterceptor(UserFistInterceptor(), UserSecondInterceptor()))
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
-
-func UserFistInterceptor() primitive.Interceptor {
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		msgCtx, _ := primitive.GetConsumerCtx(ctx)
-		fmt.Printf("msgCtx: %v, mehtod: %s", msgCtx, primitive.GetMethod(ctx))
-
-		msgs := req.([]*primitive.MessageExt)
-		fmt.Printf("user first interceptor before invoke: %v\n", msgs)
-		e := next(ctx, msgs, reply)
-
-		holder := reply.(*consumer.ConsumeResultHolder)
-		fmt.Printf("user first interceptor after invoke: %v, result: %v\n", msgs, holder)
-		return e
-	}
-}
-
-func UserSecondInterceptor() primitive.Interceptor {
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		msgs := req.([]*primitive.MessageExt)
-		fmt.Printf("user second interceptor before invoke: %v\n", msgs)
-		e := next(ctx, msgs, reply)
-		holder := reply.(*consumer.ConsumeResultHolder)
-		fmt.Printf("user second interceptor after invoke: %v, result: %v\n", msgs, holder)
-		return e
-	}
-}
diff --git a/examples/consumer/namespace/main.go b/examples/consumer/namespace/main.go
deleted file mode 100644
index d46f210..0000000
--- a/examples/consumer/namespace/main.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, err := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithCredentials(primitive.Credentials{
-			AccessKey: "RocketMQ",
-			SecretKey: "12345678",
-		}),
-		consumer.WithNamespace("namespace"),
-	)
-	if err != nil {
-		fmt.Println("init consumer error: " + err.Error())
-		os.Exit(0)
-	}
-
-	err = c.Subscribe("test", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/orderly/main.go b/examples/consumer/orderly/main.go
deleted file mode 100644
index 0f33e5f..0000000
--- a/examples/consumer/orderly/main.go
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithConsumerModel(consumer.Clustering),
-		consumer.WithConsumeFromWhere(consumer.ConsumeFromFirstOffset),
-		consumer.WithConsumerOrder(true),
-	)
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		orderlyCtx, _ := primitive.GetOrderlyCtx(ctx)
-		fmt.Printf("orderly context: %v\n", orderlyCtx)
-		fmt.Printf("subscribe orderly callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("Shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/pull/main.go b/examples/consumer/pull/main.go
deleted file mode 100644
index 5b5819e..0000000
--- a/examples/consumer/pull/main.go
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-func main() {
-	c, err := rocketmq.NewPullConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-	)
-	if err != nil {
-		rlog.Fatal(fmt.Sprintf("fail to new pullConsumer: %s", err), nil)
-	}
-	err = c.Start()
-	if err != nil {
-		rlog.Fatal(fmt.Sprintf("fail to new pullConsumer: %s", err), nil)
-	}
-
-	ctx := context.Background()
-	queue := primitive.MessageQueue{
-		Topic:      "TopicTest",
-		BrokerName: "", // replace with your broker name. otherwise, pull will failed.
-		QueueId:    0,
-	}
-
-	offset := int64(0)
-	for {
-		resp, err := c.PullFrom(ctx, queue, offset, 10)
-		if err != nil {
-			if err == errors.ErrRequestTimeout {
-				fmt.Printf("timeout \n")
-				time.Sleep(1 * time.Second)
-				continue
-			}
-			fmt.Printf("unexpectable err: %v \n", err)
-			return
-		}
-		if resp.Status == primitive.PullFound {
-			fmt.Printf("pull message success. nextOffset: %d \n", resp.NextBeginOffset)
-			for _, msg := range resp.GetMessageExts() {
-				fmt.Printf("pull msg: %v \n", msg)
-			}
-		}
-		offset = resp.NextBeginOffset
-	}
-}
diff --git a/examples/consumer/retry/concurrent/main.go b/examples/consumer/retry/concurrent/main.go
deleted file mode 100644
index 49f16d1..0000000
--- a/examples/consumer/retry/concurrent/main.go
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-// use concurrent consumer model, when Subscribe function return consumer.ConsumeRetryLater, the message will be
-// send to RocketMQ retry topic. we could set DelayLevelWhenNextConsume in ConsumeConcurrentlyContext, which used to
-// indicate the delay of message re-send to origin topic from retry topic.
-//
-// in this example, we always set DelayLevelWhenNextConsume=1, means that the message will be sent to origin topic after
-// 1s. in case of the unlimited retry, we will return consumer.ConsumeSuccess after ReconsumeTimes > 5
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithConsumerModel(consumer.Clustering),
-	)
-
-	// The DelayLevel specify the waiting time that before next reconsume,
-	// and it range is from 1 to 18 now.
-	//
-	// The time of each level is the value of indexing of {level-1} in [1s, 5s, 10s, 30s,
-	// 1m, 2m, 3m, 4m, 5m, 6m, 7m, 8m, 9m, 10m, 20m, 30m, 1h, 2h]
-	delayLevel := 1
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback len: %d \n", len(msgs))
-
-		concurrentCtx, _ := primitive.GetConcurrentlyCtx(ctx)
-		concurrentCtx.DelayLevelWhenNextConsume = delayLevel // only run when return consumer.ConsumeRetryLater
-
-		for _, msg := range msgs {
-			if msg.ReconsumeTimes > 5 {
-				fmt.Printf("msg ReconsumeTimes > 5. msg: %v", msg)
-				return consumer.ConsumeSuccess, nil
-			} else {
-				fmt.Printf("subscribe callback: %v \n", msg)
-			}
-		}
-		return consumer.ConsumeRetryLater, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shundown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/retry/order/main.go b/examples/consumer/retry/order/main.go
deleted file mode 100644
index e2d13bf..0000000
--- a/examples/consumer/retry/order/main.go
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/**
- * use orderly consumer model, when Subscribe function return consumer.SuspendCurrentQueueAMoment, it will be re-send to
- * local msg queue for later consume if msg.ReconsumeTimes < MaxReconsumeTimes, otherwise, it will be send to rocketmq
- * DLQ topic, we should manually resolve the msg.
- */
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithConsumerModel(consumer.Clustering),
-		consumer.WithConsumeFromWhere(consumer.ConsumeFromFirstOffset),
-		consumer.WithConsumerOrder(true),
-		consumer.WithMaxReconsumeTimes(5),
-	)
-
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		orderlyCtx, _ := primitive.GetOrderlyCtx(ctx)
-		fmt.Printf("orderly context: %v\n", orderlyCtx)
-		fmt.Printf("subscribe orderly callback len: %d \n", len(msgs))
-
-		for _, msg := range msgs {
-			if msg.ReconsumeTimes > 5 {
-				fmt.Printf("msg ReconsumeTimes > 5. msg: %v", msg)
-			} else {
-				fmt.Printf("subscribe orderly callback: %v \n", msg)
-			}
-		}
-		return consumer.SuspendCurrentQueueAMoment, nil
-
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shundown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/simple/main.go b/examples/consumer/simple/main.go
deleted file mode 100644
index 70f35b3..0000000
--- a/examples/consumer/simple/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-	)
-	err := c.Subscribe("test", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		for i := range msgs {
-			fmt.Printf("subscribe callback: %v \n", msgs[i])
-		}
-
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/strategy/main.go b/examples/consumer/strategy/main.go
deleted file mode 100644
index 269ce11..0000000
--- a/examples/consumer/strategy/main.go
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithStrategy(consumer.AllocateByAveragely),
-	)
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/tag/main.go b/examples/consumer/tag/main.go
deleted file mode 100644
index ec16f51..0000000
--- a/examples/consumer/tag/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-	)
-	selector := consumer.MessageSelector{
-		Type:       consumer.TAG,
-		Expression: "TagA || TagC",
-	}
-	err := c.Subscribe("TopicTest", selector, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/consumer/trace/main.go b/examples/consumer/trace/main.go
deleted file mode 100644
index 97f22ed..0000000
--- a/examples/consumer/trace/main.go
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/consumer"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func main() {
-	namesrvs := []string{"127.0.0.1:9876"}
-	traceCfg := &primitive.TraceConfig{
-		Access:   primitive.Local,
-		Resolver: primitive.NewPassthroughResolver(namesrvs),
-	}
-
-	c, _ := rocketmq.NewPushConsumer(
-		consumer.WithGroupName("testGroup"),
-		consumer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		consumer.WithTrace(traceCfg),
-	)
-	err := c.Subscribe("TopicTest", consumer.MessageSelector{}, func(ctx context.Context,
-		msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
-		fmt.Printf("subscribe callback: %v \n", msgs)
-		return consumer.ConsumeSuccess, nil
-	})
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-	// Note: start after subscribe
-	err = c.Start()
-	if err != nil {
-		fmt.Println(err.Error())
-		os.Exit(-1)
-
-	}
-	time.Sleep(time.Hour)
-	err = c.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown Consumer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/acl/main.go b/examples/producer/acl/main.go
deleted file mode 100644
index 96881d3..0000000
--- a/examples/producer/acl/main.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Package main implements a producer with user custom interceptor.
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, err := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-		producer.WithCredentials(primitive.Credentials{
-			AccessKey: "RocketMQ",
-			SecretKey: "12345678",
-		}),
-	)
-
-	if err != nil {
-		fmt.Println("init producer error: " + err.Error())
-		os.Exit(0)
-	}
-
-	err = p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	for i := 0; i < 100000; i++ {
-		res, err := p.SendSync(context.Background(), primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client!")))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/async/main.go b/examples/producer/async/main.go
deleted file mode 100644
index 2a5182c..0000000
--- a/examples/producer/async/main.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"sync"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-// Package main implements a async producer to send message.
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-		producer.WithQueueSelector(producer.NewManualQueueSelector()))
-
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	var wg sync.WaitGroup
-	for i := 0; i < 10; i++ {
-		wg.Add(1)
-		err := p.SendAsync(context.Background(),
-			func(ctx context.Context, result *primitive.SendResult, e error) {
-				if e != nil {
-					fmt.Printf("receive message error: %s\n", err)
-				} else {
-					fmt.Printf("send message success: result=%s\n", result.String())
-				}
-				wg.Done()
-			}, primitive.NewMessage("test", []byte("Hello RocketMQ Go Client!")))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		}
-	}
-	wg.Wait()
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/batch/main.go b/examples/producer/batch/main.go
deleted file mode 100644
index dc591a1..0000000
--- a/examples/producer/batch/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"strconv"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	var msgs []*primitive.Message
-	for i := 0; i < 10; i++ {
-		msgs = append(msgs, primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client! num: "+strconv.Itoa(i))))
-	}
-
-	res, err := p.SendSync(context.Background(), msgs...)
-
-	if err != nil {
-		fmt.Printf("send message error: %s\n", err)
-	} else {
-		fmt.Printf("send message success: result=%s\n", res.String())
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/delay/main.go b/examples/producer/delay/main.go
deleted file mode 100644
index aadbb70..0000000
--- a/examples/producer/delay/main.go
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	for i := 0; i < 10; i++ {
-		msg := primitive.NewMessage("test", []byte("Hello RocketMQ Go Client!"))
-		msg.WithDelayTimeLevel(3)
-		res, err := p.SendSync(context.Background(), msg)
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/interceptor/main.go b/examples/producer/interceptor/main.go
deleted file mode 100644
index c40f9a0..0000000
--- a/examples/producer/interceptor/main.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Package main implements a producer with user custom interceptor.
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-		producer.WithInterceptor(UserFirstInterceptor(), UserSecondInterceptor()),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	for i := 0; i < 10; i++ {
-		res, err := p.SendSync(context.Background(), primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client!")))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
-
-func UserFirstInterceptor() primitive.Interceptor {
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		fmt.Printf("user first interceptor before invoke: req:%v\n", req)
-		err := next(ctx, req, reply)
-		fmt.Printf("user first interceptor after invoke: req: %v, reply: %v \n", req, reply)
-		return err
-	}
-}
-
-func UserSecondInterceptor() primitive.Interceptor {
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		fmt.Printf("user second interceptor before invoke: req: %v\n", req)
-		err := next(ctx, req, reply)
-		fmt.Printf("user second interceptor after invoke: req: %v, reply: %v \n", req, reply)
-		return err
-	}
-}
diff --git a/examples/producer/namespace/main.go b/examples/producer/namespace/main.go
deleted file mode 100644
index 9124284..0000000
--- a/examples/producer/namespace/main.go
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Package main implements a producer with user custom interceptor.
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, err := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-		producer.WithCredentials(primitive.Credentials{
-			AccessKey: "RocketMQ",
-			SecretKey: "12345678",
-		}),
-		producer.WithNamespace("namespace"),
-	)
-
-	if err != nil {
-		fmt.Println("init producer error: " + err.Error())
-		os.Exit(0)
-	}
-
-	err = p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	for i := 0; i < 100000; i++ {
-		res, err := p.SendSync(context.Background(), primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client!")))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/simple/main.go b/examples/producer/simple/main.go
deleted file mode 100644
index 6fd3364..0000000
--- a/examples/producer/simple/main.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"strconv"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-// Package main implements a simple producer to send message.
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	topic := "test"
-
-	for i := 0; i < 10; i++ {
-		msg := &primitive.Message{
-			Topic: topic,
-			Body:  []byte("Hello RocketMQ Go Client! " + strconv.Itoa(i)),
-		}
-		res, err := p.SendSync(context.Background(), msg)
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/tag/main.go b/examples/producer/tag/main.go
deleted file mode 100644
index 7ce8559..0000000
--- a/examples/producer/tag/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	tags := []string{"TagA", "TagB", "TagC"}
-	for i := 0; i < 3; i++ {
-		tag := tags[i%3]
-		msg := primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client!"))
-		msg.WithTag(tag)
-
-		res, err := p.SendSync(context.Background(), msg)
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/trace/main.go b/examples/producer/trace/main.go
deleted file mode 100644
index b741704..0000000
--- a/examples/producer/trace/main.go
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-func main() {
-	namesrvs := []string{"127.0.0.1:9876"}
-	traceCfg := &primitive.TraceConfig{
-		Access:   primitive.Local,
-		Resolver: primitive.NewPassthroughResolver(namesrvs),
-	}
-
-	p, _ := rocketmq.NewProducer(
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(2),
-		producer.WithTrace(traceCfg))
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s", err.Error())
-		os.Exit(1)
-	}
-	for i := 0; i < 1; i++ {
-		res, err := p.SendSync(context.Background(), primitive.NewMessage("test",
-			[]byte("Hello RocketMQ Go Client!")))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-
-	time.Sleep(10 * time.Second)
-
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/examples/producer/transaction/main.go b/examples/producer/transaction/main.go
deleted file mode 100644
index 05b6c52..0000000
--- a/examples/producer/transaction/main.go
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"strconv"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/producer"
-)
-
-type DemoListener struct {
-	localTrans       *sync.Map
-	transactionIndex int32
-}
-
-func NewDemoListener() *DemoListener {
-	return &DemoListener{
-		localTrans: new(sync.Map),
-	}
-}
-
-func (dl *DemoListener) ExecuteLocalTransaction(msg *primitive.Message) primitive.LocalTransactionState {
-	nextIndex := atomic.AddInt32(&dl.transactionIndex, 1)
-	fmt.Printf("nextIndex: %v for transactionID: %v\n", nextIndex, msg.TransactionId)
-	status := nextIndex % 3
-	dl.localTrans.Store(msg.TransactionId, primitive.LocalTransactionState(status+1))
-
-	fmt.Printf("dl")
-	return primitive.UnknowState
-}
-
-func (dl *DemoListener) CheckLocalTransaction(msg *primitive.MessageExt) primitive.LocalTransactionState {
-	fmt.Printf("%v msg transactionID : %v\n", time.Now(), msg.TransactionId)
-	v, existed := dl.localTrans.Load(msg.TransactionId)
-	if !existed {
-		fmt.Printf("unknow msg: %v, return Commit", msg)
-		return primitive.CommitMessageState
-	}
-	state := v.(primitive.LocalTransactionState)
-	switch state {
-	case 1:
-		fmt.Printf("checkLocalTransaction COMMIT_MESSAGE: %v\n", msg)
-		return primitive.CommitMessageState
-	case 2:
-		fmt.Printf("checkLocalTransaction ROLLBACK_MESSAGE: %v\n", msg)
-		return primitive.RollbackMessageState
-	case 3:
-		fmt.Printf("checkLocalTransaction unknow: %v\n", msg)
-		return primitive.UnknowState
-	default:
-		fmt.Printf("checkLocalTransaction default COMMIT_MESSAGE: %v\n", msg)
-		return primitive.CommitMessageState
-	}
-}
-
-func main() {
-	p, _ := rocketmq.NewTransactionProducer(
-		NewDemoListener(),
-		producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		producer.WithRetry(1),
-	)
-	err := p.Start()
-	if err != nil {
-		fmt.Printf("start producer error: %s\n", err.Error())
-		os.Exit(1)
-	}
-
-	for i := 0; i < 10; i++ {
-		res, err := p.SendMessageInTransaction(context.Background(),
-			primitive.NewMessage("TopicTest5", []byte("Hello RocketMQ again "+strconv.Itoa(i))))
-
-		if err != nil {
-			fmt.Printf("send message error: %s\n", err)
-		} else {
-			fmt.Printf("send message success: result=%s\n", res.String())
-		}
-	}
-	time.Sleep(5 * time.Minute)
-	err = p.Shutdown()
-	if err != nil {
-		fmt.Printf("shutdown producer error: %s", err.Error())
-	}
-}
diff --git a/go.mod b/go.mod
deleted file mode 100644
index 0aac6ba..0000000
--- a/go.mod
+++ /dev/null
@@ -1,17 +0,0 @@
-module github.com/apache/rocketmq-client-go/v2
-
-go 1.13
-
-require (
-	github.com/emirpasic/gods v1.12.0
-	github.com/golang/mock v1.3.1
-	github.com/json-iterator/go v1.1.9
-	github.com/pkg/errors v0.8.1
-	github.com/sirupsen/logrus v1.4.1
-	github.com/smartystreets/goconvey v1.6.4
-	github.com/stathat/consistent v1.0.0
-	github.com/stretchr/testify v1.3.0
-	github.com/tidwall/gjson v1.13.0
-	go.uber.org/atomic v1.5.1
-	stathat.com/c/consistent v1.0.0 // indirect
-)
diff --git a/go.sum b/go.sum
deleted file mode 100644
index 157f415..0000000
--- a/go.sum
+++ /dev/null
@@ -1,63 +0,0 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
-github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
-github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U=
-github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
-github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
-github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
-github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
-github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
-github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
-go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM=
-go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c=
-stathat.com/c/consistent v1.0.0/go.mod h1:QkzMWzcbB+yQBL2AttO6sgsQS/JSTapcDISJalmCDS0=
diff --git a/internal/callback.go b/internal/callback.go
deleted file mode 100644
index fea11b4..0000000
--- a/internal/callback.go
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"net"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-// remotingClient callback TransactionProducer
-type CheckTransactionStateCallback struct {
-	Addr   net.Addr
-	Msg    *primitive.MessageExt
-	Header CheckTransactionStateRequestHeader
-}
diff --git a/internal/client.go b/internal/client.go
deleted file mode 100644
index c7f3e58..0000000
--- a/internal/client.go
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	errors2 "github.com/apache/rocketmq-client-go/v2/errors"
-	"net"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-const (
-	clientVersion        = "v2.1.0"
-	defaultTraceRegionID = "DefaultRegion"
-
-	// tracing message switch
-	_TraceOff = "false"
-
-	// Pulling topic information interval from the named server
-	_PullNameServerInterval = 30 * time.Second
-
-	// Sending heart beat interval to all broker
-	_HeartbeatBrokerInterval = 30 * time.Second
-
-	// Offset persistent interval for consumer
-	_PersistOffsetInterval = 5 * time.Second
-
-	// Rebalance interval
-	_RebalanceInterval = 20 * time.Second
-)
-
-var (
-	ErrServiceState = errors2.ErrService
-
-	_VIPChannelEnable = false
-)
-
-func init() {
-	if os.Getenv("com.rocketmq.sendMessageWithVIPChannel") != "" {
-		value, err := strconv.ParseBool(os.Getenv("com.rocketmq.sendMessageWithVIPChannel"))
-		if err == nil {
-			_VIPChannelEnable = value
-		}
-	}
-}
-
-type InnerProducer interface {
-	PublishTopicList() []string
-	UpdateTopicPublishInfo(topic string, info *TopicPublishInfo)
-	IsPublishTopicNeedUpdate(topic string) bool
-	IsUnitMode() bool
-}
-
-type InnerConsumer interface {
-	PersistConsumerOffset() error
-	UpdateTopicSubscribeInfo(topic string, mqs []*primitive.MessageQueue)
-	IsSubscribeTopicNeedUpdate(topic string) bool
-	SubscriptionDataList() []*SubscriptionData
-	Rebalance()
-	IsUnitMode() bool
-	GetConsumerRunningInfo() *ConsumerRunningInfo
-	ConsumeMessageDirectly(msg *primitive.MessageExt, brokerName string) *ConsumeMessageDirectlyResult
-	GetcType() string
-	GetModel() string
-	GetWhere() string
-	ResetOffset(topic string, table map[primitive.MessageQueue]int64)
-}
-
-func DefaultClientOptions() ClientOptions {
-	opts := ClientOptions{
-		InstanceName: "DEFAULT",
-		RetryTimes:   3,
-		ClientIP:     utils.LocalIP,
-	}
-	return opts
-}
-
-type ClientOptions struct {
-	GroupName         string
-	NameServerAddrs   primitive.NamesrvAddr
-	Namesrv           Namesrvs
-	ClientIP          string
-	InstanceName      string
-	UnitMode          bool
-	UnitName          string
-	VIPChannelEnabled bool
-	RetryTimes        int
-	Interceptors      []primitive.Interceptor
-	Credentials       primitive.Credentials
-	Namespace         string
-	Resolver          primitive.NsResolver
-}
-
-func (opt *ClientOptions) ChangeInstanceNameToPID() {
-	if opt.InstanceName == "DEFAULT" {
-		opt.InstanceName = fmt.Sprintf("%d#%d", os.Getpid(), time.Now().UnixNano())
-	}
-}
-
-func (opt *ClientOptions) String() string {
-	return fmt.Sprintf("ClientOption [ClientIP=%s, InstanceName=%s, "+
-		"UnitMode=%v, UnitName=%s, VIPChannelEnabled=%v]", opt.ClientIP,
-		opt.InstanceName, opt.UnitMode, opt.UnitName, opt.VIPChannelEnabled)
-}
-
-//go:generate mockgen -source client.go -destination mock_client.go -self_package github.com/apache/rocketmq-client-go/v2/internal  --package internal RMQClient
-type RMQClient interface {
-	Start()
-	Shutdown()
-
-	ClientID() string
-
-	RegisterProducer(group string, producer InnerProducer) error
-	UnregisterProducer(group string)
-	InvokeSync(ctx context.Context, addr string, request *remote.RemotingCommand,
-		timeoutMillis time.Duration) (*remote.RemotingCommand, error)
-	InvokeAsync(ctx context.Context, addr string, request *remote.RemotingCommand,
-		f func(*remote.RemotingCommand, error)) error
-	InvokeOneWay(ctx context.Context, addr string, request *remote.RemotingCommand,
-		timeoutMillis time.Duration) error
-	CheckClientInBroker()
-	SendHeartbeatToAllBrokerWithLock()
-	UpdateTopicRouteInfo()
-
-	ProcessSendResponse(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) error
-
-	RegisterConsumer(group string, consumer InnerConsumer) error
-	UnregisterConsumer(group string)
-	PullMessage(ctx context.Context, brokerAddrs string, request *PullMessageRequestHeader) (*primitive.PullResult, error)
-	RebalanceImmediately()
-	UpdatePublishInfo(topic string, data *TopicRouteData, changed bool)
-
-	GetNameSrv() Namesrvs
-}
-
-var _ RMQClient = new(rmqClient)
-
-type rmqClient struct {
-	option ClientOptions
-	// group -> InnerProducer
-	producerMap sync.Map
-
-	// group -> InnerConsumer
-	consumerMap sync.Map
-	once        sync.Once
-
-	remoteClient remote.RemotingClient
-	hbMutex      sync.Mutex
-	close        bool
-	rbMutex      sync.Mutex
-	done         chan struct{}
-	shutdownOnce sync.Once
-}
-
-func (c *rmqClient) GetNameSrv() Namesrvs {
-	return c.option.Namesrv
-}
-
-var clientMap sync.Map
-
-func GetOrNewRocketMQClient(option ClientOptions, callbackCh chan interface{}) RMQClient {
-	client := &rmqClient{
-		option:       option,
-		remoteClient: remote.NewRemotingClient(),
-		done:         make(chan struct{}),
-	}
-	actual, loaded := clientMap.LoadOrStore(client.ClientID(), client)
-
-	if loaded {
-		// compare namesrv address
-		client = actual.(*rmqClient)
-		now := option.Namesrv.(*namesrvs).resolver.Resolve()
-		old := client.GetNameSrv().(*namesrvs).resolver.Resolve()
-		if len(now) != len(old) {
-			rlog.Error("different namesrv option in the same instance", map[string]interface{}{
-				"NewNameSrv":    now,
-				"BeforeNameSrv": old,
-			})
-			return nil
-		}
-		sort.Strings(now)
-		sort.Strings(old)
-		for i := 0; i < len(now); i++ {
-			if now[i] != old[i] {
-				rlog.Error("different namesrv option in the same instance", map[string]interface{}{
-					"NewNameSrv":    now,
-					"BeforeNameSrv": old,
-				})
-				return nil
-			}
-		}
-	} else {
-		client.remoteClient.RegisterRequestFunc(ReqNotifyConsumerIdsChanged, func(req *remote.RemotingCommand, addr net.Addr) *remote.RemotingCommand {
-			rlog.Info("receive broker's notification to consumer group", map[string]interface{}{
-				rlog.LogKeyConsumerGroup: req.ExtFields["consumerGroup"],
-			})
-			client.RebalanceImmediately()
-			return nil
-		})
-		client.remoteClient.RegisterRequestFunc(ReqCheckTransactionState, func(req *remote.RemotingCommand, addr net.Addr) *remote.RemotingCommand {
-			header := new(CheckTransactionStateRequestHeader)
-			header.Decode(req.ExtFields)
-			msgExts := primitive.DecodeMessage(req.Body)
-			if len(msgExts) == 0 {
-				rlog.Warning("checkTransactionState, decode message failed", nil)
-				return nil
-			}
-			msgExt := msgExts[0]
-			// TODO: add namespace support
-			transactionID := msgExt.GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex)
-			if len(transactionID) > 0 {
-				msgExt.TransactionId = transactionID
-			}
-			group := msgExt.GetProperty(primitive.PropertyProducerGroup)
-			if group == "" {
-				rlog.Warning("checkTransactionState, pick producer group failed", nil)
-				return nil
-			}
-			if option.GroupName != group {
-				rlog.Warning("producer group is not equal", nil)
-				return nil
-			}
-			callback := &CheckTransactionStateCallback{
-				Addr:   addr,
-				Msg:    msgExt,
-				Header: *header,
-			}
-			callbackCh <- callback
-			return nil
-		})
-
-		client.remoteClient.RegisterRequestFunc(ReqGetConsumerRunningInfo, func(req *remote.RemotingCommand, addr net.Addr) *remote.RemotingCommand {
-			rlog.Info("receive get consumer running info request...", nil)
-			header := new(GetConsumerRunningInfoHeader)
-			header.Decode(req.ExtFields)
-			val, exist := clientMap.Load(header.clientID)
-			res := remote.NewRemotingCommand(ResError, nil, nil)
-			if !exist {
-				res.Remark = fmt.Sprintf("Can't find specified client instance of: %s", header.clientID)
-			} else {
-				cli, ok := val.(*rmqClient)
-				var runningInfo *ConsumerRunningInfo
-				if ok {
-					runningInfo = cli.getConsumerRunningInfo(header.consumerGroup)
-				}
-				if runningInfo != nil {
-					res.Code = ResSuccess
-					data, err := runningInfo.Encode()
-					if err != nil {
-						res.Remark = fmt.Sprintf("json marshal error: %s", err.Error())
-					} else {
-						res.Body = data
-					}
-				} else {
-					res.Remark = "there is unexpected error when get running info, please check log"
-				}
-			}
-			return res
-		})
-
-		client.remoteClient.RegisterRequestFunc(ReqConsumeMessageDirectly, func(req *remote.RemotingCommand, addr net.Addr) *remote.RemotingCommand {
-			rlog.Info("receive consume message directly request...", nil)
-			header := new(ConsumeMessageDirectlyHeader)
-			header.Decode(req.ExtFields)
-			val, exist := clientMap.Load(header.clientID)
-			res := remote.NewRemotingCommand(ResError, nil, nil)
-			if !exist {
-				res.Remark = fmt.Sprintf("Can't find specified client instance of: %s", header.clientID)
-			} else {
-				cli, ok := val.(*rmqClient)
-				msg := primitive.DecodeMessage(req.Body)[0]
-				var consumeMessageDirectlyResult *ConsumeMessageDirectlyResult
-				if ok {
-					consumeMessageDirectlyResult = cli.consumeMessageDirectly(msg, header.consumerGroup, header.brokerName)
-				}
-				if consumeMessageDirectlyResult != nil {
-					res.Code = ResSuccess
-					data, err := consumeMessageDirectlyResult.Encode()
-					if err != nil {
-						res.Remark = fmt.Sprintf("json marshal error: %s", err.Error())
-					} else {
-						res.Body = data
-					}
-				} else {
-					res.Remark = "there is unexpected error when consume message directly, please check log"
-				}
-			}
-			return res
-		})
-
-		client.remoteClient.RegisterRequestFunc(ReqResetConsumerOffset, func(req *remote.RemotingCommand, addr net.Addr) *remote.RemotingCommand {
-			rlog.Info("receive reset consumer offset request...", map[string]interface{}{
-				rlog.LogKeyBroker:        addr.String(),
-				rlog.LogKeyTopic:         req.ExtFields["topic"],
-				rlog.LogKeyConsumerGroup: req.ExtFields["group"],
-				rlog.LogKeyTimeStamp:     req.ExtFields["timestamp"],
-			})
-			header := new(ResetOffsetHeader)
-			header.Decode(req.ExtFields)
-
-			body := new(ResetOffsetBody)
-			body.Decode(req.Body)
-
-			client.resetOffset(header.topic, header.group, body.OffsetTable)
-			return nil
-		})
-	}
-	return client
-}
-
-func (c *rmqClient) Start() {
-	//ctx, cancel := context.WithCancel(context.Background())
-	//c.cancel = cancel
-	c.once.Do(func() {
-		if !c.option.Credentials.IsEmpty() {
-			c.remoteClient.RegisterInterceptor(remote.ACLInterceptor(c.option.Credentials))
-		}
-		go primitive.WithRecover(func() {
-			op := func() {
-				c.GetNameSrv().UpdateNameServerAddress()
-			}
-			time.Sleep(10 * time.Second)
-			op()
-
-			ticker := time.NewTicker(2 * time.Minute)
-			defer ticker.Stop()
-			for {
-				select {
-				case <-ticker.C:
-					op()
-				case <-c.done:
-					rlog.Info("The RMQClient stopping update name server domain info.", map[string]interface{}{
-						"clientID": c.ClientID(),
-					})
-					return
-				}
-			}
-		})
-
-		// schedule update route info
-		go primitive.WithRecover(func() {
-			// delay
-			op := func() {
-				c.UpdateTopicRouteInfo()
-			}
-			time.Sleep(10 * time.Millisecond)
-			op()
-
-			ticker := time.NewTicker(_PullNameServerInterval)
-			defer ticker.Stop()
-			for {
-				select {
-				case <-ticker.C:
-					op()
-				case <-c.done:
-					rlog.Info("The RMQClient stopping update topic route info.", map[string]interface{}{
-						"clientID": c.ClientID(),
-					})
-					return
-				}
-			}
-		})
-
-		go primitive.WithRecover(func() {
-			op := func() {
-				c.GetNameSrv().cleanOfflineBroker()
-				c.SendHeartbeatToAllBrokerWithLock()
-			}
-
-			time.Sleep(time.Second)
-			op()
-
-			ticker := time.NewTicker(_HeartbeatBrokerInterval)
-			defer ticker.Stop()
-			for {
-				select {
-				case <-ticker.C:
-					op()
-				case <-c.done:
-					rlog.Info("The RMQClient stopping clean off line broker and heart beat", map[string]interface{}{
-						"clientID": c.ClientID(),
-					})
-					return
-				}
-			}
-		})
-
-		// schedule persist offset
-		go primitive.WithRecover(func() {
-			op := func() {
-				c.consumerMap.Range(func(key, value interface{}) bool {
-					consumer := value.(InnerConsumer)
-					err := consumer.PersistConsumerOffset()
-					if err != nil {
-						rlog.Error("persist offset failed", map[string]interface{}{
-							rlog.LogKeyUnderlayError: err,
-						})
-					}
-					return true
-				})
-			}
-			time.Sleep(10 * time.Second)
-			op()
-
-			ticker := time.NewTicker(_PersistOffsetInterval)
-			defer ticker.Stop()
-			for {
-				select {
-				case <-ticker.C:
-					op()
-				case <-c.done:
-					rlog.Info("The RMQClient stopping persist offset", map[string]interface{}{
-						"clientID": c.ClientID(),
-					})
-					return
-				}
-			}
-		})
-
-		go primitive.WithRecover(func() {
-			ticker := time.NewTicker(_RebalanceInterval)
-			defer ticker.Stop()
-			for {
-				select {
-				case <-ticker.C:
-					c.RebalanceImmediately()
-				case <-c.done:
-					rlog.Info("The RMQClient stopping do rebalance", map[string]interface{}{
-						"clientID": c.ClientID(),
-					})
-					return
-				}
-			}
-		})
-	})
-}
-
-func (c *rmqClient) removeClient() {
-	rlog.Info("will remove client from clientMap", map[string]interface{}{
-		"clientID": c.ClientID(),
-	})
-	clientMap.Delete(c.ClientID())
-}
-
-func (c *rmqClient) Shutdown() {
-	c.shutdownOnce.Do(func() {
-		close(c.done)
-		c.close = true
-		c.remoteClient.ShutDown()
-		c.removeClient()
-	})
-}
-
-func (c *rmqClient) ClientID() string {
-	id := c.option.ClientIP + "@"
-	if c.option.InstanceName == "DEFAULT" {
-		id += strconv.Itoa(os.Getpid())
-	} else {
-		id += c.option.InstanceName
-	}
-	if c.option.UnitName != "" {
-		id += "@" + c.option.UnitName
-	}
-	return id
-}
-
-func (c *rmqClient) InvokeSync(ctx context.Context, addr string, request *remote.RemotingCommand,
-	timeoutMillis time.Duration) (*remote.RemotingCommand, error) {
-	if c.close {
-		return nil, ErrServiceState
-	}
-	var cancel context.CancelFunc
-	ctx, cancel = context.WithTimeout(ctx, timeoutMillis)
-	defer cancel()
-	return c.remoteClient.InvokeSync(ctx, addr, request)
-}
-
-func (c *rmqClient) InvokeAsync(ctx context.Context, addr string, request *remote.RemotingCommand,
-	f func(*remote.RemotingCommand, error)) error {
-	if c.close {
-		return ErrServiceState
-	}
-	return c.remoteClient.InvokeAsync(ctx, addr, request, func(future *remote.ResponseFuture) {
-		f(future.ResponseCommand, future.Err)
-	})
-
-}
-
-func (c *rmqClient) InvokeOneWay(ctx context.Context, addr string, request *remote.RemotingCommand,
-	timeoutMillis time.Duration) error {
-	if c.close {
-		return ErrServiceState
-	}
-	return c.remoteClient.InvokeOneWay(ctx, addr, request)
-}
-
-func (c *rmqClient) CheckClientInBroker() {
-}
-
-// TODO
-func (c *rmqClient) SendHeartbeatToAllBrokerWithLock() {
-	c.hbMutex.Lock()
-	defer c.hbMutex.Unlock()
-	hbData := NewHeartbeatData(c.ClientID())
-
-	c.producerMap.Range(func(key, value interface{}) bool {
-		pData := producerData{
-			GroupName: key.(string),
-		}
-		hbData.ProducerDatas.Add(pData)
-		return true
-	})
-
-	c.consumerMap.Range(func(key, value interface{}) bool {
-		consumer := value.(InnerConsumer)
-		cData := consumerData{
-			GroupName:         key.(string),
-			CType:             consumeType(consumer.GetcType()),
-			MessageModel:      strings.ToUpper(consumer.GetModel()),
-			Where:             consumer.GetWhere(),
-			UnitMode:          consumer.IsUnitMode(),
-			SubscriptionDatas: consumer.SubscriptionDataList(),
-		}
-		hbData.ConsumerDatas.Add(cData)
-		return true
-	})
-	if hbData.ProducerDatas.Len() == 0 && hbData.ConsumerDatas.Len() == 0 {
-		rlog.Info("sending heartbeat, but no producer and no consumer", nil)
-		return
-	}
-	c.GetNameSrv().(*namesrvs).brokerAddressesMap.Range(func(key, value interface{}) bool {
-		brokerName := key.(string)
-		data := value.(*BrokerData)
-		for id, addr := range data.BrokerAddresses {
-			rlog.Debug("try to send heart beat to broker", map[string]interface{}{
-				"brokerName": brokerName,
-				"brokerId":   id,
-				"brokerAddr": addr,
-			})
-			if hbData.ConsumerDatas.Len() == 0 && id != 0 {
-				rlog.Debug("notice, will not send heart beat to broker", map[string]interface{}{
-					"brokerName": brokerName,
-					"brokerId":   id,
-					"brokerAddr": addr,
-				})
-				continue
-			}
-			cmd := remote.NewRemotingCommand(ReqHeartBeat, nil, hbData.encode())
-
-			ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
-			response, err := c.remoteClient.InvokeSync(ctx, addr, cmd)
-			if err != nil {
-				cancel()
-				rlog.Warning("send heart beat to broker error", map[string]interface{}{
-					rlog.LogKeyUnderlayError: err,
-				})
-				return true
-			}
-			cancel()
-			if response.Code == ResSuccess {
-				c.GetNameSrv().(*namesrvs).AddBrokerVersion(brokerName, addr, int32(response.Version))
-				rlog.Debug("send heart beat to broker success", map[string]interface{}{
-					"brokerName": brokerName,
-					"brokerId":   id,
-					"brokerAddr": addr,
-				})
-			} else {
-				rlog.Warning("send heart beat to broker failed", map[string]interface{}{
-					"brokerName":   brokerName,
-					"brokerId":     id,
-					"brokerAddr":   addr,
-					"responseCode": response.Code,
-				})
-			}
-		}
-		return true
-	})
-}
-
-func (c *rmqClient) UpdateTopicRouteInfo() {
-	publishTopicSet := make(map[string]bool, 0)
-	c.producerMap.Range(func(key, value interface{}) bool {
-		producer := value.(InnerProducer)
-		list := producer.PublishTopicList()
-		for idx := range list {
-			publishTopicSet[list[idx]] = true
-		}
-		return true
-	})
-	for topic := range publishTopicSet {
-		data, changed, _ := c.GetNameSrv().UpdateTopicRouteInfo(topic)
-		c.UpdatePublishInfo(topic, data, changed)
-	}
-
-	subscribedTopicSet := make(map[string]bool, 0)
-	c.consumerMap.Range(func(key, value interface{}) bool {
-		consumer := value.(InnerConsumer)
-		list := consumer.SubscriptionDataList()
-		for idx := range list {
-			subscribedTopicSet[list[idx].Topic] = true
-		}
-		return true
-	})
-
-	for topic := range subscribedTopicSet {
-		data, changed, _ := c.GetNameSrv().UpdateTopicRouteInfo(topic)
-		c.updateSubscribeInfo(topic, data, changed)
-	}
-}
-
-func (c *rmqClient) ProcessSendResponse(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) error {
-	var status primitive.SendStatus
-	switch cmd.Code {
-	case ResFlushDiskTimeout:
-		status = primitive.SendFlushDiskTimeout
-	case ResFlushSlaveTimeout:
-		status = primitive.SendFlushSlaveTimeout
-	case ResSlaveNotAvailable:
-		status = primitive.SendSlaveNotAvailable
-	case ResSuccess:
-		status = primitive.SendOK
-	default:
-		status = primitive.SendUnknownError
-		return errors.New(cmd.Remark)
-	}
-
-	msgIDs := make([]string, 0)
-	for i := 0; i < len(msgs); i++ {
-		msgIDs = append(msgIDs, msgs[i].GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex))
-	}
-	uniqueMsgId := strings.Join(msgIDs, ",")
-
-	regionId := cmd.ExtFields[primitive.PropertyMsgRegion]
-	trace := cmd.ExtFields[primitive.PropertyTraceSwitch]
-
-	if regionId == "" {
-		regionId = defaultTraceRegionID
-	}
-
-	qId, _ := strconv.Atoi(cmd.ExtFields["queueId"])
-	off, _ := strconv.ParseInt(cmd.ExtFields["queueOffset"], 10, 64)
-
-	resp.Status = status
-	resp.MsgID = uniqueMsgId
-	resp.OffsetMsgID = cmd.ExtFields["msgId"]
-	resp.MessageQueue = &primitive.MessageQueue{
-		Topic:      msgs[0].Topic,
-		BrokerName: brokerName,
-		QueueId:    qId,
-	}
-	resp.QueueOffset = off
-	resp.TransactionID = cmd.ExtFields["transactionId"]
-	resp.RegionID = regionId
-	resp.TraceOn = trace != "" && trace != _TraceOff
-	return nil
-}
-
-// PullMessage with sync
-func (c *rmqClient) PullMessage(ctx context.Context, brokerAddrs string, request *PullMessageRequestHeader) (*primitive.PullResult, error) {
-	cmd := remote.NewRemotingCommand(ReqPullMessage, request, nil)
-	var cancel context.CancelFunc
-	ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
-	defer cancel()
-	res, err := c.remoteClient.InvokeSync(ctx, brokerAddrs, cmd)
-	if err != nil {
-		return nil, err
-	}
-
-	return c.processPullResponse(res)
-}
-
-func (c *rmqClient) processPullResponse(response *remote.RemotingCommand) (*primitive.PullResult, error) {
-
-	pullResult := &primitive.PullResult{}
-	switch response.Code {
-	case ResSuccess:
-		pullResult.Status = primitive.PullFound
-	case ResPullNotFound:
-		pullResult.Status = primitive.PullNoNewMsg
-	case ResPullRetryImmediately:
-		pullResult.Status = primitive.PullNoMsgMatched
-	case ResPullOffsetMoved:
-		pullResult.Status = primitive.PullOffsetIllegal
-	default:
-		return nil, fmt.Errorf("unknown Response Code: %d, remark: %s", response.Code, response.Remark)
-	}
-
-	c.decodeCommandCustomHeader(pullResult, response)
-	pullResult.SetBody(response.Body)
-
-	return pullResult, nil
-}
-
-func (c *rmqClient) decodeCommandCustomHeader(pr *primitive.PullResult, cmd *remote.RemotingCommand) {
-	v, exist := cmd.ExtFields["maxOffset"]
-	if exist {
-		pr.MaxOffset, _ = strconv.ParseInt(v, 10, 64)
-	}
-
-	v, exist = cmd.ExtFields["minOffset"]
-	if exist {
-		pr.MinOffset, _ = strconv.ParseInt(v, 10, 64)
-	}
-
-	v, exist = cmd.ExtFields["nextBeginOffset"]
-	if exist {
-		pr.NextBeginOffset, _ = strconv.ParseInt(v, 10, 64)
-	}
-
-	v, exist = cmd.ExtFields["suggestWhichBrokerId"]
-	if exist {
-		pr.SuggestWhichBrokerId, _ = strconv.ParseInt(v, 10, 64)
-	}
-}
-
-func (c *rmqClient) RegisterConsumer(group string, consumer InnerConsumer) error {
-	_, exist := c.consumerMap.Load(group)
-	if exist {
-		rlog.Warning("the consumer group exist already", map[string]interface{}{
-			rlog.LogKeyConsumerGroup: group,
-		})
-		return fmt.Errorf("the consumer group exist already")
-	}
-	c.consumerMap.Store(group, consumer)
-	return nil
-}
-
-func (c *rmqClient) UnregisterConsumer(group string) {
-	c.consumerMap.Delete(group)
-}
-
-func (c *rmqClient) RegisterProducer(group string, producer InnerProducer) error {
-	_, loaded := c.producerMap.LoadOrStore(group, producer)
-	if loaded {
-		return fmt.Errorf("the producer group \"%s\" has been created, specify another one", c.option.GroupName)
-	}
-	return nil
-}
-
-func (c *rmqClient) UnregisterProducer(group string) {
-	c.producerMap.Delete(group)
-}
-
-func (c *rmqClient) RebalanceImmediately() {
-	c.rbMutex.Lock()
-	defer c.rbMutex.Unlock()
-	c.consumerMap.Range(func(key, value interface{}) bool {
-		consumer := value.(InnerConsumer)
-		consumer.Rebalance()
-		return true
-	})
-}
-
-func (c *rmqClient) UpdatePublishInfo(topic string, data *TopicRouteData, changed bool) {
-	if data == nil {
-		return
-	}
-
-	c.producerMap.Range(func(key, value interface{}) bool {
-		p := value.(InnerProducer)
-		updated := changed
-		if !updated {
-			updated = p.IsPublishTopicNeedUpdate(topic)
-		}
-		if updated {
-			publishInfo := c.GetNameSrv().(*namesrvs).routeData2PublishInfo(topic, data)
-			publishInfo.HaveTopicRouterInfo = true
-			p.UpdateTopicPublishInfo(topic, publishInfo)
-		}
-		return true
-	})
-}
-
-func (c *rmqClient) updateSubscribeInfo(topic string, data *TopicRouteData, changed bool) {
-	if data == nil {
-		return
-	}
-	c.consumerMap.Range(func(key, value interface{}) bool {
-		consumer := value.(InnerConsumer)
-		updated := changed
-		if !updated {
-			updated = consumer.IsSubscribeTopicNeedUpdate(topic)
-		}
-		if updated {
-			consumer.UpdateTopicSubscribeInfo(topic, routeData2SubscribeInfo(topic, data))
-		}
-
-		return true
-	})
-}
-
-func (c *rmqClient) isNeedUpdateSubscribeInfo(topic string) bool {
-	var result bool
-	c.consumerMap.Range(func(key, value interface{}) bool {
-		consumer := value.(InnerConsumer)
-		if consumer.IsSubscribeTopicNeedUpdate(topic) {
-			result = true
-			return false
-		}
-		return true
-	})
-	return result
-}
-
-func (c *rmqClient) resetOffset(topic string, group string, offsetTable map[primitive.MessageQueue]int64) {
-	consumer, exist := c.consumerMap.Load(group)
-	if !exist {
-		rlog.Warning("group "+group+" do not exists", nil)
-		return
-	}
-	consumer.(InnerConsumer).ResetOffset(topic, offsetTable)
-}
-
-func (c *rmqClient) getConsumerRunningInfo(group string) *ConsumerRunningInfo {
-	consumer, exist := c.consumerMap.Load(group)
-	if !exist {
-		return nil
-	}
-	info := consumer.(InnerConsumer).GetConsumerRunningInfo()
-	if info != nil {
-		info.Properties[PropClientVersion] = clientVersion
-	}
-	return info
-}
-
-func (c *rmqClient) consumeMessageDirectly(msg *primitive.MessageExt, group string, brokerName string) *ConsumeMessageDirectlyResult {
-	consumer, exist := c.consumerMap.Load(group)
-	if !exist {
-		return nil
-	}
-	res := consumer.(InnerConsumer).ConsumeMessageDirectly(msg, brokerName)
-	return res
-}
-
-func routeData2SubscribeInfo(topic string, data *TopicRouteData) []*primitive.MessageQueue {
-	list := make([]*primitive.MessageQueue, 0)
-	for idx := range data.QueueDataList {
-		qd := data.QueueDataList[idx]
-		if queueIsReadable(qd.Perm) {
-			for i := 0; i < qd.ReadQueueNums; i++ {
-				list = append(list, &primitive.MessageQueue{
-					Topic:      topic,
-					BrokerName: qd.BrokerName,
-					QueueId:    i,
-				})
-			}
-		}
-	}
-	return list
-}
-
-func brokerVIPChannel(brokerAddr string) string {
-	if !_VIPChannelEnable {
-		return brokerAddr
-	}
-	var brokerAddrNew strings.Builder
-	ipAndPort := strings.Split(brokerAddr, ":")
-	port, err := strconv.Atoi(ipAndPort[1])
-	if err != nil {
-		return ""
-	}
-	brokerAddrNew.WriteString(ipAndPort[0])
-	brokerAddrNew.WriteString(":")
-	brokerAddrNew.WriteString(strconv.Itoa(port - 2))
-	return brokerAddrNew.String()
-}
diff --git a/internal/constants.go b/internal/constants.go
deleted file mode 100644
index e2e911f..0000000
--- a/internal/constants.go
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-const (
-	RetryGroupTopicPrefix    = "%RETRY%"
-	DefaultConsumerGroup     = "DEFAULT_CONSUMER"
-	ClientInnerProducerGroup = "CLIENT_INNER_PRODUCER"
-	SystemTopicPrefix        = "rmq_sys_"
-)
-
-func GetRetryTopic(group string) string {
-	return RetryGroupTopicPrefix + group
-}
diff --git a/internal/mock_client.go b/internal/mock_client.go
deleted file mode 100644
index c975038..0000000
--- a/internal/mock_client.go
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by MockGen. DO NOT EDIT.
-// Source: client.go
-
-// Package internal is a generated GoMock package.
-package internal
-
-import (
-	"context"
-	"reflect"
-	"time"
-
-	"github.com/golang/mock/gomock"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-// MockInnerProducer is a mock of InnerProducer interface
-type MockInnerProducer struct {
-	ctrl     *gomock.Controller
-	recorder *MockInnerProducerMockRecorder
-}
-
-// MockInnerProducerMockRecorder is the mock recorder for MockInnerProducer
-type MockInnerProducerMockRecorder struct {
-	mock *MockInnerProducer
-}
-
-// NewMockInnerProducer creates a new mock instance
-func NewMockInnerProducer(ctrl *gomock.Controller) *MockInnerProducer {
-	mock := &MockInnerProducer{ctrl: ctrl}
-	mock.recorder = &MockInnerProducerMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockInnerProducer) EXPECT() *MockInnerProducerMockRecorder {
-	return m.recorder
-}
-
-// PublishTopicList mocks base method
-func (m *MockInnerProducer) PublishTopicList() []string {
-	ret := m.ctrl.Call(m, "PublishTopicList")
-	ret0, _ := ret[0].([]string)
-	return ret0
-}
-
-// PublishTopicList indicates an expected call of PublishTopicList
-func (mr *MockInnerProducerMockRecorder) PublishTopicList() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishTopicList", reflect.TypeOf((*MockInnerProducer)(nil).PublishTopicList))
-}
-
-// UpdateTopicPublishInfo mocks base method
-func (m *MockInnerProducer) UpdateTopicPublishInfo(topic string, info *TopicPublishInfo) {
-	m.ctrl.Call(m, "UpdateTopicPublishInfo", topic, info)
-}
-
-// UpdateTopicPublishInfo indicates an expected call of UpdateTopicPublishInfo
-func (mr *MockInnerProducerMockRecorder) UpdateTopicPublishInfo(topic, info interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTopicPublishInfo", reflect.TypeOf((*MockInnerProducer)(nil).UpdateTopicPublishInfo), topic, info)
-}
-
-// IsPublishTopicNeedUpdate mocks base method
-func (m *MockInnerProducer) IsPublishTopicNeedUpdate(topic string) bool {
-	ret := m.ctrl.Call(m, "IsPublishTopicNeedUpdate", topic)
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// IsPublishTopicNeedUpdate indicates an expected call of IsPublishTopicNeedUpdate
-func (mr *MockInnerProducerMockRecorder) IsPublishTopicNeedUpdate(topic interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPublishTopicNeedUpdate", reflect.TypeOf((*MockInnerProducer)(nil).IsPublishTopicNeedUpdate), topic)
-}
-
-// IsUnitMode mocks base method
-func (m *MockInnerProducer) IsUnitMode() bool {
-	ret := m.ctrl.Call(m, "IsUnitMode")
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// IsUnitMode indicates an expected call of IsUnitMode
-func (mr *MockInnerProducerMockRecorder) IsUnitMode() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUnitMode", reflect.TypeOf((*MockInnerProducer)(nil).IsUnitMode))
-}
-
-// MockInnerConsumer is a mock of InnerConsumer interface
-type MockInnerConsumer struct {
-	ctrl     *gomock.Controller
-	recorder *MockInnerConsumerMockRecorder
-}
-
-// MockInnerConsumerMockRecorder is the mock recorder for MockInnerConsumer
-type MockInnerConsumerMockRecorder struct {
-	mock *MockInnerConsumer
-}
-
-// NewMockInnerConsumer creates a new mock instance
-func NewMockInnerConsumer(ctrl *gomock.Controller) *MockInnerConsumer {
-	mock := &MockInnerConsumer{ctrl: ctrl}
-	mock.recorder = &MockInnerConsumerMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockInnerConsumer) EXPECT() *MockInnerConsumerMockRecorder {
-	return m.recorder
-}
-
-// PersistConsumerOffset mocks base method
-func (m *MockInnerConsumer) PersistConsumerOffset() error {
-	ret := m.ctrl.Call(m, "PersistConsumerOffset")
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// PersistConsumerOffset indicates an expected call of PersistConsumerOffset
-func (mr *MockInnerConsumerMockRecorder) PersistConsumerOffset() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistConsumerOffset", reflect.TypeOf((*MockInnerConsumer)(nil).PersistConsumerOffset))
-}
-
-// UpdateTopicSubscribeInfo mocks base method
-func (m *MockInnerConsumer) UpdateTopicSubscribeInfo(topic string, mqs []*primitive.MessageQueue) {
-	m.ctrl.Call(m, "UpdateTopicSubscribeInfo", topic, mqs)
-}
-
-// UpdateTopicSubscribeInfo indicates an expected call of UpdateTopicSubscribeInfo
-func (mr *MockInnerConsumerMockRecorder) UpdateTopicSubscribeInfo(topic, mqs interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTopicSubscribeInfo", reflect.TypeOf((*MockInnerConsumer)(nil).UpdateTopicSubscribeInfo), topic, mqs)
-}
-
-// IsSubscribeTopicNeedUpdate mocks base method
-func (m *MockInnerConsumer) IsSubscribeTopicNeedUpdate(topic string) bool {
-	ret := m.ctrl.Call(m, "IsSubscribeTopicNeedUpdate", topic)
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// IsSubscribeTopicNeedUpdate indicates an expected call of IsSubscribeTopicNeedUpdate
-func (mr *MockInnerConsumerMockRecorder) IsSubscribeTopicNeedUpdate(topic interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSubscribeTopicNeedUpdate", reflect.TypeOf((*MockInnerConsumer)(nil).IsSubscribeTopicNeedUpdate), topic)
-}
-
-// SubscriptionDataList mocks base method
-func (m *MockInnerConsumer) SubscriptionDataList() []*SubscriptionData {
-	ret := m.ctrl.Call(m, "SubscriptionDataList")
-	ret0, _ := ret[0].([]*SubscriptionData)
-	return ret0
-}
-
-// SubscriptionDataList indicates an expected call of SubscriptionDataList
-func (mr *MockInnerConsumerMockRecorder) SubscriptionDataList() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscriptionDataList", reflect.TypeOf((*MockInnerConsumer)(nil).SubscriptionDataList))
-}
-
-// Rebalance mocks base method
-func (m *MockInnerConsumer) Rebalance() {
-	m.ctrl.Call(m, "Rebalance")
-}
-
-// Rebalance indicates an expected call of Rebalance
-func (mr *MockInnerConsumerMockRecorder) Rebalance() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rebalance", reflect.TypeOf((*MockInnerConsumer)(nil).Rebalance))
-}
-
-// IsUnitMode mocks base method
-func (m *MockInnerConsumer) IsUnitMode() bool {
-	ret := m.ctrl.Call(m, "IsUnitMode")
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// IsUnitMode indicates an expected call of IsUnitMode
-func (mr *MockInnerConsumerMockRecorder) IsUnitMode() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUnitMode", reflect.TypeOf((*MockInnerConsumer)(nil).IsUnitMode))
-}
-
-// GetConsumerRunningInfo mocks base method
-func (m *MockInnerConsumer) GetConsumerRunningInfo() *ConsumerRunningInfo {
-	ret := m.ctrl.Call(m, "GetConsumerRunningInfo")
-	ret0, _ := ret[0].(*ConsumerRunningInfo)
-	return ret0
-}
-
-// GetConsumerRunningInfo indicates an expected call of GetConsumerRunningInfo
-func (mr *MockInnerConsumerMockRecorder) GetConsumerRunningInfo() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConsumerRunningInfo", reflect.TypeOf((*MockInnerConsumer)(nil).GetConsumerRunningInfo))
-}
-
-// MockRMQClient is a mock of RMQClient interface
-type MockRMQClient struct {
-	ctrl     *gomock.Controller
-	recorder *MockRMQClientMockRecorder
-	Namesrv  *MockNamesrvs
-}
-
-func (m *MockRMQClient) GetNameSrv() Namesrvs {
-	return m.Namesrv
-}
-
-func (m *MockRMQClient) SetNameSrv(mockNamesrvs *MockNamesrvs) {
-	m.Namesrv = mockNamesrvs
-}
-
-// MockRMQClientMockRecorder is the mock recorder for MockRMQClient
-type MockRMQClientMockRecorder struct {
-	mock *MockRMQClient
-}
-
-// NewMockRMQClient creates a new mock instance
-func NewMockRMQClient(ctrl *gomock.Controller) *MockRMQClient {
-	mock := &MockRMQClient{ctrl: ctrl}
-	mock.recorder = &MockRMQClientMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockRMQClient) EXPECT() *MockRMQClientMockRecorder {
-	return m.recorder
-}
-
-// Start mocks base method
-func (m *MockRMQClient) Start() {
-	m.ctrl.Call(m, "Start")
-}
-
-// Start indicates an expected call of Start
-func (mr *MockRMQClientMockRecorder) Start() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockRMQClient)(nil).Start))
-}
-
-// Shutdown mocks base method
-func (m *MockRMQClient) Shutdown() {
-	m.ctrl.Call(m, "Shutdown")
-}
-
-// Shutdown indicates an expected call of Shutdown
-func (mr *MockRMQClientMockRecorder) Shutdown() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockRMQClient)(nil).Shutdown))
-}
-
-// ClientID mocks base method
-func (m *MockRMQClient) ClientID() string {
-	ret := m.ctrl.Call(m, "ClientID")
-	ret0, _ := ret[0].(string)
-	return ret0
-}
-
-// ClientID indicates an expected call of ClientID
-func (mr *MockRMQClientMockRecorder) ClientID() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientID", reflect.TypeOf((*MockRMQClient)(nil).ClientID))
-}
-
-// RegisterProducer mocks base method
-func (m *MockRMQClient) RegisterProducer(group string, producer InnerProducer) error {
-	ret := m.ctrl.Call(m, "RegisterProducer", group, producer)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// RegisterProducer indicates an expected call of RegisterProducer
-func (mr *MockRMQClientMockRecorder) RegisterProducer(group, producer interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProducer", reflect.TypeOf((*MockRMQClient)(nil).RegisterProducer), group, producer)
-}
-
-// UnregisterProducer mocks base method
-func (m *MockRMQClient) UnregisterProducer(group string) {
-	m.ctrl.Call(m, "UnregisterProducer", group)
-}
-
-// UnregisterProducer indicates an expected call of UnregisterProducer
-func (mr *MockRMQClientMockRecorder) UnregisterProducer(group interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnregisterProducer", reflect.TypeOf((*MockRMQClient)(nil).UnregisterProducer), group)
-}
-
-// InvokeSync mocks base method
-func (m *MockRMQClient) InvokeSync(ctx context.Context, addr string, request *remote.RemotingCommand, timeoutMillis time.Duration) (*remote.RemotingCommand, error) {
-	ret := m.ctrl.Call(m, "InvokeSync", ctx, addr, request, timeoutMillis)
-	ret0, _ := ret[0].(*remote.RemotingCommand)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// InvokeSync indicates an expected call of InvokeSync
-func (mr *MockRMQClientMockRecorder) InvokeSync(ctx, addr, request, timeoutMillis interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeSync", reflect.TypeOf((*MockRMQClient)(nil).InvokeSync), ctx, addr, request, timeoutMillis)
-}
-
-// InvokeAsync mocks base method
-func (m *MockRMQClient) InvokeAsync(ctx context.Context, addr string, request *remote.RemotingCommand, f func(*remote.RemotingCommand, error)) error {
-	ret := m.ctrl.Call(m, "InvokeAsync", ctx, addr, request, f)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// InvokeAsync indicates an expected call of InvokeAsync
-func (mr *MockRMQClientMockRecorder) InvokeAsync(ctx, addr, request, f interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeAsync", reflect.TypeOf((*MockRMQClient)(nil).InvokeAsync), ctx, addr, request, f)
-}
-
-// InvokeOneWay mocks base method
-func (m *MockRMQClient) InvokeOneWay(ctx context.Context, addr string, request *remote.RemotingCommand, timeoutMillis time.Duration) error {
-	ret := m.ctrl.Call(m, "InvokeOneWay", ctx, addr, request, timeoutMillis)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// InvokeOneWay indicates an expected call of InvokeOneWay
-func (mr *MockRMQClientMockRecorder) InvokeOneWay(ctx, addr, request, timeoutMillis interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeOneWay", reflect.TypeOf((*MockRMQClient)(nil).InvokeOneWay), ctx, addr, request, timeoutMillis)
-}
-
-// CheckClientInBroker mocks base method
-func (m *MockRMQClient) CheckClientInBroker() {
-	m.ctrl.Call(m, "CheckClientInBroker")
-}
-
-// CheckClientInBroker indicates an expected call of CheckClientInBroker
-func (mr *MockRMQClientMockRecorder) CheckClientInBroker() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckClientInBroker", reflect.TypeOf((*MockRMQClient)(nil).CheckClientInBroker))
-}
-
-// SendHeartbeatToAllBrokerWithLock mocks base method
-func (m *MockRMQClient) SendHeartbeatToAllBrokerWithLock() {
-	m.ctrl.Call(m, "SendHeartbeatToAllBrokerWithLock")
-}
-
-// SendHeartbeatToAllBrokerWithLock indicates an expected call of SendHeartbeatToAllBrokerWithLock
-func (mr *MockRMQClientMockRecorder) SendHeartbeatToAllBrokerWithLock() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendHeartbeatToAllBrokerWithLock", reflect.TypeOf((*MockRMQClient)(nil).SendHeartbeatToAllBrokerWithLock))
-}
-
-// UpdateTopicRouteInfo mocks base method
-func (m *MockRMQClient) UpdateTopicRouteInfo() {
-	m.ctrl.Call(m, "UpdateTopicRouteInfo")
-}
-
-// UpdateTopicRouteInfo indicates an expected call of UpdateTopicRouteInfo
-func (mr *MockRMQClientMockRecorder) UpdateTopicRouteInfo() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTopicRouteInfo", reflect.TypeOf((*MockRMQClient)(nil).UpdateTopicRouteInfo))
-}
-
-// ProcessSendResponse mocks base method
-func (m *MockRMQClient) ProcessSendResponse(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) error {
-	varargs := []interface{}{brokerName, cmd, resp}
-	for _, a := range msgs {
-		varargs = append(varargs, a)
-	}
-	ret := m.ctrl.Call(m, "ProcessSendResponse", varargs...)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// ProcessSendResponse indicates an expected call of ProcessSendResponse
-func (mr *MockRMQClientMockRecorder) ProcessSendResponse(brokerName, cmd, resp interface{}, msgs ...interface{}) *gomock.Call {
-	varargs := append([]interface{}{brokerName, cmd, resp}, msgs...)
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessSendResponse", reflect.TypeOf((*MockRMQClient)(nil).ProcessSendResponse), varargs...)
-}
-
-// RegisterConsumer mocks base method
-func (m *MockRMQClient) RegisterConsumer(group string, consumer InnerConsumer) error {
-	ret := m.ctrl.Call(m, "RegisterConsumer", group, consumer)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// RegisterConsumer indicates an expected call of RegisterConsumer
-func (mr *MockRMQClientMockRecorder) RegisterConsumer(group, consumer interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterConsumer", reflect.TypeOf((*MockRMQClient)(nil).RegisterConsumer), group, consumer)
-}
-
-// UnregisterConsumer mocks base method
-func (m *MockRMQClient) UnregisterConsumer(group string) {
-	m.ctrl.Call(m, "UnregisterConsumer", group)
-}
-
-// UnregisterConsumer indicates an expected call of UnregisterConsumer
-func (mr *MockRMQClientMockRecorder) UnregisterConsumer(group interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnregisterConsumer", reflect.TypeOf((*MockRMQClient)(nil).UnregisterConsumer), group)
-}
-
-// PullMessage mocks base method
-func (m *MockRMQClient) PullMessage(ctx context.Context, brokerAddrs string, request *PullMessageRequestHeader) (*primitive.PullResult, error) {
-	ret := m.ctrl.Call(m, "PullMessage", ctx, brokerAddrs, request)
-	ret0, _ := ret[0].(*primitive.PullResult)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// PullMessage indicates an expected call of PullMessage
-func (mr *MockRMQClientMockRecorder) PullMessage(ctx, brokerAddrs, request interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PullMessage", reflect.TypeOf((*MockRMQClient)(nil).PullMessage), ctx, brokerAddrs, request)
-}
-
-// RebalanceImmediately mocks base method
-func (m *MockRMQClient) RebalanceImmediately() {
-	m.ctrl.Call(m, "RebalanceImmediately")
-}
-
-// RebalanceImmediately indicates an expected call of RebalanceImmediately
-func (mr *MockRMQClientMockRecorder) RebalanceImmediately() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebalanceImmediately", reflect.TypeOf((*MockRMQClient)(nil).RebalanceImmediately))
-}
-
-// UpdatePublishInfo mocks base method
-func (m *MockRMQClient) UpdatePublishInfo(topic string, data *TopicRouteData, changed bool) {
-	m.ctrl.Call(m, "UpdatePublishInfo", topic, data, changed)
-}
-
-// UpdatePublishInfo indicates an expected call of UpdatePublishInfo
-func (mr *MockRMQClientMockRecorder) UpdatePublishInfo(topic, data, changed interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePublishInfo", reflect.TypeOf((*MockRMQClient)(nil).UpdatePublishInfo), topic, data, changed)
-}
diff --git a/internal/mock_namesrv.go b/internal/mock_namesrv.go
deleted file mode 100644
index 7ce6f97..0000000
--- a/internal/mock_namesrv.go
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-// Code generated by MockGen. DO NOT EDIT.
-// Source: namesrv.go
-
-// Package internal is a generated GoMock package.
-package internal
-
-import (
-	reflect "reflect"
-
-	primitive "github.com/apache/rocketmq-client-go/v2/primitive"
-	gomock "github.com/golang/mock/gomock"
-)
-
-// MockNamesrvs is a mock of Namesrvs interface
-type MockNamesrvs struct {
-	ctrl     *gomock.Controller
-	recorder *MockNamesrvsMockRecorder
-}
-
-func (m *MockNamesrvs) UpdateTopicRouteInfoWithDefault(topic string, defaultTopic string, defaultQueueNum int) (*TopicRouteData, bool, error) {
-	return m.UpdateTopicRouteInfo(topic)
-}
-
-// MockNamesrvsMockRecorder is the mock recorder for MockNamesrvs
-type MockNamesrvsMockRecorder struct {
-	mock *MockNamesrvs
-}
-
-// NewMockNamesrvs creates a new mock instance
-func NewMockNamesrvs(ctrl *gomock.Controller) *MockNamesrvs {
-	mock := &MockNamesrvs{ctrl: ctrl}
-	mock.recorder = &MockNamesrvsMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockNamesrvs) EXPECT() *MockNamesrvsMockRecorder {
-	return m.recorder
-}
-
-// UpdateNameServerAddress mocks base method
-func (m *MockNamesrvs) UpdateNameServerAddress() {
-	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "UpdateNameServerAddress")
-}
-
-// UpdateNameServerAddress indicates an expected call of UpdateNameServerAddress
-func (mr *MockNamesrvsMockRecorder) UpdateNameServerAddress() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateNameServerAddress", reflect.TypeOf((*MockNamesrvs)(nil).UpdateNameServerAddress))
-}
-
-// AddBroker mocks base method
-func (m *MockNamesrvs) AddBroker(routeData *TopicRouteData) {
-	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "AddBroker", routeData)
-}
-
-// AddBroker indicates an expected call of AddBroker
-func (mr *MockNamesrvsMockRecorder) AddBroker(routeData interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBroker", reflect.TypeOf((*MockNamesrvs)(nil).AddBroker), routeData)
-}
-
-// cleanOfflineBroker mocks base method
-func (m *MockNamesrvs) cleanOfflineBroker() {
-	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "cleanOfflineBroker")
-}
-
-// cleanOfflineBroker indicates an expected call of cleanOfflineBroker
-func (mr *MockNamesrvsMockRecorder) cleanOfflineBroker() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cleanOfflineBroker", reflect.TypeOf((*MockNamesrvs)(nil).cleanOfflineBroker))
-}
-
-// UpdateTopicRouteInfo mocks base method
-func (m *MockNamesrvs) UpdateTopicRouteInfo(topic string) (*TopicRouteData, bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "UpdateTopicRouteInfo", topic)
-	ret0, _ := ret[0].(*TopicRouteData)
-	ret1, _ := ret[1].(bool)
-	ret2, _ := ret[2].(error)
-	return ret0, ret1, ret2
-}
-
-// UpdateTopicRouteInfo indicates an expected call of UpdateTopicRouteInfo
-func (mr *MockNamesrvsMockRecorder) UpdateTopicRouteInfo(topic interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTopicRouteInfo", reflect.TypeOf((*MockNamesrvs)(nil).UpdateTopicRouteInfo), topic)
-}
-
-// FetchPublishMessageQueues mocks base method
-func (m *MockNamesrvs) FetchPublishMessageQueues(topic string) ([]*primitive.MessageQueue, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FetchPublishMessageQueues", topic)
-	ret0, _ := ret[0].([]*primitive.MessageQueue)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// FetchPublishMessageQueues indicates an expected call of FetchPublishMessageQueues
-func (mr *MockNamesrvsMockRecorder) FetchPublishMessageQueues(topic interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchPublishMessageQueues", reflect.TypeOf((*MockNamesrvs)(nil).FetchPublishMessageQueues), topic)
-}
-
-// FindBrokerAddrByTopic mocks base method
-func (m *MockNamesrvs) FindBrokerAddrByTopic(topic string) string {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FindBrokerAddrByTopic", topic)
-	ret0, _ := ret[0].(string)
-	return ret0
-}
-
-// FindBrokerAddrByTopic indicates an expected call of FindBrokerAddrByTopic
-func (mr *MockNamesrvsMockRecorder) FindBrokerAddrByTopic(topic interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBrokerAddrByTopic", reflect.TypeOf((*MockNamesrvs)(nil).FindBrokerAddrByTopic), topic)
-}
-
-// FindBrokerAddrByName mocks base method
-func (m *MockNamesrvs) FindBrokerAddrByName(brokerName string) string {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FindBrokerAddrByName", brokerName)
-	ret0, _ := ret[0].(string)
-	return ret0
-}
-
-// FindBrokerAddrByName indicates an expected call of FindBrokerAddrByName
-func (mr *MockNamesrvsMockRecorder) FindBrokerAddrByName(brokerName interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBrokerAddrByName", reflect.TypeOf((*MockNamesrvs)(nil).FindBrokerAddrByName), brokerName)
-}
-
-// FindBrokerAddressInSubscribe mocks base method
-func (m *MockNamesrvs) FindBrokerAddressInSubscribe(brokerName string, brokerId int64, onlyThisBroker bool) *FindBrokerResult {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FindBrokerAddressInSubscribe", brokerName, brokerId, onlyThisBroker)
-	ret0, _ := ret[0].(*FindBrokerResult)
-	return ret0
-}
-
-// FindBrokerAddressInSubscribe indicates an expected call of FindBrokerAddressInSubscribe
-func (mr *MockNamesrvsMockRecorder) FindBrokerAddressInSubscribe(brokerName, brokerId, onlyThisBroker interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBrokerAddressInSubscribe", reflect.TypeOf((*MockNamesrvs)(nil).FindBrokerAddressInSubscribe), brokerName, brokerId, onlyThisBroker)
-}
-
-// FetchSubscribeMessageQueues mocks base method
-func (m *MockNamesrvs) FetchSubscribeMessageQueues(topic string) ([]*primitive.MessageQueue, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FetchSubscribeMessageQueues", topic)
-	ret0, _ := ret[0].([]*primitive.MessageQueue)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// FetchSubscribeMessageQueues indicates an expected call of FetchSubscribeMessageQueues
-func (mr *MockNamesrvsMockRecorder) FetchSubscribeMessageQueues(topic interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchSubscribeMessageQueues", reflect.TypeOf((*MockNamesrvs)(nil).FetchSubscribeMessageQueues), topic)
-}
-
-// AddrList mocks base method
-func (m *MockNamesrvs) AddrList() []string {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "AddrList")
-	ret0, _ := ret[0].([]string)
-	return ret0
-}
-
-// AddrList indicates an expected call of AddrList
-func (mr *MockNamesrvsMockRecorder) AddrList() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrList", reflect.TypeOf((*MockNamesrvs)(nil).AddrList))
-}
diff --git a/internal/model.go b/internal/model.go
deleted file mode 100644
index 7a011d7..0000000
--- a/internal/model.go
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"github.com/tidwall/gjson"
-	"sort"
-	"strconv"
-	"strings"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	jsoniter "github.com/json-iterator/go"
-)
-
-type FindBrokerResult struct {
-	BrokerAddr    string
-	Slave         bool
-	BrokerVersion int32
-}
-
-type (
-	// groupName of consumer
-	consumeType string
-
-	ServiceState int32
-)
-
-const (
-	StateCreateJust ServiceState = iota
-	StateStartFailed
-	StateRunning
-	StateShutdown
-)
-
-type SubscriptionData struct {
-	ClassFilterMode bool      `json:"classFilterMode"`
-	Topic           string    `json:"topic"`
-	SubString       string    `json:"subString"`
-	Tags            utils.Set `json:"tagsSet"`
-	Codes           utils.Set `json:"codeSet"`
-	SubVersion      int64     `json:"subVersion"`
-	ExpType         string    `json:"expressionType"`
-}
-
-type producerData struct {
-	GroupName string `json:"groupName"`
-}
-
-func (p producerData) UniqueID() string {
-	return p.GroupName
-}
-
-type consumerData struct {
-	GroupName         string              `json:"groupName"`
-	CType             consumeType         `json:"consumeType"`
-	MessageModel      string              `json:"messageModel"`
-	Where             string              `json:"consumeFromWhere"`
-	SubscriptionDatas []*SubscriptionData `json:"subscriptionDataSet"`
-	UnitMode          bool                `json:"unitMode"`
-}
-
-func (c consumerData) UniqueID() string {
-	return c.GroupName
-}
-
-type heartbeatData struct {
-	ClientId      string    `json:"clientID"`
-	ProducerDatas utils.Set `json:"producerDataSet"`
-	ConsumerDatas utils.Set `json:"consumerDataSet"`
-}
-
-func NewHeartbeatData(clientID string) *heartbeatData {
-	return &heartbeatData{
-		ClientId:      clientID,
-		ProducerDatas: utils.NewSet(),
-		ConsumerDatas: utils.NewSet(),
-	}
-}
-
-func (data *heartbeatData) encode() []byte {
-	d, err := jsoniter.Marshal(data)
-	if err != nil {
-		rlog.Error("marshal heartbeatData error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-		return nil
-	}
-	rlog.Debug("heartbeat: "+string(d), nil)
-	return d
-}
-
-const (
-	PropNameServerAddr         = "PROP_NAMESERVER_ADDR"
-	PropThreadPoolCoreSize     = "PROP_THREADPOOL_CORE_SIZE"
-	PropConsumeOrderly         = "PROP_CONSUMEORDERLY"
-	PropConsumeType            = "PROP_CONSUME_TYPE"
-	PropClientVersion          = "PROP_CLIENT_VERSION"
-	PropConsumerStartTimestamp = "PROP_CONSUMER_START_TIMESTAMP"
-)
-
-type ProcessQueueInfo struct {
-	CommitOffset            int64 `json:"commitOffset"`
-	CachedMsgMinOffset      int64 `json:"cachedMsgMinOffset"`
-	CachedMsgMaxOffset      int64 `json:"cachedMsgMaxOffset"`
-	CachedMsgCount          int   `json:"cachedMsgCount"`
-	CachedMsgSizeInMiB      int64 `json:"cachedMsgSizeInMiB"`
-	TransactionMsgMinOffset int64 `json:"transactionMsgMinOffset"`
-	TransactionMsgMaxOffset int64 `json:"transactionMsgMaxOffset"`
-	TransactionMsgCount     int   `json:"transactionMsgCount"`
-	Locked                  bool  `json:"locked"`
-	TryUnlockTimes          int64 `json:"tryUnlockTimes"`
-	LastLockTimestamp       int64 `json:"lastLockTimestamp"`
-	Dropped                 bool  `json:"dropped"`
-	LastPullTimestamp       int64 `json:"lastPullTimestamp"`
-	LastConsumeTimestamp    int64 `json:"lastConsumeTimestamp"`
-}
-
-type ConsumeStatus struct {
-	PullRT            float64 `json:"pullRT"`
-	PullTPS           float64 `json:"pullTPS"`
-	ConsumeRT         float64 `json:"consumeRT"`
-	ConsumeOKTPS      float64 `json:"consumeOKTPS"`
-	ConsumeFailedTPS  float64 `json:"consumeFailedTPS"`
-	ConsumeFailedMsgs int64   `json:"consumeFailedMsgs"`
-}
-
-type ConsumerRunningInfo struct {
-	Properties       map[string]string
-	SubscriptionData map[*SubscriptionData]bool
-	MQTable          map[primitive.MessageQueue]ProcessQueueInfo
-	StatusTable      map[string]ConsumeStatus
-}
-
-func (info ConsumerRunningInfo) Encode() ([]byte, error) {
-	data, err := json.Marshal(info.Properties)
-	if err != nil {
-		return nil, err
-	}
-	jsonData := fmt.Sprintf("{\"%s\":%s", "properties", string(data))
-
-	data, err = json.Marshal(info.StatusTable)
-	if err != nil {
-		return nil, err
-	}
-	jsonData = fmt.Sprintf("%s,\"%s\":%s", jsonData, "statusTable", string(data))
-
-	subs := make([]*SubscriptionData, len(info.SubscriptionData))
-	idx := 0
-	for k := range info.SubscriptionData {
-		subs[idx] = k
-		idx++
-	}
-
-	// make sure test case table
-	sort.Slice(subs, func(i, j int) bool {
-		sub1 := subs[i]
-		sub2 := subs[j]
-		if sub1.ClassFilterMode != sub2.ClassFilterMode {
-			return sub1.ClassFilterMode == false
-		}
-		com := strings.Compare(sub1.Topic, sub1.Topic)
-		if com != 0 {
-			return com > 0
-		}
-
-		com = strings.Compare(sub1.SubString, sub1.SubString)
-		if com != 0 {
-			return com > 0
-		}
-
-		if sub1.SubVersion != sub2.SubVersion {
-			return sub1.SubVersion > sub2.SubVersion
-		}
-
-		com = strings.Compare(sub1.ExpType, sub1.ExpType)
-		if com != 0 {
-			return com > 0
-		}
-
-		v1, _ := sub1.Tags.MarshalJSON()
-		v2, _ := sub2.Tags.MarshalJSON()
-		com = bytes.Compare(v1, v2)
-		if com != 0 {
-			return com > 0
-		}
-
-		v1, _ = sub1.Codes.MarshalJSON()
-		v2, _ = sub2.Codes.MarshalJSON()
-		com = bytes.Compare(v1, v2)
-		if com != 0 {
-			return com > 0
-		}
-		return true
-	})
-
-	data, err = json.Marshal(subs)
-	if err != nil {
-		return nil, err
-	}
-	jsonData = fmt.Sprintf("%s,\"%s\":%s", jsonData, "subscriptionSet", string(data))
-
-	tableJson := ""
-	keys := make([]primitive.MessageQueue, 0)
-
-	for k := range info.MQTable {
-		keys = append(keys, k)
-	}
-
-	sort.Slice(keys, func(i, j int) bool {
-		q1 := keys[i]
-		q2 := keys[j]
-		com := strings.Compare(q1.Topic, q2.Topic)
-		if com != 0 {
-			return com < 0
-		}
-
-		com = strings.Compare(q1.BrokerName, q2.BrokerName)
-		if com != 0 {
-			return com < 0
-		}
-
-		return q1.QueueId < q2.QueueId
-	})
-
-	for idx := range keys {
-		dataK, err := json.Marshal(keys[idx])
-		if err != nil {
-			return nil, err
-		}
-		dataV, err := json.Marshal(info.MQTable[keys[idx]])
-		tableJson = fmt.Sprintf("%s,%s:%s", tableJson, string(dataK), string(dataV))
-	}
-	tableJson = strings.TrimLeft(tableJson, ",")
-	jsonData = fmt.Sprintf("%s,\"%s\":%s}", jsonData, "mqTable", fmt.Sprintf("{%s}", tableJson))
-	return []byte(jsonData), nil
-}
-
-func NewConsumerRunningInfo() *ConsumerRunningInfo {
-	return &ConsumerRunningInfo{
-		Properties:       make(map[string]string),
-		SubscriptionData: make(map[*SubscriptionData]bool),
-		MQTable:          make(map[primitive.MessageQueue]ProcessQueueInfo),
-		StatusTable:      make(map[string]ConsumeStatus),
-	}
-}
-
-type ConsumeMessageDirectlyResult struct {
-	Order          bool          `json:"order"`
-	AutoCommit     bool          `json:"autoCommit"`
-	ConsumeResult  ConsumeResult `json:"consumeResult"`
-	Remark         string        `json:"remark"`
-	SpentTimeMills int64         `json:"spentTimeMills"`
-}
-
-type ConsumeResult int
-
-const (
-	ConsumeSuccess ConsumeResult = iota
-	ConsumeRetryLater
-	Rollback
-	Commit
-	ThrowException
-	ReturnNull
-)
-
-func (result ConsumeMessageDirectlyResult) Encode() ([]byte, error) {
-	data, err := json.Marshal(result)
-	if err != nil {
-		return nil, err
-	}
-	return data, nil
-}
-
-type ResetOffsetBody struct {
-	OffsetTable map[primitive.MessageQueue]int64 `json:"offsetTable"`
-}
-
-// Decode note: the origin implementation for parse json is in gson format.
-// this func should support both gson and fastjson schema.
-func (resetOffsetBody *ResetOffsetBody) Decode(body []byte) {
-	validJSON := gjson.ValidBytes(body)
-
-	var offsetTable map[primitive.MessageQueue]int64
-
-	if validJSON {
-		offsetTable = parseGsonFormat(body)
-	} else {
-		offsetTable = parseFastJsonFormat(body)
-	}
-
-	resetOffsetBody.OffsetTable = offsetTable
-}
-
-func parseGsonFormat(body []byte) map[primitive.MessageQueue]int64 {
-	result := gjson.ParseBytes(body)
-
-	rlog.Debug("offset table string "+result.Get("offsetTable").String(), nil)
-
-	offsetTable := make(map[primitive.MessageQueue]int64, 0)
-
-	offsetStr := result.Get("offsetTable").String()
-	if len(offsetStr) <= 2 {
-		rlog.Warning("parse reset offset table json get nothing in body", map[string]interface{}{
-			"origin json": offsetStr,
-		})
-		return offsetTable
-	}
-
-	offsetTableArray := strings.Split(offsetStr, "],[")
-
-	for index, v := range offsetTableArray {
-		kvArray := strings.Split(v, "},")
-
-		var kstr, vstr string
-		if index == len(offsetTableArray)-1 {
-			vstr = kvArray[1][:len(kvArray[1])-2]
-		} else {
-			vstr = kvArray[1]
-		}
-		offset, err := strconv.ParseInt(vstr, 10, 64)
-		if err != nil {
-			rlog.Error("Unmarshal offset error", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err,
-			})
-			return nil
-		}
-
-		if index == 0 {
-			kstr = kvArray[0][2:len(kvArray[0])] + "}"
-		} else {
-			kstr = kvArray[0] + "}"
-		}
-		kObj := new(primitive.MessageQueue)
-		err = jsoniter.Unmarshal([]byte(kstr), &kObj)
-		if err != nil {
-			rlog.Error("Unmarshal message queue error", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err,
-			})
-			return nil
-		}
-		offsetTable[*kObj] = offset
-	}
-
-	return offsetTable
-}
-
-func parseFastJsonFormat(body []byte) map[primitive.MessageQueue]int64 {
-	offsetTable := make(map[primitive.MessageQueue]int64)
-
-	jsonStr := string(body)
-	offsetStr := gjson.Get(jsonStr, "offsetTable").String()
-
-	if len(offsetStr) <= 2 {
-		rlog.Warning("parse reset offset table json get nothing in body", map[string]interface{}{
-			"origin json": jsonStr,
-		})
-		return offsetTable
-	}
-
-	trimStr := offsetStr[2 : len(offsetStr)-1]
-
-	split := strings.Split(trimStr, ",{")
-
-	for _, v := range split {
-		tuple := strings.Split(v, "}:")
-
-		queueStr := "{" + tuple[0] + "}"
-
-		var err error
-		// ignore err for now
-		offset, err := strconv.Atoi(tuple[1])
-
-		var queue primitive.MessageQueue
-		err = json.Unmarshal([]byte(queueStr), &queue)
-
-		if err != nil {
-			rlog.Error("parse reset offset table json get nothing in body", map[string]interface{}{
-				"origin json": jsonStr,
-			})
-		}
-
-		offsetTable[queue] = int64(offset)
-	}
-
-	return offsetTable
-}
diff --git a/internal/model_test.go b/internal/model_test.go
deleted file mode 100644
index a653fa4..0000000
--- a/internal/model_test.go
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"encoding/json"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"strings"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/tidwall/gjson"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func TestHeartbeatData(t *testing.T) {
-	Convey("test heatbeat json", t, func() {
-
-		Convey("producerData set marshal", func() {
-			pData := &producerData{
-				GroupName: "group name",
-			}
-			pData2 := &producerData{
-				GroupName: "group name 2",
-			}
-			set := utils.NewSet()
-			set.Add(pData)
-			set.Add(pData2)
-
-			v, err := json.Marshal(set)
-			So(err, ShouldBeNil)
-			rlog.Info("Json Producer", map[string]interface{}{
-				"result": string(v),
-			})
-		})
-
-		Convey("producer heatbeat", func() {
-
-			hbt := NewHeartbeatData("producer client id")
-			p1 := &producerData{
-				GroupName: "group name",
-			}
-			p2 := &producerData{
-				GroupName: "group name 2",
-			}
-
-			hbt.ProducerDatas.Add(p1)
-			hbt.ProducerDatas.Add(p2)
-
-			v, err := json.Marshal(hbt)
-			So(err, ShouldBeNil)
-			rlog.Info("Json Producer", map[string]interface{}{
-				"result": string(v),
-			})
-		})
-
-		Convey("consumer heartbeat", func() {
-
-			hbt := NewHeartbeatData("consumer client id")
-			c1 := consumerData{
-				GroupName: "consumer data 1",
-			}
-			c2 := consumerData{
-				GroupName: "consumer data 2",
-			}
-			hbt.ConsumerDatas.Add(c1)
-			hbt.ConsumerDatas.Add(c2)
-
-			v, err := json.Marshal(hbt)
-			So(err, ShouldBeNil)
-			rlog.Info("Json Consumer", map[string]interface{}{
-				"result": string(v),
-			})
-		})
-
-		Convey("producer & consumer heartbeat", func() {
-
-			hbt := NewHeartbeatData("consumer client id")
-
-			p1 := &producerData{
-				GroupName: "group name",
-			}
-			p2 := &producerData{
-				GroupName: "group name 2",
-			}
-
-			hbt.ProducerDatas.Add(p1)
-			hbt.ProducerDatas.Add(p2)
-
-			c1 := consumerData{
-				GroupName: "consumer data 1",
-			}
-			c2 := consumerData{
-				GroupName: "consumer data 2",
-			}
-			hbt.ConsumerDatas.Add(c1)
-			hbt.ConsumerDatas.Add(c2)
-
-			v, err := json.Marshal(hbt)
-			So(err, ShouldBeNil)
-			rlog.Info("Json Producer and Consumer", map[string]interface{}{
-				"result": string(v),
-			})
-		})
-	})
-
-}
-
-func TestConsumerRunningInfo_MarshalJSON(t *testing.T) {
-	Convey("test ConsumerRunningInfo MarshalJson", t, func() {
-		props := map[string]string{
-			"maxReconsumeTimes":             "-1",
-			"unitMode":                      "false",
-			"adjustThreadPoolNumsThreshold": "100000",
-			"consumerGroup":                 "mq-client-go-test%GID_GO_TEST",
-			"messageModel":                  "CLUSTERING",
-			"suspendCurrentQueueTimeMillis": "1000",
-			"pullThresholdSizeForTopic":     "-1",
-			"pullThresholdSizeForQueue":     "100",
-			"PROP_CLIENT_VERSION":           "V4_5_1",
-			"consumeConcurrentlyMaxSpan":    "2000",
-			"postSubscriptionWhenPull":      "false",
-			"consumeTimestamp":              "20191127013617",
-			"PROP_CONSUME_TYPE":             "CONSUME_PASSIVELY",
-			"consumeTimeout":                "15",
-			"consumeMessageBatchMaxSize":    "1",
-			"PROP_THREADPOOL_CORE_SIZE":     "20",
-			"pullInterval":                  "0",
-			"pullThresholdForQueue":         "1000",
-			"pullThresholdForTopic":         "-1",
-			"consumeFromWhere":              "CONSUME_FROM_FIRST_OFFSET",
-			"PROP_NAMESERVER_ADDR":          "mq-client-go-test.mq-internet-access.mq-internet.aliyuncs.com:80;",
-			"pullBatchSize":                 "32",
-			"consumeThreadMin":              "20",
-			"PROP_CONSUMER_START_TIMESTAMP": "1574791577504",
-			"consumeThreadMax":              "20",
-			"subscription":                  "{}",
-			"PROP_CONSUMEORDERLY":           "false",
-		}
-		subData := map[*SubscriptionData]bool{
-			&SubscriptionData{
-				ClassFilterMode: false,
-				Codes:           utils.NewSet(),
-				ExpType:         "TAG",
-				SubString:       "*",
-				SubVersion:      1574791579242,
-				Tags:            utils.NewSet(),
-				Topic:           "%RETRY%mq-client-go-test%GID_GO_TEST",
-			}: true,
-			&SubscriptionData{
-				ClassFilterMode: true,
-				Codes:           utils.NewSet(),
-				ExpType:         "TAG",
-				SubString:       "*",
-				SubVersion:      1574791577523,
-				Tags:            utils.NewSet(),
-				Topic:           "mq-client-go-test%go-test",
-			}: true,
-		}
-		statusTable := map[string]ConsumeStatus{
-			"%RETRY%mq-client-go-test%GID_GO_TEST": {
-				PullRT:            11.11,
-				PullTPS:           22.22,
-				ConsumeRT:         33.33,
-				ConsumeOKTPS:      44.44,
-				ConsumeFailedTPS:  55.55,
-				ConsumeFailedMsgs: 666,
-			},
-			"mq-client-go-test%go-test": {
-				PullRT:            123,
-				PullTPS:           123,
-				ConsumeRT:         123,
-				ConsumeOKTPS:      123,
-				ConsumeFailedTPS:  123,
-				ConsumeFailedMsgs: 1234,
-			},
-		}
-		mqTable := map[primitive.MessageQueue]ProcessQueueInfo{
-			{
-				Topic:      "%RETRY%mq-client-go-test%GID_GO_TEST",
-				BrokerName: "qd7internet-01",
-				QueueId:    0,
-			}: {
-				CommitOffset:            0,
-				CachedMsgMinOffset:      0,
-				CachedMsgMaxOffset:      0,
-				CachedMsgCount:          0,
-				CachedMsgSizeInMiB:      0,
-				TransactionMsgMinOffset: 0,
-				TransactionMsgMaxOffset: 0,
-				TransactionMsgCount:     0,
-				Locked:                  false,
-				TryUnlockTimes:          0,
-				LastLockTimestamp:       1574791579221,
-				Dropped:                 false,
-				LastPullTimestamp:       1574791579242,
-				LastConsumeTimestamp:    1574791579221,
-			},
-			{
-				Topic:      "%RETRY%mq-client-go-test%GID_GO_TEST",
-				BrokerName: "qd7internet-01",
-				QueueId:    1,
-			}: {
-				CommitOffset:            1,
-				CachedMsgMinOffset:      2,
-				CachedMsgMaxOffset:      3,
-				CachedMsgCount:          4,
-				CachedMsgSizeInMiB:      5,
-				TransactionMsgMinOffset: 6,
-				TransactionMsgMaxOffset: 7,
-				TransactionMsgCount:     8,
-				Locked:                  true,
-				TryUnlockTimes:          9,
-				LastLockTimestamp:       1574791579221,
-				Dropped:                 false,
-				LastPullTimestamp:       1574791579242,
-				LastConsumeTimestamp:    1574791579221,
-			},
-		}
-		info := ConsumerRunningInfo{
-			Properties:       props,
-			SubscriptionData: subData,
-			StatusTable:      statusTable,
-			MQTable:          mqTable,
-		}
-		data, err := info.Encode()
-		So(err, ShouldBeNil)
-		result := gjson.ParseBytes(data)
-		Convey("test Properties fields", func() {
-			r1 := result.Get("properties")
-			So(r1.Exists(), ShouldBeTrue)
-			m := r1.Map()
-			So(len(m), ShouldEqual, 27)
-
-			So(m["PROP_CLIENT_VERSION"], ShouldNotBeEmpty)
-			So(m["PROP_CLIENT_VERSION"].String(), ShouldEqual, "V4_5_1")
-
-			So(m["PROP_CONSUME_TYPE"], ShouldNotBeNil)
-			So(m["PROP_CONSUME_TYPE"].String(), ShouldEqual, "CONSUME_PASSIVELY")
-
-			So(m["PROP_THREADPOOL_CORE_SIZE"], ShouldNotBeNil)
-			So(m["PROP_THREADPOOL_CORE_SIZE"].String(), ShouldEqual, "20")
-
-			So(m["PROP_NAMESERVER_ADDR"], ShouldNotBeNil)
-			So(m["PROP_NAMESERVER_ADDR"].String(), ShouldEqual, "mq-client-go-test.mq-internet-access.mq-internet.aliyuncs.com:80;")
-
-			So(m["PROP_CONSUMER_START_TIMESTAMP"], ShouldNotBeNil)
-			So(m["PROP_CONSUMER_START_TIMESTAMP"].String(), ShouldEqual, "1574791577504")
-
-			So(m["PROP_CONSUMEORDERLY"], ShouldNotBeNil)
-			So(m["PROP_CONSUMEORDERLY"].String(), ShouldEqual, "false")
-		})
-		Convey("test SubscriptionData fields", func() {
-			r2 := result.Get("subscriptionSet")
-			So(r2.Exists(), ShouldBeTrue)
-			arr := r2.Array()
-			So(len(arr), ShouldEqual, 2)
-
-			m1 := arr[0].Map()
-			So(len(m1), ShouldEqual, 7)
-			So(m1["classFilterMode"].Bool(), ShouldEqual, false)
-			So(len(m1["codes"].Array()), ShouldEqual, 0)
-			So(m1["expressionType"].String(), ShouldEqual, "TAG")
-			So(m1["subString"].String(), ShouldEqual, "*")
-			So(m1["subVersion"].Int(), ShouldEqual, 1574791579242)
-			So(len(m1["tags"].Array()), ShouldEqual, 0)
-			So(m1["topic"].String(), ShouldEqual, "%RETRY%mq-client-go-test%GID_GO_TEST")
-
-			m2 := arr[1].Map()
-			So(len(m2), ShouldEqual, 7)
-			So(m2["classFilterMode"].Bool(), ShouldEqual, true)
-			So(len(m2["codes"].Array()), ShouldEqual, 0)
-			So(m2["expressionType"].String(), ShouldEqual, "TAG")
-			So(m2["subString"].String(), ShouldEqual, "*")
-			So(m2["subVersion"].Int(), ShouldEqual, 1574791577523)
-			So(len(m2["tags"].Array()), ShouldEqual, 0)
-			So(m2["topic"].String(), ShouldEqual, "mq-client-go-test%go-test")
-		})
-		Convey("test StatusTable fields", func() {
-			r3 := result.Get("statusTable")
-			So(r3.Exists(), ShouldBeTrue)
-			m := r3.Map()
-			So(len(m), ShouldEqual, 2)
-
-			status1 := m["mq-client-go-test%go-test"].Map()
-			So(len(status1), ShouldEqual, 6)
-			So(status1["pullRT"].Float(), ShouldEqual, 123)
-			So(status1["pullTPS"].Float(), ShouldEqual, 123)
-			So(status1["consumeRT"].Float(), ShouldEqual, 123)
-			So(status1["consumeOKTPS"].Float(), ShouldEqual, 123)
-			So(status1["consumeFailedTPS"].Float(), ShouldEqual, 123)
-			So(status1["consumeFailedMsgs"].Int(), ShouldEqual, 1234)
-
-			status2 := m["%RETRY%mq-client-go-test%GID_GO_TEST"].Map()
-			So(len(status2), ShouldEqual, 6)
-			So(status2["pullRT"].Float(), ShouldEqual, 11.11)
-			So(status2["pullTPS"].Float(), ShouldEqual, 22.22)
-			So(status2["consumeRT"].Float(), ShouldEqual, 33.33)
-			So(status2["consumeOKTPS"].Float(), ShouldEqual, 44.44)
-			So(status2["consumeFailedTPS"].Float(), ShouldEqual, 55.55)
-			So(status2["consumeFailedMsgs"].Int(), ShouldEqual, 666)
-		})
-		Convey("test MQTable fields", func() {
-			r4 := result.Get("mqTable")
-			So(r4.Exists(), ShouldBeTrue)
-			objNumbers := strings.Split(r4.String(), "},{")
-			So(len(objNumbers), ShouldEqual, 2)
-
-			obj1Str := objNumbers[0][1:len(objNumbers[0])] + "}"
-			obj1KV := strings.Split(obj1Str, "}:{")
-			So(len(obj1KV), ShouldEqual, 2)
-
-			obj1 := gjson.Parse("{" + obj1KV[1][0:len(obj1KV[1])])
-			So(obj1.Exists(), ShouldBeTrue)
-			obj1M := obj1.Map()
-			So(len(obj1M), ShouldEqual, 14)
-			So(obj1M["commitOffset"].Int(), ShouldEqual, 0)
-			So(obj1M["cachedMsgMinOffset"].Int(), ShouldEqual, 0)
-			So(obj1M["cachedMsgMaxOffset"].Int(), ShouldEqual, 0)
-			So(obj1M["cachedMsgCount"].Int(), ShouldEqual, 0)
-			So(obj1M["cachedMsgSizeInMiB"].Int(), ShouldEqual, 0)
-			So(obj1M["transactionMsgMinOffset"].Int(), ShouldEqual, 0)
-			So(obj1M["transactionMsgMaxOffset"].Int(), ShouldEqual, 0)
-			So(obj1M["transactionMsgCount"].Int(), ShouldEqual, 0)
-			So(obj1M["locked"].Bool(), ShouldEqual, false)
-			So(obj1M["tryUnlockTimes"].Int(), ShouldEqual, 0)
-			So(obj1M["lastLockTimestamp"].Int(), ShouldEqual, 1574791579221)
-			So(obj1M["dropped"].Bool(), ShouldEqual, false)
-			So(obj1M["lastPullTimestamp"].Int(), ShouldEqual, 1574791579242)
-			So(obj1M["lastConsumeTimestamp"].Int(), ShouldEqual, 1574791579221)
-
-			obj2Str := "{" + objNumbers[1][0:len(objNumbers[1])-1]
-			obj2KV := strings.Split(obj2Str, "}:{")
-			So(len(obj2KV), ShouldEqual, 2)
-			obj2 := gjson.Parse("{" + obj2KV[1][0:len(obj2KV[1])])
-			So(obj2.Exists(), ShouldBeTrue)
-			obj2M := obj2.Map()
-			So(len(obj2M), ShouldEqual, 14)
-			So(obj2M["commitOffset"].Int(), ShouldEqual, 1)
-			So(obj2M["cachedMsgMinOffset"].Int(), ShouldEqual, 2)
-			So(obj2M["cachedMsgMaxOffset"].Int(), ShouldEqual, 3)
-			So(obj2M["cachedMsgCount"].Int(), ShouldEqual, 4)
-			So(obj2M["cachedMsgSizeInMiB"].Int(), ShouldEqual, 5)
-			So(obj2M["transactionMsgMinOffset"].Int(), ShouldEqual, 6)
-			So(obj2M["transactionMsgMaxOffset"].Int(), ShouldEqual, 7)
-			So(obj2M["transactionMsgCount"].Int(), ShouldEqual, 8)
-			So(obj2M["locked"].Bool(), ShouldEqual, true)
-			So(obj2M["tryUnlockTimes"].Int(), ShouldEqual, 9)
-			So(obj2M["lastLockTimestamp"].Int(), ShouldEqual, 1574791579221)
-			So(obj2M["dropped"].Bool(), ShouldEqual, false)
-			So(obj2M["lastPullTimestamp"].Int(), ShouldEqual, 1574791579242)
-			So(obj2M["lastConsumeTimestamp"].Int(), ShouldEqual, 1574791579221)
-		})
-	})
-}
-
-func TestConsumeMessageDirectlyResult_MarshalJSON(t *testing.T) {
-	Convey("test ConsumeMessageDirectlyResult MarshalJson", t, func() {
-		Convey("test consume success", func() {
-			consumeMessageDirectlyResult := ConsumeMessageDirectlyResult{
-				Order:          false,
-				AutoCommit:     true,
-				SpentTimeMills: 2,
-			}
-			consumeMessageDirectlyResult.ConsumeResult = ConsumeSuccess
-			data, err := consumeMessageDirectlyResult.Encode()
-			So(err, ShouldBeNil)
-			rlog.Info("Json consumeMessageDirectlyResult", map[string]interface{}{
-				"result": string(data),
-			})
-		})
-
-		Convey("test consume timeout", func() {
-			consumeResult := ConsumeMessageDirectlyResult{
-				Order:          false,
-				AutoCommit:     true,
-				SpentTimeMills: 2,
-			}
-			consumeResult.ConsumeResult = ReturnNull
-			data, err := consumeResult.Encode()
-			So(err, ShouldBeNil)
-			rlog.Info("Json consumeMessageDirectlyResult", map[string]interface{}{
-				"result": string(data),
-			})
-		})
-
-		Convey("test consume exception", func() {
-			consumeResult := ConsumeMessageDirectlyResult{
-				Order:          false,
-				AutoCommit:     true,
-				SpentTimeMills: 5,
-			}
-			consumeResult.ConsumeResult = ThrowException
-			consumeResult.Remark = "Unknown Exception"
-			data, err := consumeResult.Encode()
-			So(err, ShouldBeNil)
-			rlog.Info("Json consumeMessageDirectlyResult", map[string]interface{}{
-				"result": string(data),
-			})
-		})
-	})
-}
-
-func TestRestOffsetBody_MarshalJSON(t *testing.T) {
-	Convey("test ResetOffset Body Decode gson json schema", t, func() {
-		body := "{\"offsetTable\":[[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":5},23354233],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":4},23354245],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":7},23354203],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":6},23354312],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":1},23373517],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":0},23373350],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":3},23373424],[{\"topic\":\"zx_tst\",\"brokerName\":\"tjwqtst-common-rocketmq-raft0\",\"queueId\":2},23373382]]}"
-		resetOffsetBody := new(ResetOffsetBody)
-		resetOffsetBody.Decode([]byte(body))
-		offsetTable := resetOffsetBody.OffsetTable
-		So(offsetTable, ShouldNotBeNil)
-		So(len(offsetTable), ShouldEqual, 8)
-		messageQueue := primitive.MessageQueue{
-			Topic:      "zx_tst",
-			BrokerName: "tjwqtst-common-rocketmq-raft0",
-			QueueId:    5,
-		}
-		So(offsetTable[messageQueue], ShouldEqual, 23354233)
-	})
-
-	Convey("test ResetOffset Body Decode fast json schema", t, func() {
-		body := "{\"offsetTable\":{{\"brokerName\":\"RaftNode00\",\"queueId\":0,\"topic\":\"topicB\"}:11110,{\"brokerName\":\"RaftNode00\",\"queueId\":1,\"topic\":\"topicB\"}:0,{\"brokerName\":\"RaftNode00\",\"queueId\":2,\"topic\":\"topicB\"}:0,{\"brokerName\":\"RaftNode00\",\"queueId\":3,\"topic\":\"topicB\"}:0}}"
-		resetOffsetBody := new(ResetOffsetBody)
-		resetOffsetBody.Decode([]byte(body))
-		offsetTable := resetOffsetBody.OffsetTable
-		So(offsetTable, ShouldNotBeNil)
-		So(len(offsetTable), ShouldEqual, 4)
-		messageQueue := primitive.MessageQueue{
-			Topic:      "topicB",
-			BrokerName: "RaftNode00",
-			QueueId:    0,
-		}
-		So(offsetTable[messageQueue], ShouldEqual, 11110)
-	})
-
-	Convey("test ResetOffset Body Decode fast json schema with one item", t, func() {
-		body := "{\"offsetTable\":{{\"brokerName\":\"RaftNode00\",\"queueId\":0,\"topic\":\"topicB\"}:11110}}"
-		resetOffsetBody := new(ResetOffsetBody)
-		resetOffsetBody.Decode([]byte(body))
-		offsetTable := resetOffsetBody.OffsetTable
-		So(offsetTable, ShouldNotBeNil)
-		So(len(offsetTable), ShouldEqual, 1)
-		messageQueue := primitive.MessageQueue{
-			Topic:      "topicB",
-			BrokerName: "RaftNode00",
-			QueueId:    0,
-		}
-		So(offsetTable[messageQueue], ShouldEqual, 11110)
-	})
-
-	Convey("test ResetOffset Body Decode empty fast json ", t, func() {
-		body := "{\"offsetTable\":{}}"
-		resetOffsetBody := new(ResetOffsetBody)
-		resetOffsetBody.Decode([]byte(body))
-		offsetTable := resetOffsetBody.OffsetTable
-		So(offsetTable, ShouldNotBeNil)
-		So(len(offsetTable), ShouldEqual, 0)
-	})
-
-	Convey("test ResetOffset Body Decode empty gson json ", t, func() {
-		body := "{\"offsetTable\":[]}"
-		resetOffsetBody := new(ResetOffsetBody)
-		resetOffsetBody.Decode([]byte(body))
-		offsetTable := resetOffsetBody.OffsetTable
-		So(offsetTable, ShouldNotBeNil)
-		So(len(offsetTable), ShouldEqual, 0)
-	})
-}
diff --git a/internal/mq_version.go b/internal/mq_version.go
deleted file mode 100644
index 4b5c645..0000000
--- a/internal/mq_version.go
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing software
-distributed under the License is distributed on an "AS IS" BASIS
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-const (
-	V4_1_0 = 0
-)
diff --git a/internal/namesrv.go b/internal/namesrv.go
deleted file mode 100644
index 96e708a..0000000
--- a/internal/namesrv.go
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"errors"
-	"fmt"
-	"regexp"
-	"strings"
-	"sync"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-const (
-	DEFAULT_NAMESRV_ADDR = "http://jmenv.tbsite.net:8080/rocketmq/nsaddr"
-)
-
-var (
-	ipRegex, _ = regexp.Compile(`^((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))`)
-
-	ErrNoNameserver = errors.New("nameServerAddrs can't be empty.")
-	ErrMultiIP      = errors.New("multiple IP addr does not support")
-	ErrIllegalIP    = errors.New("IP addr error")
-)
-
-//go:generate mockgen -source namesrv.go -destination mock_namesrv.go -self_package github.com/apache/rocketmq-client-go/v2/internal  --package internal Namesrvs
-type Namesrvs interface {
-	UpdateNameServerAddress()
-
-	AddBroker(routeData *TopicRouteData)
-
-	cleanOfflineBroker()
-
-	UpdateTopicRouteInfo(topic string) (routeData *TopicRouteData, changed bool, err error)
-
-	UpdateTopicRouteInfoWithDefault(topic string, defaultTopic string, defaultQueueNum int) (*TopicRouteData, bool, error)
-
-	FetchPublishMessageQueues(topic string) ([]*primitive.MessageQueue, error)
-
-	FindBrokerAddrByTopic(topic string) string
-
-	FindBrokerAddrByName(brokerName string) string
-
-	FindBrokerAddressInSubscribe(brokerName string, brokerId int64, onlyThisBroker bool) *FindBrokerResult
-
-	FetchSubscribeMessageQueues(topic string) ([]*primitive.MessageQueue, error)
-
-	AddrList() []string
-}
-
-// namesrvs rocketmq namesrv instance.
-type namesrvs struct {
-	// namesrv addr list
-	srvs []string
-
-	// lock for getNameServerAddress in case of update index race condition
-	lock sync.Locker
-
-	// index indicate the next position for getNameServerAddress
-	index int
-
-	// brokerName -> *BrokerData
-	brokerAddressesMap sync.Map
-
-	bundleClient *rmqClient
-
-	// brokerName -> map[string]int32: brokerAddr -> version
-	brokerVersionMap map[string]map[string]int32
-	// lock for broker version read/write
-	brokerLock *sync.RWMutex
-
-	//subscribeInfoMap sync.Map
-	routeDataMap sync.Map
-
-	lockNamesrv sync.Mutex
-
-	nameSrvClient remote.RemotingClient
-
-	resolver primitive.NsResolver
-}
-
-var _ Namesrvs = (*namesrvs)(nil)
-var namesrvMap sync.Map
-
-// NewNamesrv init Namesrv from namesrv addr string.
-// addr primitive.NamesrvAddr
-func GetOrSetNamesrv(clientId string, namesrv *namesrvs) *namesrvs {
-	actual, _ := namesrvMap.LoadOrStore(clientId, namesrv)
-	return actual.(*namesrvs)
-}
-func GetNamesrv(clientId string) (*namesrvs, error) {
-	actual, ok := namesrvMap.Load(clientId)
-	if !ok {
-		return nil, fmt.Errorf("the namesrv in instanceName [%s] not found", clientId)
-	}
-	return actual.(*namesrvs), nil
-}
-func NewNamesrv(resolver primitive.NsResolver) (*namesrvs, error) {
-	addr := resolver.Resolve()
-	if len(addr) == 0 {
-		return nil, errors.New("no name server addr found with resolver: " + resolver.Description())
-	}
-
-	if err := primitive.NamesrvAddr(addr).Check(); err != nil {
-		return nil, err
-	}
-	nameSrvClient := remote.NewRemotingClient()
-	return &namesrvs{
-		srvs:             addr,
-		lock:             new(sync.Mutex),
-		nameSrvClient:    nameSrvClient,
-		brokerVersionMap: make(map[string]map[string]int32, 0),
-		brokerLock:       new(sync.RWMutex),
-		resolver:         resolver,
-	}, nil
-}
-
-// getNameServerAddress return namesrv using round-robin strategy.
-func (s *namesrvs) getNameServerAddress() string {
-	s.lock.Lock()
-	defer s.lock.Unlock()
-
-	addr := s.srvs[s.index%len(s.srvs)]
-	index := s.index + 1
-	if index < 0 {
-		index = -index
-	}
-	index %= len(s.srvs)
-	s.index = index
-	if strings.HasPrefix(addr, "https") {
-		return strings.TrimPrefix(addr, "https://")
-	}
-	return strings.TrimPrefix(addr, "http://")
-}
-
-func (s *namesrvs) Size() int {
-	return len(s.srvs)
-}
-
-func (s *namesrvs) String() string {
-	return strings.Join(s.srvs, ";")
-}
-func (s *namesrvs) SetCredentials(credentials primitive.Credentials) {
-	s.nameSrvClient.RegisterInterceptor(remote.ACLInterceptor(credentials))
-}
-
-func (s *namesrvs) AddrList() []string {
-	return s.srvs
-}
-
-// UpdateNameServerAddress will update srvs.
-// docs: https://rocketmq.apache.org/docs/best-practice-namesvr/
-func (s *namesrvs) UpdateNameServerAddress() {
-	s.lock.Lock()
-	defer s.lock.Unlock()
-
-	srvs := s.resolver.Resolve()
-	if len(srvs) == 0 {
-		return
-	}
-
-	updated := primitive.Diff(s.srvs, srvs)
-	if !updated {
-		return
-	}
-
-	s.srvs = srvs
-}
diff --git a/internal/namesrv_test.go b/internal/namesrv_test.go
deleted file mode 100644
index b047a07..0000000
--- a/internal/namesrv_test.go
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"net"
-	"net/http"
-	"os"
-	"strings"
-	"sync"
-	"testing"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/stretchr/testify/assert"
-)
-
-// TestSelector test roundrobin selector in namesrv
-func TestSelector(t *testing.T) {
-	srvs := []string{"127.0.0.1:9876", "127.0.0.1:9879", "12.24.123.243:10911", "12.24.123.243:10915"}
-	namesrv, err := NewNamesrv(primitive.NewPassthroughResolver(srvs))
-	assert.Nil(t, err)
-
-	assert.Equal(t, srvs[0], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[1], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[2], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[3], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[0], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[1], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[2], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[3], namesrv.getNameServerAddress())
-	assert.Equal(t, srvs[0], namesrv.getNameServerAddress())
-}
-
-func TestGetNamesrv(t *testing.T) {
-	Convey("Test GetNamesrv round-robin strategy", t, func() {
-		ns := &namesrvs{
-			srvs: []string{"192.168.100.1",
-				"192.168.100.2",
-				"192.168.100.3",
-				"192.168.100.4",
-				"192.168.100.5",
-			},
-			lock: new(sync.Mutex),
-		}
-
-		index1 := ns.index
-		IP1 := ns.getNameServerAddress()
-
-		index2 := ns.index
-		IP2 := ns.getNameServerAddress()
-
-		So(index1+1, ShouldEqual, index2)
-		So(IP1, ShouldEqual, ns.srvs[index1])
-		So(IP2, ShouldEqual, ns.srvs[index2])
-	})
-}
-
-func TestUpdateNameServerAddress(t *testing.T) {
-	Convey("Test UpdateNameServerAddress method", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-		http.HandleFunc("/nameserver/addrs", func(w http.ResponseWriter, r *http.Request) {
-			fmt.Fprintf(w, strings.Join(srvs, ";"))
-		})
-		server := &http.Server{Addr: ":0", Handler: nil}
-		listener, _ := net.Listen("tcp", ":0")
-		go server.Serve(listener)
-
-		port := listener.Addr().(*net.TCPAddr).Port
-		nameServerDommain := fmt.Sprintf("http://127.0.0.1:%d/nameserver/addrs", port)
-		rlog.Info("Temporary Nameserver", map[string]interface{}{
-			"domain": nameServerDommain,
-		})
-
-		resolver := primitive.NewHttpResolver("DEFAULT", nameServerDommain)
-		ns := &namesrvs{
-			srvs:     []string{},
-			lock:     new(sync.Mutex),
-			resolver: resolver,
-		}
-
-		ns.UpdateNameServerAddress()
-
-		index1 := ns.index
-		IP1 := ns.getNameServerAddress()
-
-		index2 := ns.index
-		IP2 := ns.getNameServerAddress()
-
-		So(index1+1, ShouldEqual, index2)
-		So(IP1, ShouldEqual, srvs[index1])
-		So(IP2, ShouldEqual, srvs[index2])
-	})
-}
-
-func TestUpdateNameServerAddressUseEnv(t *testing.T) {
-	Convey("Test UpdateNameServerAddress Use Env", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-
-		resolver := primitive.NewEnvResolver()
-		ns := &namesrvs{
-			srvs:     []string{},
-			lock:     new(sync.Mutex),
-			resolver: resolver,
-		}
-		os.Setenv("NAMESRV_ADDR", strings.Join(srvs, ";"))
-		ns.UpdateNameServerAddress()
-
-		index1 := ns.index
-		IP1 := ns.getNameServerAddress()
-
-		index2 := ns.index
-		IP2 := ns.getNameServerAddress()
-
-		So(index1+1, ShouldEqual, index2)
-		So(IP1, ShouldEqual, srvs[index1])
-		So(IP2, ShouldEqual, srvs[index2])
-	})
-}
diff --git a/internal/perm.go b/internal/perm.go
deleted file mode 100644
index 638b7a7..0000000
--- a/internal/perm.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-const (
-	permPriority = 0x1 << 3
-	permRead     = 0x1 << 2
-	permWrite    = 0x1 << 1
-	permInherit  = 0x1 << 0
-)
-
-func queueIsReadable(perm int) bool {
-	return (perm & permRead) == permRead
-}
-
-func queueIsWriteable(perm int) bool {
-	return (perm & permWrite) == permWrite
-}
-
-func queueIsInherited(perm int) bool {
-	return (perm & permInherit) == permInherit
-}
-
-func perm2string(perm int) string {
-	bytes := make([]byte, 3)
-	for i := 0; i < 3; i++ {
-		bytes[i] = '-'
-	}
-
-	if queueIsReadable(perm) {
-		bytes[0] = 'R'
-	}
-
-	if queueIsWriteable(perm) {
-		bytes[1] = 'W'
-	}
-
-	if queueIsInherited(perm) {
-		bytes[2] = 'X'
-	}
-
-	return string(bytes)
-}
diff --git a/internal/remote/codec.go b/internal/remote/codec.go
deleted file mode 100644
index 6b3d3d6..0000000
--- a/internal/remote/codec.go
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package remote
-
-import (
-	"bytes"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"sync/atomic"
-
-	jsoniter "github.com/json-iterator/go"
-)
-
-var opaque int32
-
-const (
-	// 0, REQUEST_COMMAND
-	RPCType = 0
-	// 1, RPC
-	RPCOneWay = 1
-	//ResponseType for response
-	ResponseType = 1
-	_Flag        = 0
-	_Version     = 317
-)
-
-type LanguageCode byte
-
-const (
-	_Java    = LanguageCode(0)
-	_Go      = LanguageCode(9)
-	_Unknown = LanguageCode(127)
-)
-
-func (lc LanguageCode) MarshalJSON() ([]byte, error) {
-	return []byte(`"GO"`), nil
-}
-
-func (lc *LanguageCode) UnmarshalJSON(b []byte) error {
-	switch string(b) {
-	case "JAVA":
-		*lc = _Java
-	case "GO", `"GO"`:
-		*lc = _Go
-	default:
-		*lc = _Unknown
-	}
-	return nil
-}
-
-func (lc LanguageCode) String() string {
-	switch lc {
-	case _Java:
-		return "JAVA"
-	case _Go:
-		return "GO"
-	default:
-		return "unknown"
-	}
-}
-
-type RemotingCommand struct {
-	Code      int16             `json:"code"`
-	Language  LanguageCode      `json:"language"`
-	Version   int16             `json:"version"`
-	Opaque    int32             `json:"opaque"`
-	Flag      int32             `json:"flag"`
-	Remark    string            `json:"remark"`
-	ExtFields map[string]string `json:"extFields"`
-	Body      []byte            `json:"-"`
-}
-
-type CustomHeader interface {
-	Encode() map[string]string
-}
-
-func NewRemotingCommand(code int16, header CustomHeader, body []byte) *RemotingCommand {
-	cmd := &RemotingCommand{
-		Code:      code,
-		Version:   _Version,
-		Opaque:    atomic.AddInt32(&opaque, 1),
-		Body:      body,
-		Language:  _Go,
-		ExtFields: make(map[string]string),
-	}
-
-	if header != nil {
-		cmd.ExtFields = header.Encode()
-	}
-
-	return cmd
-}
-
-func (command *RemotingCommand) String() string {
-	return fmt.Sprintf("Code: %d, opaque: %d, Remark: %s, ExtFields: %v",
-		command.Code, command.Opaque, command.Remark, command.ExtFields)
-}
-
-func (command *RemotingCommand) isResponseType() bool {
-	return command.Flag&(ResponseType) == ResponseType
-}
-
-func (command *RemotingCommand) markResponseType() {
-	command.Flag = command.Flag | ResponseType
-}
-
-var (
-	jsonSerializer     = &jsonCodec{}
-	rocketMqSerializer = &rmqCodec{}
-	codecType          byte
-)
-
-// encode RemotingCommand
-//
-// Frame format:
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// + item | frame_size | header_length |         header_body        |     body     +
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// + len  |   4bytes   |     4bytes    | (21 + r_len + e_len) bytes | remain bytes +
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-func (command *RemotingCommand) WriteTo(w io.Writer) error {
-	var (
-		header []byte
-		err    error
-	)
-
-	switch codecType {
-	case JsonCodecs:
-		header, err = jsonSerializer.encodeHeader(command)
-	case RocketMQCodecs:
-		header, err = rocketMqSerializer.encodeHeader(command)
-	}
-
-	if err != nil {
-		return err
-	}
-
-	frameSize := 4 + len(header) + len(command.Body)
-	err = binary.Write(w, binary.BigEndian, int32(frameSize))
-	if err != nil {
-		return err
-	}
-
-	err = binary.Write(w, binary.BigEndian, markProtocolType(int32(len(header))))
-	if err != nil {
-		return err
-	}
-
-	_, err = w.Write(header)
-	if err != nil {
-		return err
-	}
-
-	_, err = w.Write(command.Body)
-	return err
-}
-
-func encode(command *RemotingCommand) ([]byte, error) {
-	var (
-		header []byte
-		err    error
-	)
-
-	switch codecType {
-	case JsonCodecs:
-		header, err = jsonSerializer.encodeHeader(command)
-	case RocketMQCodecs:
-		header, err = rocketMqSerializer.encodeHeader(command)
-	}
-
-	if err != nil {
-		return nil, err
-	}
-
-	frameSize := 4 + len(header) + len(command.Body)
-	buf := bytes.NewBuffer(make([]byte, frameSize))
-	buf.Reset()
-
-	err = binary.Write(buf, binary.BigEndian, int32(frameSize))
-	if err != nil {
-		return nil, err
-	}
-
-	err = binary.Write(buf, binary.BigEndian, markProtocolType(int32(len(header))))
-	if err != nil {
-		return nil, err
-	}
-
-	err = binary.Write(buf, binary.BigEndian, header)
-	if err != nil {
-		return nil, err
-	}
-
-	err = binary.Write(buf, binary.BigEndian, command.Body)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func decode(data []byte) (*RemotingCommand, error) {
-	buf := bytes.NewReader(data)
-	length := int32(len(data))
-	var oriHeaderLen int32
-	err := binary.Read(buf, binary.BigEndian, &oriHeaderLen)
-	if err != nil {
-		return nil, err
-	}
-
-	headerLength := oriHeaderLen & 0xFFFFFF
-	headerData := make([]byte, headerLength)
-	if _, err = io.ReadFull(buf, headerData); err != nil {
-		return nil, err
-	}
-
-	var command *RemotingCommand
-	switch codeType := byte((oriHeaderLen >> 24) & 0xFF); codeType {
-	case JsonCodecs:
-		command, err = jsonSerializer.decodeHeader(headerData)
-	case RocketMQCodecs:
-		command, err = rocketMqSerializer.decodeHeader(headerData)
-	default:
-		err = fmt.Errorf("unknown codec type: %d", codeType)
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	bodyLength := length - 4 - headerLength
-	if bodyLength > 0 {
-		bodyData := make([]byte, bodyLength)
-		if _, err = io.ReadFull(buf, bodyData); err != nil {
-			return nil, err
-		}
-		command.Body = bodyData
-	}
-	return command, nil
-}
-
-func markProtocolType(source int32) []byte {
-	result := make([]byte, 4)
-	result[0] = codecType
-	result[1] = byte((source >> 16) & 0xFF)
-	result[2] = byte((source >> 8) & 0xFF)
-	result[3] = byte(source & 0xFF)
-	return result
-}
-
-const (
-	JsonCodecs     = byte(0)
-	RocketMQCodecs = byte(1)
-)
-
-type serializer interface {
-	encodeHeader(command *RemotingCommand) ([]byte, error)
-	decodeHeader(data []byte) (*RemotingCommand, error)
-}
-
-// jsonCodec please refer to remoting/protocol/RemotingSerializable
-type jsonCodec struct{}
-
-func (c *jsonCodec) encodeHeader(command *RemotingCommand) ([]byte, error) {
-	buf, err := jsoniter.Marshal(command)
-	if err != nil {
-		return nil, err
-	}
-	return buf, nil
-}
-
-func (c *jsonCodec) decodeHeader(header []byte) (*RemotingCommand, error) {
-	command := &RemotingCommand{}
-	command.ExtFields = make(map[string]string)
-	command.Body = make([]byte, 0)
-	err := jsoniter.Unmarshal(header, command)
-	if err != nil {
-		return nil, err
-	}
-	return command, nil
-}
-
-// rmqCodec implementation of RocketMQCodecs private protocol, please refer to remoting/protocol/RocketMQSerializable
-// RocketMQCodecs Private Protocol Header format:
-//
-// v_flag: version flag
-// r_len: length of remark body
-// r_body: data of remark body
-// e_len: length of extends fields body
-// e_body: data of extends fields
-//
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// + item | request_code | l_flag | v_flag | opaque | request_flag |  r_len  |   r_body    |  e_len  |    e_body   +
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// + len  |    2bytes    |  1byte | 2bytes | 4bytes |    4 bytes   | 4 bytes | r_len bytes | 4 bytes | e_len bytes +
-// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-const (
-	// header + body length
-	headerFixedLength = 21
-)
-
-type rmqCodec struct{}
-
-// encodeHeader
-func (c *rmqCodec) encodeHeader(command *RemotingCommand) ([]byte, error) {
-	extBytes, err := c.encodeMaps(command.ExtFields)
-	if err != nil {
-		return nil, err
-	}
-
-	buf := bytes.NewBuffer(make([]byte, headerFixedLength+len(command.Remark)+len(extBytes)))
-	buf.Reset()
-
-	// request code, length is 2 bytes
-	err = binary.Write(buf, binary.BigEndian, int16(command.Code))
-	if err != nil {
-		return nil, err
-	}
-
-	// language flag, length is 1 byte
-	err = binary.Write(buf, binary.BigEndian, _Go)
-	if err != nil {
-		return nil, err
-	}
-
-	// version flag, length is 2 bytes
-	err = binary.Write(buf, binary.BigEndian, int16(command.Version))
-	if err != nil {
-		return nil, err
-	}
-
-	// opaque flag, opaque is request identifier, length is 4 bytes
-	err = binary.Write(buf, binary.BigEndian, command.Opaque)
-	if err != nil {
-		return nil, err
-	}
-
-	// request flag, length is 4 bytes
-	err = binary.Write(buf, binary.BigEndian, command.Flag)
-	if err != nil {
-		return nil, err
-	}
-
-	// remark length flag, length is 4 bytes
-	err = binary.Write(buf, binary.BigEndian, int32(len(command.Remark)))
-	if err != nil {
-		return nil, err
-	}
-
-	// write remark, len(command.Remark) bytes
-	if len(command.Remark) > 0 {
-		err = binary.Write(buf, binary.BigEndian, []byte(command.Remark))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	err = binary.Write(buf, binary.BigEndian, int32(len(extBytes)))
-	if err != nil {
-		return nil, err
-	}
-
-	if len(extBytes) > 0 {
-		err = binary.Write(buf, binary.BigEndian, extBytes)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (c *rmqCodec) encodeMaps(maps map[string]string) ([]byte, error) {
-	if maps == nil || len(maps) == 0 {
-		return []byte{}, nil
-	}
-	extFieldsBuf := bytes.NewBuffer([]byte{})
-	var err error
-	for key, value := range maps {
-		err = binary.Write(extFieldsBuf, binary.BigEndian, int16(len(key)))
-		if err != nil {
-			return nil, err
-		}
-		err = binary.Write(extFieldsBuf, binary.BigEndian, []byte(key))
-		if err != nil {
-			return nil, err
-		}
-
-		err = binary.Write(extFieldsBuf, binary.BigEndian, int32(len(value)))
-		if err != nil {
-			return nil, err
-		}
-		err = binary.Write(extFieldsBuf, binary.BigEndian, []byte(value))
-		if err != nil {
-			return nil, err
-		}
-	}
-	return extFieldsBuf.Bytes(), nil
-}
-
-func (c *rmqCodec) decodeHeader(data []byte) (*RemotingCommand, error) {
-	var err error
-	command := &RemotingCommand{}
-	buf := bytes.NewBuffer(data)
-	var code int16
-	err = binary.Read(buf, binary.BigEndian, &code)
-	if err != nil {
-		return nil, err
-	}
-	command.Code = code
-
-	var (
-		languageCode byte
-		remarkLen    int32
-		extFieldsLen int32
-	)
-	err = binary.Read(buf, binary.BigEndian, &languageCode)
-	if err != nil {
-		return nil, err
-	}
-	command.Language = LanguageCode(languageCode)
-
-	var version int16
-	err = binary.Read(buf, binary.BigEndian, &version)
-	if err != nil {
-		return nil, err
-	}
-	command.Version = version
-
-	// int opaque
-	err = binary.Read(buf, binary.BigEndian, &command.Opaque)
-	if err != nil {
-		return nil, err
-	}
-
-	// int flag
-	err = binary.Read(buf, binary.BigEndian, &command.Flag)
-	if err != nil {
-		return nil, err
-	}
-
-	// String remark
-	err = binary.Read(buf, binary.BigEndian, &remarkLen)
-	if err != nil {
-		return nil, err
-	}
-
-	if remarkLen > 0 {
-		var remarkData = make([]byte, remarkLen)
-		if _, err = io.ReadFull(buf, remarkData); err != nil {
-			return nil, err
-		}
-		command.Remark = string(remarkData)
-	}
-
-	err = binary.Read(buf, binary.BigEndian, &extFieldsLen)
-	if err != nil {
-		return nil, err
-	}
-
-	if extFieldsLen > 0 {
-		extFieldsData := make([]byte, extFieldsLen)
-		if _, err := io.ReadFull(buf, extFieldsData); err != nil {
-			return nil, err
-		}
-
-		command.ExtFields = make(map[string]string)
-		buf := bytes.NewBuffer(extFieldsData)
-		var (
-			kLen int16
-			vLen int32
-		)
-		for buf.Len() > 0 {
-			err = binary.Read(buf, binary.BigEndian, &kLen)
-			if err != nil {
-				return nil, err
-			}
-
-			key, err := getExtFieldsData(buf, int32(kLen))
-			if err != nil {
-				return nil, err
-			}
-
-			err = binary.Read(buf, binary.BigEndian, &vLen)
-			if err != nil {
-				return nil, err
-			}
-
-			value, err := getExtFieldsData(buf, vLen)
-			if err != nil {
-				return nil, err
-			}
-			command.ExtFields[key] = value
-		}
-	}
-
-	return command, nil
-}
-
-func getExtFieldsData(buff io.Reader, length int32) (string, error) {
-	var data = make([]byte, length)
-	if _, err := io.ReadFull(buff, data); err != nil {
-		return "", err
-	}
-
-	return string(data), nil
-}
diff --git a/internal/remote/codec_test.go b/internal/remote/codec_test.go
deleted file mode 100644
index 0717451..0000000
--- a/internal/remote/codec_test.go
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package remote
-
-import (
-	"encoding/json"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"math/rand"
-	"reflect"
-	"testing"
-	"unsafe"
-
-	jsoniter "github.com/json-iterator/go"
-
-	"github.com/stretchr/testify/assert"
-)
-
-type testHeader struct {
-}
-
-func (t testHeader) Encode() map[string]string {
-	properties := make(map[string]string)
-	for i := 0; i < 10; i++ {
-		properties[randomString(rand.Intn(20))] = randomString(rand.Intn(20))
-	}
-	return properties
-}
-
-func randomBytes(length int) []byte {
-	bs := make([]byte, length)
-	if _, err := rand.Read(bs); err != nil {
-		panic("read random bytes fail")
-	}
-	return bs
-}
-
-func randomString(length int) string {
-	bs := make([]byte, length)
-	for i := 0; i < len(bs); i++ {
-		bs[i] = byte(97 + rand.Intn(26))
-	}
-	return string(bs)
-}
-
-func randomNewRemotingCommand() *RemotingCommand {
-	var h testHeader
-	body := randomBytes(rand.Intn(100))
-	return NewRemotingCommand(int16(rand.Intn(1000)), h, body)
-}
-
-func Test_encode(t *testing.T) {
-	for i := 0; i < 1000; i++ {
-		rc := randomNewRemotingCommand()
-		if _, err := encode(rc); err != nil {
-			t.Fatalf("encode RemotingCommand to bytes fail: %v", err)
-		}
-	}
-}
-
-func Benchmark_encode(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		if _, err := encode(rc); err != nil {
-			b.Fatalf("encode RemotingCommand to bytes fail: %v", err)
-		}
-	}
-}
-
-func Test_decode(t *testing.T) {
-	for i := 0; i < 1000; i++ {
-		rc := randomNewRemotingCommand()
-
-		bs, err := encode(rc)
-		if err != nil {
-			t.Fatalf("encode RemotingCommand to bytes fail: %v", err)
-		}
-		bs = bs[4:]
-		decodedRc, err := decode(bs)
-		if err != nil {
-			t.Fatalf("decode bytes to RemotingCommand fail: %v", err)
-		}
-
-		if rc.Code != decodedRc.Code {
-			t.Fatalf("wrong Code. want=%d, got=%d", rc.Code, decodedRc.Code)
-		}
-		if rc.Version != decodedRc.Version {
-			t.Fatalf("wrong Version. want=%d, got=%d", rc.Version, decodedRc.Version)
-		}
-		if rc.Opaque != decodedRc.Opaque {
-			t.Fatalf("wrong opaque. want=%d, got=%d", rc.Opaque, decodedRc.Opaque)
-		}
-		if rc.Remark != decodedRc.Remark {
-			t.Fatalf("wrong remark. want=%s, got=%s", rc.Remark, decodedRc.Remark)
-		}
-		if rc.Flag != decodedRc.Flag {
-			t.Fatalf("wrong flag. want=%d, got=%d", rc.Flag, decodedRc.Flag)
-		}
-		if !reflect.DeepEqual(rc.ExtFields, decodedRc.ExtFields) {
-			t.Fatalf("wrong extFields, want=%v, got=%v", rc.ExtFields, decodedRc.ExtFields)
-		}
-	}
-}
-
-func Benchmark_decode(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	bs, err := encode(rc)
-	if err != nil {
-		b.Fatalf("encode RemotingCommand to bytes fail: %v", err)
-	}
-	b.ResetTimer()
-	bs = bs[4:]
-	for i := 0; i < b.N; i++ {
-		if _, err := decode(bs); err != nil {
-			b.Fatalf("decode bytes to RemotingCommand fail: %v", err)
-		}
-	}
-}
-
-func Test_jsonCodec_encodeHeader(t *testing.T) {
-	for i := 0; i < 1000; i++ {
-		rc := randomNewRemotingCommand()
-
-		if _, err := jsonSerializer.encodeHeader(rc); err != nil {
-			t.Fatalf("encode header with jsonCodec fail: %v", err)
-		}
-	}
-}
-
-func Benchmark_jsonCodec_encodeHeader(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		if _, err := jsonSerializer.encodeHeader(rc); err != nil {
-			b.Fatalf("encode header with jsonCodec fail: %v", err)
-		}
-	}
-}
-
-func Test_jsonCodec_decodeHeader(t *testing.T) {
-	for i := 0; i < 1; i++ {
-		rc := randomNewRemotingCommand()
-
-		headers, err := jsonSerializer.encodeHeader(rc)
-		if err != nil {
-			t.Fatalf("encode header with jsonCodec fail: %v", err)
-		}
-
-		decodedRc, err := jsonSerializer.decodeHeader(headers)
-		if err != nil {
-			t.Fatalf("decode header with jsonCodec fail: %v", err)
-		}
-
-		if rc.Code != decodedRc.Code {
-			t.Fatalf("wrong Code. want=%d, got=%d", rc.Code, decodedRc.Code)
-		}
-		if rc.Version != decodedRc.Version {
-			t.Fatalf("wrong Version. want=%d, got=%d", rc.Version, decodedRc.Version)
-		}
-		if rc.Opaque != decodedRc.Opaque {
-			t.Fatalf("wrong opaque. want=%d, got=%d", rc.Opaque, decodedRc.Opaque)
-		}
-		if rc.Remark != decodedRc.Remark {
-			t.Fatalf("wrong remark. want=%s, got=%s", rc.Remark, decodedRc.Remark)
-		}
-		if rc.Flag != decodedRc.Flag {
-			t.Fatalf("wrong flag. want=%d, got=%d", rc.Flag, decodedRc.Flag)
-		}
-		if !reflect.DeepEqual(rc.ExtFields, decodedRc.ExtFields) {
-			t.Fatalf("wrong extFields, want=%v, got=%v", rc.ExtFields, decodedRc.ExtFields)
-		}
-	}
-}
-
-func Benchmark_jsonCodec_decodeHeader(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	headers, err := jsonSerializer.encodeHeader(rc)
-	if err != nil {
-		b.Fatalf("encode header with jsonCodec fail: %v", err)
-	}
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		if _, err := jsonSerializer.decodeHeader(headers); err != nil {
-			b.Fatalf("decode header with jsonCodec fail: %v", err)
-		}
-	}
-}
-
-func Test_rmqCodec_encodeHeader(t *testing.T) {
-	for i := 0; i < 1000; i++ {
-		rc := randomNewRemotingCommand()
-
-		if _, err := rocketMqSerializer.encodeHeader(rc); err != nil {
-			t.Fatalf("encode header with rmqCodec fail: %v", err)
-		}
-	}
-}
-
-func Benchmark_rmqCodec_encodeHeader(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		if _, err := rocketMqSerializer.encodeHeader(rc); err != nil {
-			b.Fatalf("encode header with rmqCodec fail: %v", err)
-		}
-	}
-}
-
-func Test_rmqCodec_decodeHeader(t *testing.T) {
-	for i := 0; i < 1; i++ {
-		rc := randomNewRemotingCommand()
-
-		headers, err := rocketMqSerializer.encodeHeader(rc)
-		if err != nil {
-			t.Fatalf("encode header with rmqCodec fail: %v", err)
-		}
-
-		decodedRc, err := rocketMqSerializer.decodeHeader(headers)
-		if err != nil {
-			t.Fatalf("decode header with rmqCodec fail: %v", err)
-		}
-		if rc.Code != decodedRc.Code {
-			t.Fatalf("wrong Code. want=%d, got=%d", rc.Code, decodedRc.Code)
-		}
-		if rc.Version != decodedRc.Version {
-			t.Fatalf("wrong Version. want=%d, got=%d", rc.Version, decodedRc.Version)
-		}
-		if rc.Opaque != decodedRc.Opaque {
-			t.Fatalf("wrong opaque. want=%d, got=%d", rc.Opaque, decodedRc.Opaque)
-		}
-		if rc.Remark != decodedRc.Remark {
-			t.Fatalf("wrong remark. want=%s, got=%s", rc.Remark, decodedRc.Remark)
-		}
-		if rc.Flag != decodedRc.Flag {
-			t.Fatalf("wrong flag. want=%d, got=%d", rc.Flag, decodedRc.Flag)
-		}
-		if !reflect.DeepEqual(rc.ExtFields, decodedRc.ExtFields) {
-			t.Fatalf("wrong extFields, want=%v, got=%v", rc.ExtFields, decodedRc.ExtFields)
-		}
-
-	}
-}
-
-func Benchmark_rmqCodec_decodeHeader(b *testing.B) {
-	rc := randomNewRemotingCommand()
-	headers, err := rocketMqSerializer.encodeHeader(rc)
-	if err != nil {
-		b.Fatalf("encode header with rmqCodec fail: %v", err)
-	}
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		if _, err := rocketMqSerializer.decodeHeader(headers); err != nil {
-			b.Fatalf("decode header with rmqCodec fail: %v", err)
-		}
-	}
-}
-
-func TestCommandJsonEncodeDecode(t *testing.T) {
-	var h testHeader
-	cmd := NewRemotingCommand(192, h, []byte("Hello RocketMQCodecs"))
-	codecType = JsonCodecs
-	cmdData, err := encode(cmd)
-	if err != nil {
-		t.Errorf("failed to encode remotingCommand in JSON, %s", err)
-	} else {
-		if len(cmdData) == 0 {
-			t.Errorf("failed to encode remotingCommand, result is empty.")
-		}
-	}
-	cmdData = cmdData[4:]
-	newCmd, err := decode(cmdData)
-	if err != nil {
-		t.Errorf("failed to decode remoting in JSON. %s", err)
-	}
-	if newCmd.Code != cmd.Code {
-		t.Errorf("wrong command code. want=%d, got=%d", cmd.Code, newCmd.Code)
-	}
-	if newCmd.Version != cmd.Version {
-		t.Errorf("wrong command version. want=%d, got=%d", cmd.Version, newCmd.Version)
-	}
-	if newCmd.Opaque != cmd.Opaque {
-		t.Errorf("wrong command version. want=%d, got=%d", cmd.Opaque, newCmd.Opaque)
-	}
-	if newCmd.Flag != cmd.Flag {
-		t.Errorf("wrong commad flag. want=%d, got=%d", cmd.Flag, newCmd.Flag)
-	}
-	if newCmd.Remark != cmd.Remark {
-		t.Errorf("wrong command remakr. want=%s, got=%s", cmd.Remark, newCmd.Remark)
-	}
-}
-
-func TestCommandRocketMQEncodeDecode(t *testing.T) {
-	var h testHeader
-	cmd := NewRemotingCommand(192, h, []byte("Hello RocketMQCodecs"))
-	codecType = RocketMQCodecs
-	cmdData, err := encode(cmd)
-	if err != nil {
-		t.Errorf("failed to encode remotingCommand in JSON, %s", err)
-	} else {
-		if len(cmdData) == 0 {
-			t.Errorf("failed to encode remotingCommand, result is empty.")
-		}
-	}
-	cmdData = cmdData[4:]
-	newCmd, err := decode(cmdData)
-	if err != nil {
-		t.Errorf("failed to decode remoting in JSON. %s", err)
-	}
-	if newCmd.Code != cmd.Code {
-		t.Errorf("wrong command code. want=%d, got=%d", cmd.Code, newCmd.Code)
-	}
-	if newCmd.Language != cmd.Language {
-		t.Errorf("wrong command language. want=%d, got=%d", cmd.Language, newCmd.Language)
-	}
-	if newCmd.Version != cmd.Version {
-		t.Errorf("wrong command version. want=%d, got=%d", cmd.Version, newCmd.Version)
-	}
-	if newCmd.Opaque != cmd.Opaque {
-		t.Errorf("wrong command version. want=%d, got=%d", cmd.Opaque, newCmd.Opaque)
-	}
-	if newCmd.Flag != cmd.Flag {
-		t.Errorf("wrong commad flag. want=%d, got=%d", cmd.Flag, newCmd.Flag)
-	}
-	if newCmd.Remark != cmd.Remark {
-		t.Errorf("wrong command remakr. want=%s, got=%s", cmd.Remark, newCmd.Remark)
-	}
-}
-
-func TestCommandJsonIter(t *testing.T) {
-	var h testHeader
-	cmd := NewRemotingCommand(192, h, []byte("Hello RocketMQCodecs"))
-	cmdData, err := json.Marshal(cmd)
-	assert.Nil(t, err)
-	rlog.Info("Command Data From Json", map[string]interface{}{
-		"data": *(*string)(unsafe.Pointer(&cmdData)),
-	})
-
-	data, err := jsoniter.Marshal(cmd)
-	assert.Nil(t, err)
-	rlog.Info("Command Data From Jsoniter", map[string]interface{}{
-		"data": *(*string)(unsafe.Pointer(&data)),
-	})
-
-	var cmdResp RemotingCommand
-	err = json.Unmarshal(cmdData, &cmdResp)
-	assert.Nil(t, err)
-	rlog.Info("Json Decode Success", map[string]interface{}{
-		"cmd": cmdResp,
-		"language": cmdResp.Language,
-	})
-
-	var cmdResp2 RemotingCommand
-	err = json.Unmarshal(data, &cmdResp2)
-	assert.Nil(t, err)
-	rlog.Info("Json Decode Success", map[string]interface{}{
-		"cmd": cmdResp2,
-		"language": cmdResp2.Language,
-	})
-}
diff --git a/internal/remote/future.go b/internal/remote/future.go
deleted file mode 100644
index a7d3268..0000000
--- a/internal/remote/future.go
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package remote
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"sync"
-)
-
-// ResponseFuture
-type ResponseFuture struct {
-	ResponseCommand *RemotingCommand
-	Err             error
-	Opaque          int32
-	callback        func(*ResponseFuture)
-	Done            chan bool
-	callbackOnce    sync.Once
-	ctx             context.Context
-}
-
-// NewResponseFuture create ResponseFuture with opaque, timeout and callback
-func NewResponseFuture(ctx context.Context, opaque int32, callback func(*ResponseFuture)) *ResponseFuture {
-	return &ResponseFuture{
-		Opaque:   opaque,
-		Done:     make(chan bool),
-		callback: callback,
-		ctx:      ctx,
-	}
-}
-
-func (r *ResponseFuture) executeInvokeCallback() {
-	r.callbackOnce.Do(func() {
-		if r.callback != nil {
-			r.callback(r)
-		}
-	})
-}
-
-func (r *ResponseFuture) waitResponse() (*RemotingCommand, error) {
-	var (
-		cmd *RemotingCommand
-		err error
-	)
-	select {
-	case <-r.Done:
-		cmd, err = r.ResponseCommand, r.Err
-	case <-r.ctx.Done():
-		err = errors.ErrRequestTimeout
-		r.Err = err
-	}
-	return cmd, err
-}
diff --git a/internal/remote/interceptor.go b/internal/remote/interceptor.go
deleted file mode 100644
index cf96717..0000000
--- a/internal/remote/interceptor.go
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package remote
-
-import (
-	"context"
-	"crypto/hmac"
-	"crypto/sha1"
-	"encoding/base64"
-	"hash"
-	"sort"
-	"strings"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-const (
-	signature     = "Signature"
-	accessKey     = "AccessKey"
-	securityToken = "SecurityToken"
-	keyFile       = "KEY_FILE"
-	// System.getProperty("rocketmq.client.keyFile", System.getProperty("user.home") + File.separator + "key");
-)
-
-func ACLInterceptor(credentials primitive.Credentials) primitive.Interceptor {
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		cmd := req.(*RemotingCommand)
-		m := make(map[string]string)
-		order := make([]string, 1)
-		m[accessKey] = credentials.AccessKey
-		order[0] = accessKey
-		if credentials.SecurityToken != "" {
-			m[securityToken] = credentials.SecurityToken
-		}
-		for k, v := range cmd.ExtFields {
-			m[k] = v
-			order = append(order, k)
-		}
-		sort.Slice(order, func(i, j int) bool {
-			return strings.Compare(order[i], order[j]) < 0
-		})
-		content := ""
-		for idx := range order {
-			content += m[order[idx]]
-		}
-		buf := make([]byte, len(content)+len(cmd.Body))
-		copy(buf, []byte(content))
-		copy(buf[len(content):], cmd.Body)
-
-		cmd.ExtFields[signature] = calculateSignature(buf, []byte(credentials.SecretKey))
-		cmd.ExtFields[accessKey] = credentials.AccessKey
-
-		// The SecurityToken value is unnecessary, user can choose this one.
-		if credentials.SecurityToken != "" {
-			cmd.ExtFields[securityToken] = credentials.SecurityToken
-		}
-		err := next(ctx, req, reply)
-		return err
-	}
-}
-
-func calculateSignature(data, sk []byte) string {
-	mac := hmac.New(func() hash.Hash {
-		return sha1.New()
-	}, sk)
-	mac.Write(data)
-	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
-}
diff --git a/internal/remote/interceptor_test.go b/internal/remote/interceptor_test.go
deleted file mode 100644
index c2cc6ca..0000000
--- a/internal/remote/interceptor_test.go
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package remote
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func Test_CalculateSignature(t *testing.T) {
-	assert.Equal(t, "tAb/54Rwwcq+pbH8Loi7FWX4QSQ=",
-		calculateSignature([]byte("Hello RocketMQ Client ACL Feature"), []byte("adiaushdiaushd")))
-}
diff --git a/internal/remote/mock_remote_client.go b/internal/remote/mock_remote_client.go
deleted file mode 100644
index 7d7b41c..0000000
--- a/internal/remote/mock_remote_client.go
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-// Code generated by MockGen. DO NOT EDIT.
-// Source: remote_client.go
-
-// Package remote is a generated GoMock package.
-package remote
-
-import (
-	context "context"
-	reflect "reflect"
-
-	primitive "github.com/apache/rocketmq-client-go/v2/primitive"
-	gomock "github.com/golang/mock/gomock"
-)
-
-// MockRemotingClient is a mock of RemotingClient interface
-type MockRemotingClient struct {
-	ctrl     *gomock.Controller
-	recorder *MockRemotingClientMockRecorder
-}
-
-// MockRemotingClientMockRecorder is the mock recorder for MockRemotingClient
-type MockRemotingClientMockRecorder struct {
-	mock *MockRemotingClient
-}
-
-// NewMockRemotingClient creates a new mock instance
-func NewMockRemotingClient(ctrl *gomock.Controller) *MockRemotingClient {
-	mock := &MockRemotingClient{ctrl: ctrl}
-	mock.recorder = &MockRemotingClientMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockRemotingClient) EXPECT() *MockRemotingClientMockRecorder {
-	return m.recorder
-}
-
-// RegisterRequestFunc mocks base method
-func (m *MockRemotingClient) RegisterRequestFunc(code int16, f ClientRequestFunc) {
-	m.ctrl.Call(m, "RegisterRequestFunc", code, f)
-}
-
-// RegisterRequestFunc indicates an expected call of RegisterRequestFunc
-func (mr *MockRemotingClientMockRecorder) RegisterRequestFunc(code, f interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRequestFunc", reflect.TypeOf((*MockRemotingClient)(nil).RegisterRequestFunc), code, f)
-}
-
-// RegisterInterceptor mocks base method
-func (m *MockRemotingClient) RegisterInterceptor(interceptors ...primitive.Interceptor) {
-	varargs := []interface{}{}
-	for _, a := range interceptors {
-		varargs = append(varargs, a)
-	}
-	m.ctrl.Call(m, "RegisterInterceptor", varargs...)
-}
-
-// RegisterInterceptor indicates an expected call of RegisterInterceptor
-func (mr *MockRemotingClientMockRecorder) RegisterInterceptor(interceptors ...interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInterceptor", reflect.TypeOf((*MockRemotingClient)(nil).RegisterInterceptor), interceptors...)
-}
-
-// InvokeSync mocks base method
-func (m *MockRemotingClient) InvokeSync(ctx context.Context, addr string, request *RemotingCommand) (*RemotingCommand, error) {
-	ret := m.ctrl.Call(m, "InvokeSync", ctx, addr, request)
-	ret0, _ := ret[0].(*RemotingCommand)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// InvokeSync indicates an expected call of InvokeSync
-func (mr *MockRemotingClientMockRecorder) InvokeSync(ctx, addr, request interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeSync", reflect.TypeOf((*MockRemotingClient)(nil).InvokeSync), ctx, addr, request)
-}
-
-// InvokeAsync mocks base method
-func (m *MockRemotingClient) InvokeAsync(ctx context.Context, addr string, request *RemotingCommand, callback func(*ResponseFuture)) error {
-	ret := m.ctrl.Call(m, "InvokeAsync", ctx, addr, request, callback)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// InvokeAsync indicates an expected call of InvokeAsync
-func (mr *MockRemotingClientMockRecorder) InvokeAsync(ctx, addr, request, callback interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeAsync", reflect.TypeOf((*MockRemotingClient)(nil).InvokeAsync), ctx, addr, request, callback)
-}
-
-// InvokeOneWay mocks base method
-func (m *MockRemotingClient) InvokeOneWay(ctx context.Context, addr string, request *RemotingCommand) error {
-	ret := m.ctrl.Call(m, "InvokeOneWay", ctx, addr, request)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// InvokeOneWay indicates an expected call of InvokeOneWay
-func (mr *MockRemotingClientMockRecorder) InvokeOneWay(ctx, addr, request interface{}) *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InvokeOneWay", reflect.TypeOf((*MockRemotingClient)(nil).InvokeOneWay), ctx, addr, request)
-}
-
-// ShutDown mocks base method
-func (m *MockRemotingClient) ShutDown() {
-	m.ctrl.Call(m, "ShutDown")
-}
-
-// ShutDown indicates an expected call of ShutDown
-func (mr *MockRemotingClientMockRecorder) ShutDown() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShutDown", reflect.TypeOf((*MockRemotingClient)(nil).ShutDown))
-}
diff --git a/internal/remote/remote_client.go b/internal/remote/remote_client.go
deleted file mode 100644
index 33b4633..0000000
--- a/internal/remote/remote_client.go
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package remote
-
-import (
-	"bufio"
-	"bytes"
-	"context"
-	"encoding/binary"
-	"io"
-	"net"
-	"sync"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type ClientRequestFunc func(*RemotingCommand, net.Addr) *RemotingCommand
-
-type TcpOption struct {
-	// TODO
-}
-
-//go:generate mockgen -source remote_client.go -destination mock_remote_client.go -self_package github.com/apache/rocketmq-client-go/v2/internal/remote  --package remote RemotingClient
-type RemotingClient interface {
-	RegisterRequestFunc(code int16, f ClientRequestFunc)
-	RegisterInterceptor(interceptors ...primitive.Interceptor)
-	InvokeSync(ctx context.Context, addr string, request *RemotingCommand) (*RemotingCommand, error)
-	InvokeAsync(ctx context.Context, addr string, request *RemotingCommand, callback func(*ResponseFuture)) error
-	InvokeOneWay(ctx context.Context, addr string, request *RemotingCommand) error
-	ShutDown()
-}
-
-var _ RemotingClient = &remotingClient{}
-
-type remotingClient struct {
-	responseTable    sync.Map
-	connectionTable  sync.Map
-	option           TcpOption
-	processors       map[int16]ClientRequestFunc
-	connectionLocker sync.Mutex
-	interceptor      primitive.Interceptor
-}
-
-func NewRemotingClient() *remotingClient {
-	return &remotingClient{
-		processors: make(map[int16]ClientRequestFunc),
-	}
-}
-
-func (c *remotingClient) RegisterRequestFunc(code int16, f ClientRequestFunc) {
-	c.processors[code] = f
-}
-
-// TODO: merge sync and async model. sync should run on async model by blocking on chan
-func (c *remotingClient) InvokeSync(ctx context.Context, addr string, request *RemotingCommand) (*RemotingCommand, error) {
-	conn, err := c.connect(ctx, addr)
-	if err != nil {
-		return nil, err
-	}
-	resp := NewResponseFuture(ctx, request.Opaque, nil)
-	c.responseTable.Store(resp.Opaque, resp)
-	defer c.responseTable.Delete(request.Opaque)
-	err = c.sendRequest(conn, request)
-	if err != nil {
-		return nil, err
-	}
-	return resp.waitResponse()
-}
-
-// InvokeAsync send request without blocking, just return immediately.
-func (c *remotingClient) InvokeAsync(ctx context.Context, addr string, request *RemotingCommand, callback func(*ResponseFuture)) error {
-	conn, err := c.connect(ctx, addr)
-	if err != nil {
-		return err
-	}
-	resp := NewResponseFuture(ctx, request.Opaque, callback)
-	c.responseTable.Store(resp.Opaque, resp)
-	err = c.sendRequest(conn, request)
-	if err != nil {
-		return err
-	}
-	go primitive.WithRecover(func() {
-		c.receiveAsync(resp)
-	})
-	return nil
-}
-
-func (c *remotingClient) receiveAsync(f *ResponseFuture) {
-	_, err := f.waitResponse()
-	if err != nil {
-		f.executeInvokeCallback()
-	}
-}
-
-func (c *remotingClient) InvokeOneWay(ctx context.Context, addr string, request *RemotingCommand) error {
-	conn, err := c.connect(ctx, addr)
-	if err != nil {
-		return err
-	}
-	return c.sendRequest(conn, request)
-}
-
-func (c *remotingClient) connect(ctx context.Context, addr string) (*tcpConnWrapper, error) {
-	//it needs additional locker.
-	c.connectionLocker.Lock()
-	defer c.connectionLocker.Unlock()
-	conn, ok := c.connectionTable.Load(addr)
-	if ok {
-		return conn.(*tcpConnWrapper), nil
-	}
-	tcpConn, err := initConn(ctx, addr)
-	if err != nil {
-		return nil, err
-	}
-	c.connectionTable.Store(addr, tcpConn)
-	go primitive.WithRecover(func() {
-		c.receiveResponse(tcpConn)
-	})
-	return tcpConn, nil
-}
-
-func (c *remotingClient) receiveResponse(r *tcpConnWrapper) {
-	var err error
-	header := primitive.GetHeader()
-	defer primitive.BackHeader(header)
-	for {
-		if err != nil {
-			// conn has been closed actively
-			if r.isClosed(err) {
-				return
-			}
-			if err != io.EOF {
-				rlog.Error("conn error, close connection", map[string]interface{}{
-					rlog.LogKeyUnderlayError: err,
-				})
-			}
-			c.closeConnection(r)
-			r.destroy()
-			break
-		}
-
-		_, err = io.ReadFull(r, *header)
-		if err != nil {
-			continue
-		}
-
-		var length int32
-		err = binary.Read(bytes.NewReader(*header), binary.BigEndian, &length)
-		if err != nil {
-			continue
-		}
-
-		buf := make([]byte, length)
-
-		_, err = io.ReadFull(r, buf)
-		if err != nil {
-			continue
-		}
-
-		cmd, err := decode(buf)
-		if err != nil {
-			rlog.Error("decode RemotingCommand error", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err,
-			})
-			continue
-		}
-		c.processCMD(cmd, r)
-	}
-}
-
-func (c *remotingClient) processCMD(cmd *RemotingCommand, r *tcpConnWrapper) {
-	if cmd.isResponseType() {
-		resp, exist := c.responseTable.Load(cmd.Opaque)
-		if exist {
-			c.responseTable.Delete(cmd.Opaque)
-			responseFuture := resp.(*ResponseFuture)
-			go primitive.WithRecover(func() {
-				responseFuture.ResponseCommand = cmd
-				responseFuture.executeInvokeCallback()
-				if responseFuture.Done != nil {
-					close(responseFuture.Done)
-				}
-			})
-		}
-	} else {
-		f := c.processors[cmd.Code]
-		if f != nil {
-			// single goroutine will be deadlock
-			// TODO: optimize with goroutine pool, https://github.com/apache/rocketmq-client-go/v2/issues/307
-			go primitive.WithRecover(func() {
-				res := f(cmd, r.RemoteAddr())
-				if res != nil {
-					res.Opaque = cmd.Opaque
-					res.Flag |= 1 << 0
-					err := c.sendRequest(r, res)
-					if err != nil {
-						rlog.Warning("send response to broker error", map[string]interface{}{
-							rlog.LogKeyUnderlayError: err,
-							"responseCode":           res.Code,
-						})
-					}
-				}
-			})
-		} else {
-			rlog.Warning("receive broker's requests, but no func to handle", map[string]interface{}{
-				"responseCode": cmd.Code,
-			})
-		}
-	}
-}
-
-func (c *remotingClient) createScanner(r io.Reader) *bufio.Scanner {
-	scanner := bufio.NewScanner(r)
-
-	// max batch size: 32, max message size: 4Mb
-	scanner.Buffer(make([]byte, 1024*1024), 128*1024*1024)
-	scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
-		defer func() {
-			if err := recover(); err != nil {
-				rlog.Error("scanner split panic", map[string]interface{}{
-					"panic": err,
-				})
-			}
-		}()
-		if !atEOF {
-			if len(data) >= 4 {
-				var length int32
-				err := binary.Read(bytes.NewReader(data[0:4]), binary.BigEndian, &length)
-				if err != nil {
-					rlog.Error("split data error", map[string]interface{}{
-						rlog.LogKeyUnderlayError: err,
-					})
-					return 0, nil, err
-				}
-
-				if int(length)+4 <= len(data) {
-					return int(length) + 4, data[4 : length+4], nil
-				}
-			}
-		}
-		return 0, nil, nil
-	})
-	return scanner
-}
-
-func (c *remotingClient) sendRequest(conn *tcpConnWrapper, request *RemotingCommand) error {
-	var err error
-	if c.interceptor != nil {
-		err = c.interceptor(context.Background(), request, nil, func(ctx context.Context, req, reply interface{}) error {
-			return c.doRequest(conn, request)
-		})
-	} else {
-		err = c.doRequest(conn, request)
-	}
-	return err
-}
-
-func (c *remotingClient) doRequest(conn *tcpConnWrapper, request *RemotingCommand) error {
-	conn.Lock()
-	defer conn.Unlock()
-	err := request.WriteTo(conn)
-	if err != nil {
-		c.closeConnection(conn)
-		return err
-	}
-	return nil
-}
-
-func (c *remotingClient) closeConnection(toCloseConn *tcpConnWrapper) {
-	c.connectionTable.Range(func(key, value interface{}) bool {
-		if value == toCloseConn {
-			c.connectionTable.Delete(key)
-			return false
-		} else {
-			return true
-		}
-	})
-}
-
-func (c *remotingClient) ShutDown() {
-	c.responseTable.Range(func(key, value interface{}) bool {
-		c.responseTable.Delete(key)
-		return true
-	})
-	c.connectionTable.Range(func(key, value interface{}) bool {
-		conn := value.(*tcpConnWrapper)
-		err := conn.destroy()
-		if err != nil {
-			rlog.Warning("close remoting conn error", map[string]interface{}{
-				"remote":                 conn.RemoteAddr(),
-				rlog.LogKeyUnderlayError: err,
-			})
-		}
-		return true
-	})
-}
-
-func (c *remotingClient) RegisterInterceptor(interceptors ...primitive.Interceptor) {
-	c.interceptor = primitive.ChainInterceptors(interceptors...)
-}
diff --git a/internal/remote/remote_client_test.go b/internal/remote/remote_client_test.go
deleted file mode 100644
index fa33f4f..0000000
--- a/internal/remote/remote_client_test.go
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package remote
-
-import (
-	"bytes"
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"math/rand"
-	"net"
-	"reflect"
-	"sync"
-	"testing"
-	"time"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewResponseFuture(t *testing.T) {
-	future := NewResponseFuture(context.Background(), 10, nil)
-	if future.Opaque != 10 {
-		t.Errorf("wrong ResponseFuture's opaque. want=%d, got=%d", 10, future.Opaque)
-	}
-	if future.Err != nil {
-		t.Errorf("wrong RespnseFuture's Err. want=<nil>, got=%v", future.Err)
-	}
-	if future.callback != nil {
-		t.Errorf("wrong ResponseFuture's callback. want=<nil>, got!=<nil>")
-	}
-	if future.Done == nil {
-		t.Errorf("wrong ResponseFuture's done. want=<channel>, got=<nil>")
-	}
-}
-
-func TestResponseFutureTimeout(t *testing.T) {
-	callback := func(r *ResponseFuture) {
-		if r.ResponseCommand.Remark == "" {
-			r.ResponseCommand.Remark = "Hello RocketMQ."
-		} else {
-			r.ResponseCommand.Remark = r.ResponseCommand.Remark + "Go Client"
-		}
-	}
-	future := NewResponseFuture(context.Background(), 10, callback)
-	future.ResponseCommand = NewRemotingCommand(200,
-		nil, nil)
-
-	var wg sync.WaitGroup
-	wg.Add(10)
-	for i := 0; i < 10; i++ {
-		go func() {
-			future.executeInvokeCallback()
-			wg.Done()
-		}()
-	}
-	wg.Wait()
-	if future.ResponseCommand.Remark != "Hello RocketMQ." {
-		t.Errorf("wrong ResponseFuture.ResponseCommand.Remark. want=%s, got=%s",
-			"Hello RocketMQ.", future.ResponseCommand.Remark)
-	}
-
-}
-
-func TestResponseFutureWaitResponse(t *testing.T) {
-	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(1000))
-	defer cancel()
-	future := NewResponseFuture(ctx, 10, nil)
-	if _, err := future.waitResponse(); err != errors.ErrRequestTimeout {
-		t.Errorf("wrong ResponseFuture waitResponse. want=%v, got=%v",
-			errors.ErrRequestTimeout, err)
-	}
-	future = NewResponseFuture(context.Background(), 10, nil)
-	responseError := errors.ErrResponse
-	go func() {
-		time.Sleep(100 * time.Millisecond)
-		future.Err = responseError
-		future.Done <- true
-	}()
-	if _, err := future.waitResponse(); err != responseError {
-		t.Errorf("wrong ResponseFuture waitResponse. want=%v. got=%v",
-			responseError, err)
-	}
-	future = NewResponseFuture(context.Background(), 10, nil)
-	responseRemotingCommand := NewRemotingCommand(202, nil, nil)
-	go func() {
-		time.Sleep(100 * time.Millisecond)
-		future.ResponseCommand = responseRemotingCommand
-		future.Done <- true
-	}()
-	if r, err := future.waitResponse(); err != nil {
-		t.Errorf("wrong ResponseFuture waitResponse error: %v", err)
-	} else {
-		if r != responseRemotingCommand {
-			t.Errorf("wrong ResponseFuture waitResposne result. want=%v, got=%v",
-				responseRemotingCommand, r)
-		}
-	}
-}
-
-func TestCreateScanner(t *testing.T) {
-	r := randomNewRemotingCommand()
-	content, err := encode(r)
-	if err != nil {
-		t.Fatalf("failed to encode RemotingCommand. %s", err)
-	}
-	client := NewRemotingClient()
-	reader := bytes.NewReader(content)
-	scanner := client.createScanner(reader)
-	for scanner.Scan() {
-		rcr, err := decode(scanner.Bytes())
-		if err != nil {
-			t.Fatalf("failedd to decode RemotingCommand from scanner")
-		}
-		if r.Code != rcr.Code {
-			t.Fatalf("wrong Code. want=%d, got=%d", r.Code, rcr.Code)
-		}
-		if r.Version != rcr.Version {
-			t.Fatalf("wrong Version. want=%d, got=%d", r.Version, rcr.Version)
-		}
-		if r.Opaque != rcr.Opaque {
-			t.Fatalf("wrong opaque. want=%d, got=%d", r.Opaque, rcr.Opaque)
-		}
-		if r.Flag != rcr.Flag {
-			t.Fatalf("wrong flag. want=%d, got=%d", r.Opaque, rcr.Opaque)
-		}
-		if !reflect.DeepEqual(r.ExtFields, rcr.ExtFields) {
-			t.Fatalf("wrong extFields. want=%v, got=%v", r.ExtFields, rcr.ExtFields)
-		}
-	}
-}
-
-func TestInvokeSync(t *testing.T) {
-	addr := ":3004"
-
-	clientSendRemtingCommand := NewRemotingCommand(10, nil, []byte("Hello RocketMQ"))
-	serverSendRemotingCommand := NewRemotingCommand(20, nil, []byte("Welcome native"))
-	serverSendRemotingCommand.Opaque = clientSendRemtingCommand.Opaque
-	serverSendRemotingCommand.Flag = ResponseType
-	var wg sync.WaitGroup
-	wg.Add(1)
-	client := NewRemotingClient()
-
-	var clientSend sync.WaitGroup // blocking client send message until the server listen success.
-	clientSend.Add(1)
-
-	go func() {
-		clientSend.Wait()
-		receiveCommand, err := client.InvokeSync(context.Background(), addr,
-			clientSendRemtingCommand)
-		if err != nil {
-			t.Fatalf("failed to invoke synchronous. %s", err)
-		} else {
-			assert.Equal(t, len(receiveCommand.ExtFields), 0)
-			assert.Equal(t, len(serverSendRemotingCommand.ExtFields), 0)
-			// in order to avoid the difference of ExtFields between the receiveCommand and serverSendRemotingCommand
-			// the ExtFields in receiveCommand is map[string]string(nil), but serverSendRemotingCommand is map[string]string{}
-			receiveCommand.ExtFields = nil
-			serverSendRemotingCommand.ExtFields = nil
-			assert.Equal(t, receiveCommand, serverSendRemotingCommand, "remotingCommand prased in client is different from server.")
-		}
-		wg.Done()
-	}()
-
-	l, err := net.Listen("tcp", addr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer l.Close()
-	clientSend.Done()
-	for {
-		conn, err := l.Accept()
-		if err != nil {
-			return
-		}
-		defer conn.Close()
-		scanner := client.createScanner(conn)
-		for scanner.Scan() {
-			receivedRemotingCommand, err := decode(scanner.Bytes())
-			if err != nil {
-				t.Errorf("failed to decode RemotingCommnad. %s", err)
-			}
-			if clientSendRemtingCommand.Code != receivedRemotingCommand.Code {
-				t.Errorf("wrong code. want=%d, got=%d", receivedRemotingCommand.Code,
-					clientSendRemtingCommand.Code)
-			}
-			body, err := encode(serverSendRemotingCommand)
-			if err != nil {
-				t.Fatalf("failed to encode RemotingCommand")
-			}
-			_, err = conn.Write(body)
-			if err != nil {
-				t.Fatalf("failed to write body to conneciton.")
-			}
-			goto done
-		}
-	}
-done:
-	wg.Wait()
-}
-
-func TestInvokeAsync(t *testing.T) {
-	addr := ":3006"
-	var wg sync.WaitGroup
-	cnt := 50
-	wg.Add(cnt)
-	client := NewRemotingClient()
-	for i := 0; i < cnt; i++ {
-		go func(index int) {
-			time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-			t.Logf("[Send: %d] asychronous message", index)
-			sendRemotingCommand := randomNewRemotingCommand()
-			err := client.InvokeAsync(context.Background(), addr, sendRemotingCommand, func(r *ResponseFuture) {
-				t.Logf("[Receive: %d] asychronous message response", index)
-				if string(sendRemotingCommand.Body) != string(r.ResponseCommand.Body) {
-					t.Errorf("wrong response message. want=%s, got=%s", string(sendRemotingCommand.Body),
-						string(r.ResponseCommand.Body))
-				}
-				wg.Done()
-			})
-			if err != nil {
-				t.Errorf("failed to invokeAsync. %s", err)
-			}
-
-		}(i)
-	}
-	l, err := net.Listen("tcp", addr)
-	if err != nil {
-		t.Fatalf("failed to create tcp network. %s", err)
-	}
-	defer l.Close()
-	count := 0
-	for {
-		conn, err := l.Accept()
-		if err != nil {
-			t.Fatalf("failed to create connection. %s", err)
-		}
-		defer conn.Close()
-		scanner := client.createScanner(conn)
-		for scanner.Scan() {
-			t.Log("receive request")
-			r, err := decode(scanner.Bytes())
-			if err != nil {
-				t.Errorf("failed to decode RemotingCommand %s", err)
-			}
-			r.markResponseType()
-			body, _ := encode(r)
-			_, err = conn.Write(body)
-			if err != nil {
-				t.Fatalf("failed to send response %s", err)
-			}
-			count++
-			if count >= cnt {
-				goto done
-			}
-		}
-	}
-done:
-
-	wg.Wait()
-}
-
-func TestInvokeAsyncTimeout(t *testing.T) {
-	addr := ":3002"
-
-	clientSendRemtingCommand := NewRemotingCommand(10, nil, []byte("Hello RocketMQ"))
-	serverSendRemotingCommand := NewRemotingCommand(20, nil, []byte("Welcome native"))
-	serverSendRemotingCommand.Opaque = clientSendRemtingCommand.Opaque
-	serverSendRemotingCommand.Flag = ResponseType
-
-	var wg sync.WaitGroup
-	wg.Add(1)
-	client := NewRemotingClient()
-
-	var clientSend sync.WaitGroup // blocking client send message until the server listen success.
-	clientSend.Add(1)
-	go func() {
-		clientSend.Wait()
-		ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10*time.Second))
-		defer cancel()
-		err := client.InvokeAsync(ctx, addr, clientSendRemtingCommand,
-			func(r *ResponseFuture) {
-				assert.NotNil(t, r.Err)
-				assert.Equal(t, errors.ErrRequestTimeout, r.Err)
-				wg.Done()
-			})
-		assert.Nil(t, err, "failed to invokeSync.")
-	}()
-
-	l, err := net.Listen("tcp", addr)
-	assert.Nil(t, err)
-	defer l.Close()
-	clientSend.Done()
-
-	for {
-		conn, err := l.Accept()
-		assert.Nil(t, err)
-		defer conn.Close()
-
-		scanner := client.createScanner(conn)
-		for scanner.Scan() {
-			t.Logf("receive request.")
-			_, err := decode(scanner.Bytes())
-			assert.Nil(t, err, "failed to decode RemotingCommnad.")
-
-			time.Sleep(5 * time.Second) // force client timeout
-			goto done
-		}
-	}
-done:
-	wg.Wait()
-}
-
-func TestInvokeOneWay(t *testing.T) {
-	addr := ":3008"
-	clientSendRemtingCommand := NewRemotingCommand(10, nil, []byte("Hello RocketMQ"))
-
-	var wg sync.WaitGroup
-	wg.Add(1)
-	client := NewRemotingClient()
-
-	var clientSend sync.WaitGroup // blocking client send message until the server listen success.
-	clientSend.Add(1)
-	go func() {
-		clientSend.Wait()
-		err := client.InvokeOneWay(context.Background(), addr, clientSendRemtingCommand)
-		if err != nil {
-			t.Fatalf("failed to invoke synchronous. %s", err)
-		}
-		wg.Done()
-	}()
-
-	l, err := net.Listen("tcp", addr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer l.Close()
-	clientSend.Done()
-	for {
-		conn, err := l.Accept()
-		if err != nil {
-			return
-		}
-		defer conn.Close()
-		scanner := client.createScanner(conn)
-		for scanner.Scan() {
-			receivedRemotingCommand, err := decode(scanner.Bytes())
-			if err != nil {
-				t.Errorf("failed to decode RemotingCommnad. %s", err)
-			}
-			if clientSendRemtingCommand.Code != receivedRemotingCommand.Code {
-				t.Errorf("wrong code. want=%d, got=%d", receivedRemotingCommand.Code,
-					clientSendRemtingCommand.Code)
-			}
-			goto done
-		}
-	}
-done:
-	wg.Wait()
-}
diff --git a/internal/remote/rpchook.go b/internal/remote/rpchook.go
deleted file mode 100644
index a95391d..0000000
--- a/internal/remote/rpchook.go
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package remote
-
-type RPCHook interface {
-	DoBeforeRequest(string, *RemotingCommand)
-	DoAfterResponse(string, *RemotingCommand)
-}
diff --git a/internal/remote/tcp_conn.go b/internal/remote/tcp_conn.go
deleted file mode 100644
index ae340c6..0000000
--- a/internal/remote/tcp_conn.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package remote
-
-import (
-	"context"
-	"net"
-	"sync"
-
-	"go.uber.org/atomic"
-)
-
-// TODO: Adding TCP Connections Pool, https://github.com/apache/rocketmq-client-go/v2/issues/298
-type tcpConnWrapper struct {
-	net.Conn
-	sync.Mutex
-	closed atomic.Bool
-}
-
-func initConn(ctx context.Context, addr string) (*tcpConnWrapper, error) {
-	var d net.Dialer
-	conn, err := d.DialContext(ctx, "tcp", addr)
-	if err != nil {
-		return nil, err
-	}
-	return &tcpConnWrapper{
-		Conn: conn,
-	}, nil
-}
-
-func (wrapper *tcpConnWrapper) destroy() error {
-	wrapper.closed.Swap(true)
-	return wrapper.Conn.Close()
-}
-
-func (wrapper *tcpConnWrapper) isClosed(err error) bool {
-	if !wrapper.closed.Load() {
-		return false
-	}
-
-	opErr, ok := err.(*net.OpError)
-	if !ok {
-		return false
-	}
-
-	return opErr.Err.Error() == "use of closed network connection"
-}
diff --git a/internal/request.go b/internal/request.go
deleted file mode 100644
index 0e3d8e1..0000000
--- a/internal/request.go
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"fmt"
-	"strconv"
-	"time"
-)
-
-const (
-	ReqSendMessage                   = int16(10)
-	ReqPullMessage                   = int16(11)
-	ReqQueryMessage                  = int16(12)
-	ReqQueryConsumerOffset           = int16(14)
-	ReqUpdateConsumerOffset          = int16(15)
-	ReqCreateTopic                   = int16(17)
-	ReqSearchOffsetByTimestamp       = int16(29)
-	ReqGetMaxOffset                  = int16(30)
-	ReqGetMinOffset                  = int16(31)
-	ReqViewMessageByID               = int16(33)
-	ReqHeartBeat                     = int16(34)
-	ReqConsumerSendMsgBack           = int16(36)
-	ReqENDTransaction                = int16(37)
-	ReqGetConsumerListByGroup        = int16(38)
-	ReqLockBatchMQ                   = int16(41)
-	ReqUnlockBatchMQ                 = int16(42)
-	ReqGetRouteInfoByTopic           = int16(105)
-	ReqGetBrokerClusterInfo          = int16(106)
-	ReqSendBatchMessage              = int16(320)
-	ReqCheckTransactionState         = int16(39)
-	ReqNotifyConsumerIdsChanged      = int16(40)
-	ReqGetAllTopicListFromNameServer = int16(206)
-	ReqDeleteTopicInBroker           = int16(215)
-	ReqDeleteTopicInNameSrv          = int16(216)
-	ReqResetConsumerOffset           = int16(220)
-	ReqGetConsumerRunningInfo        = int16(307)
-	ReqConsumeMessageDirectly        = int16(309)
-)
-
-type SendMessageRequestHeader struct {
-	ProducerGroup         string
-	Topic                 string
-	QueueId               int
-	SysFlag               int
-	BornTimestamp         int64
-	Flag                  int32
-	Properties            string
-	ReconsumeTimes        int
-	UnitMode              bool
-	MaxReconsumeTimes     int
-	Batch                 bool
-	DefaultTopic          string
-	DefaultTopicQueueNums int
-}
-
-func (request *SendMessageRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["producerGroup"] = request.ProducerGroup
-	maps["topic"] = request.Topic
-	maps["queueId"] = strconv.Itoa(request.QueueId)
-	maps["sysFlag"] = fmt.Sprintf("%d", request.SysFlag)
-	maps["bornTimestamp"] = strconv.FormatInt(request.BornTimestamp, 10)
-	maps["flag"] = fmt.Sprintf("%d", request.Flag)
-	maps["reconsumeTimes"] = strconv.Itoa(request.ReconsumeTimes)
-	maps["unitMode"] = strconv.FormatBool(request.UnitMode)
-	maps["maxReconsumeTimes"] = strconv.Itoa(request.MaxReconsumeTimes)
-	maps["defaultTopic"] = "TBW102"
-	maps["defaultTopicQueueNums"] = "4"
-	maps["batch"] = strconv.FormatBool(request.Batch)
-	maps["properties"] = request.Properties
-
-	return maps
-}
-
-type EndTransactionRequestHeader struct {
-	ProducerGroup        string
-	TranStateTableOffset int64
-	CommitLogOffset      int64
-	CommitOrRollback     int
-	FromTransactionCheck bool
-	MsgID                string
-	TransactionId        string
-}
-
-type SendMessageRequestV2Header struct {
-	*SendMessageRequestHeader
-}
-
-func (request *SendMessageRequestV2Header) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["a"] = request.ProducerGroup
-	maps["b"] = request.Topic
-	maps["c"] = request.DefaultTopic
-	maps["d"] = strconv.Itoa(request.DefaultTopicQueueNums)
-	maps["e"] = strconv.Itoa(request.QueueId)
-	maps["f"] = fmt.Sprintf("%d", request.SysFlag)
-	maps["g"] = strconv.FormatInt(request.BornTimestamp, 10)
-	maps["h"] = fmt.Sprintf("%d", request.Flag)
-	maps["i"] = request.Properties
-	maps["j"] = strconv.Itoa(request.ReconsumeTimes)
-	maps["k"] = strconv.FormatBool(request.UnitMode)
-	maps["l"] = strconv.Itoa(request.MaxReconsumeTimes)
-	maps["m"] = strconv.FormatBool(request.Batch)
-	return maps
-}
-
-func (request *EndTransactionRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["producerGroup"] = request.ProducerGroup
-	maps["tranStateTableOffset"] = strconv.FormatInt(request.TranStateTableOffset, 10)
-	maps["commitLogOffset"] = strconv.Itoa(int(request.CommitLogOffset))
-	maps["commitOrRollback"] = strconv.Itoa(request.CommitOrRollback)
-	maps["fromTransactionCheck"] = strconv.FormatBool(request.FromTransactionCheck)
-	maps["msgId"] = request.MsgID
-	maps["transactionId"] = request.TransactionId
-	return maps
-}
-
-type CheckTransactionStateRequestHeader struct {
-	TranStateTableOffset int64
-	CommitLogOffset      int64
-	MsgId                string
-	TransactionId        string
-	OffsetMsgId          string
-}
-
-func (request *CheckTransactionStateRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["tranStateTableOffset"] = strconv.FormatInt(request.TranStateTableOffset, 10)
-	maps["commitLogOffset"] = strconv.FormatInt(request.CommitLogOffset, 10)
-	maps["msgId"] = request.MsgId
-	maps["transactionId"] = request.TransactionId
-	maps["offsetMsgId"] = request.OffsetMsgId
-
-	return maps
-}
-
-func (request *CheckTransactionStateRequestHeader) Decode(properties map[string]string) {
-	if len(properties) == 0 {
-		return
-	}
-	if v, existed := properties["tranStateTableOffset"]; existed {
-		request.TranStateTableOffset, _ = strconv.ParseInt(v, 10, 0)
-	}
-	if v, existed := properties["commitLogOffset"]; existed {
-		request.CommitLogOffset, _ = strconv.ParseInt(v, 10, 0)
-	}
-	if v, existed := properties["msgId"]; existed {
-		request.MsgId = v
-	}
-	if v, existed := properties["transactionId"]; existed {
-		request.MsgId = v
-	}
-	if v, existed := properties["offsetMsgId"]; existed {
-		request.MsgId = v
-	}
-}
-
-type ConsumerSendMsgBackRequestHeader struct {
-	Group             string
-	Offset            int64
-	DelayLevel        int
-	OriginMsgId       string
-	OriginTopic       string
-	UnitMode          bool
-	MaxReconsumeTimes int32
-}
-
-func (request *ConsumerSendMsgBackRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["group"] = request.Group
-	maps["offset"] = strconv.FormatInt(request.Offset, 10)
-	maps["delayLevel"] = strconv.Itoa(request.DelayLevel)
-	maps["originMsgId"] = request.OriginMsgId
-	maps["originTopic"] = request.OriginTopic
-	maps["unitMode"] = strconv.FormatBool(request.UnitMode)
-	maps["maxReconsumeTimes"] = strconv.Itoa(int(request.MaxReconsumeTimes))
-
-	return maps
-}
-
-type PullMessageRequestHeader struct {
-	ConsumerGroup        string
-	Topic                string
-	QueueId              int32
-	QueueOffset          int64
-	MaxMsgNums           int32
-	SysFlag              int32
-	CommitOffset         int64
-	SuspendTimeoutMillis time.Duration
-	SubExpression        string
-	SubVersion           int64
-	ExpressionType       string
-}
-
-func (request *PullMessageRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.ConsumerGroup
-	maps["topic"] = request.Topic
-	maps["queueId"] = fmt.Sprintf("%d", request.QueueId)
-	maps["queueOffset"] = fmt.Sprintf("%d", request.QueueOffset)
-	maps["maxMsgNums"] = fmt.Sprintf("%d", request.MaxMsgNums)
-	maps["sysFlag"] = fmt.Sprintf("%d", request.SysFlag)
-	maps["commitOffset"] = fmt.Sprintf("%d", request.CommitOffset)
-	maps["suspendTimeoutMillis"] = fmt.Sprintf("%d", request.SuspendTimeoutMillis/time.Millisecond)
-	maps["subscription"] = request.SubExpression
-	maps["subVersion"] = fmt.Sprintf("%d", request.SubVersion)
-	maps["expressionType"] = request.ExpressionType
-
-	return maps
-}
-
-type GetConsumerListRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-}
-
-func (request *GetConsumerListRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.ConsumerGroup
-	return maps
-}
-
-type GetMaxOffsetRequestHeader struct {
-	Topic   string
-	QueueId int
-}
-
-func (request *GetMaxOffsetRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-	maps["queueId"] = strconv.Itoa(request.QueueId)
-	return maps
-}
-
-type QueryConsumerOffsetRequestHeader struct {
-	ConsumerGroup string
-	Topic         string
-	QueueId       int
-}
-
-func (request *QueryConsumerOffsetRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.ConsumerGroup
-	maps["topic"] = request.Topic
-	maps["queueId"] = strconv.Itoa(request.QueueId)
-	return maps
-}
-
-type SearchOffsetRequestHeader struct {
-	Topic     string
-	QueueId   int
-	Timestamp int64
-}
-
-func (request *SearchOffsetRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-	maps["queueId"] = strconv.Itoa(request.QueueId)
-	maps["timestamp"] = strconv.FormatInt(request.Timestamp, 10)
-	return maps
-}
-
-type UpdateConsumerOffsetRequestHeader struct {
-	ConsumerGroup string
-	Topic         string
-	QueueId       int
-	CommitOffset  int64
-}
-
-func (request *UpdateConsumerOffsetRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.ConsumerGroup
-	maps["topic"] = request.Topic
-	maps["queueId"] = strconv.Itoa(request.QueueId)
-	maps["commitOffset"] = strconv.FormatInt(request.CommitOffset, 10)
-	return maps
-}
-
-type GetRouteInfoRequestHeader struct {
-	Topic string
-}
-
-func (request *GetRouteInfoRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-	return maps
-}
-
-type GetConsumerRunningInfoHeader struct {
-	consumerGroup string
-	clientID      string
-}
-
-func (request *GetConsumerRunningInfoHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.consumerGroup
-	maps["clientId"] = request.clientID
-	return maps
-}
-
-func (request *GetConsumerRunningInfoHeader) Decode(properties map[string]string) {
-	if len(properties) == 0 {
-		return
-	}
-	if v, existed := properties["consumerGroup"]; existed {
-		request.consumerGroup = v
-	}
-
-	if v, existed := properties["clientId"]; existed {
-		request.clientID = v
-	}
-}
-
-type QueryMessageRequestHeader struct {
-	Topic          string
-	Key            string
-	MaxNum         int
-	BeginTimestamp int64
-	EndTimestamp   int64
-}
-
-func (request *QueryMessageRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-	maps["key"] = request.Key
-	maps["maxNum"] = fmt.Sprintf("%d", request.MaxNum)
-	maps["beginTimestamp"] = strconv.FormatInt(request.BeginTimestamp, 10)
-	maps["endTimestamp"] = fmt.Sprintf("%d", request.EndTimestamp)
-
-	return maps
-}
-
-func (request *QueryMessageRequestHeader) Decode(properties map[string]string) error {
-	return nil
-}
-
-type ViewMessageRequestHeader struct {
-	Offset int64
-}
-
-func (request *ViewMessageRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["offset"] = strconv.FormatInt(request.Offset, 10)
-
-	return maps
-}
-
-type CreateTopicRequestHeader struct {
-	Topic           string
-	DefaultTopic    string
-	ReadQueueNums   int
-	WriteQueueNums  int
-	Perm            int
-	TopicFilterType string
-	TopicSysFlag    int
-	Order           bool
-}
-
-func (request *CreateTopicRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-	maps["defaultTopic"] = request.DefaultTopic
-	maps["readQueueNums"] = fmt.Sprintf("%d", request.ReadQueueNums)
-	maps["writeQueueNums"] = fmt.Sprintf("%d", request.WriteQueueNums)
-	maps["perm"] = fmt.Sprintf("%d", request.Perm)
-	maps["topicFilterType"] = request.TopicFilterType
-	maps["topicSysFlag"] = fmt.Sprintf("%d", request.TopicSysFlag)
-	maps["order"] = strconv.FormatBool(request.Order)
-
-	return maps
-}
-
-type TopicListRequestHeader struct {
-	Topic string
-}
-
-func (request *TopicListRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-
-	return maps
-}
-
-type DeleteTopicRequestHeader struct {
-	Topic string
-}
-
-func (request *DeleteTopicRequestHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.Topic
-
-	return maps
-}
-
-type ResetOffsetHeader struct {
-	topic     string
-	group     string
-	timestamp int64
-	isForce   bool
-}
-
-func (request *ResetOffsetHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["topic"] = request.topic
-	maps["group"] = request.group
-	maps["timestamp"] = strconv.FormatInt(request.timestamp, 10)
-	return maps
-}
-
-func (request *ResetOffsetHeader) Decode(properties map[string]string) {
-	if len(properties) == 0 {
-		return
-	}
-
-	if v, existed := properties["topic"]; existed {
-		request.topic = v
-	}
-
-	if v, existed := properties["group"]; existed {
-		request.group = v
-	}
-
-	if v, existed := properties["timestamp"]; existed {
-		request.timestamp, _ = strconv.ParseInt(v, 10, 0)
-	}
-}
-
-type ConsumeMessageDirectlyHeader struct {
-	consumerGroup string
-	clientID      string
-	msgId         string
-	brokerName    string
-}
-
-func (request *ConsumeMessageDirectlyHeader) Encode() map[string]string {
-	maps := make(map[string]string)
-	maps["consumerGroup"] = request.consumerGroup
-	maps["clientId"] = request.clientID
-	maps["msgId"] = request.msgId
-	maps["brokerName"] = request.brokerName
-	return maps
-}
-
-func (request *ConsumeMessageDirectlyHeader) Decode(properties map[string]string) {
-	if len(properties) == 0 {
-		return
-	}
-
-	if v, existed := properties["consumerGroup"]; existed {
-		request.consumerGroup = v
-	}
-
-	if v, existed := properties["clientId"]; existed {
-		request.clientID = v
-	}
-
-	if v, existed := properties["msgId"]; existed {
-		request.msgId = v
-	}
-
-	if v, existed := properties["brokerName"]; existed {
-		request.brokerName = v
-	}
-}
diff --git a/internal/response.go b/internal/response.go
deleted file mode 100644
index ae75b9c..0000000
--- a/internal/response.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-const (
-	ResSuccess              = int16(0)
-	ResError                = int16(1)
-	ResFlushDiskTimeout     = int16(10)
-	ResSlaveNotAvailable    = int16(11)
-	ResFlushSlaveTimeout    = int16(12)
-	ResTopicNotExist        = int16(17)
-	ResPullNotFound         = int16(19)
-	ResPullRetryImmediately = int16(20)
-	ResPullOffsetMoved      = int16(21)
-)
-
-type SendMessageResponse struct {
-	MsgId         string
-	QueueId       int32
-	QueueOffset   int64
-	TransactionId string
-	MsgRegion     string
-}
-
-func (response *SendMessageResponse) Decode(properties map[string]string) {
-
-}
-
-type PullMessageResponse struct {
-	SuggestWhichBrokerId int64
-	NextBeginOffset      int64
-	MinOffset            int64
-	MaxOffset            int64
-}
diff --git a/internal/route.go b/internal/route.go
deleted file mode 100644
index 54dbbea..0000000
--- a/internal/route.go
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"math/rand"
-	"sort"
-	"strconv"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	jsoniter "github.com/json-iterator/go"
-	"github.com/tidwall/gjson"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-const (
-	EnvNameServerAddr = "NAMESRV_ADDR"
-
-	requestTimeout   = 3 * time.Second
-	defaultTopic     = "TBW102"
-	defaultQueueNums = 4
-	MasterId         = int64(0)
-)
-
-func (s *namesrvs) cleanOfflineBroker() {
-	// TODO optimize
-	s.lockNamesrv.Lock()
-	s.brokerAddressesMap.Range(func(key, value interface{}) bool {
-		brokerName := key.(string)
-		bd := value.(*BrokerData)
-		for k, v := range bd.BrokerAddresses {
-			isBrokerAddrExistInTopicRoute := false
-			s.routeDataMap.Range(func(key, value interface{}) bool {
-				trd := value.(*TopicRouteData)
-				for idx := range trd.BrokerDataList {
-					for _, v1 := range trd.BrokerDataList[idx].BrokerAddresses {
-						if v1 == v {
-							isBrokerAddrExistInTopicRoute = true
-							return false
-						}
-					}
-				}
-				return true
-			})
-			if !isBrokerAddrExistInTopicRoute {
-				delete(bd.BrokerAddresses, k)
-				rlog.Info("the broker: [name=%s, ID=%d, addr=%s,] is offline, remove it", map[string]interface{}{
-					"brokerName": brokerName,
-					"brokerID":   k,
-					"brokerAddr": v,
-				})
-			}
-		}
-		if len(bd.BrokerAddresses) == 0 {
-			s.brokerAddressesMap.Delete(brokerName)
-			rlog.Info("the broker name's host is offline, remove it", map[string]interface{}{
-				"brokerName": brokerName,
-			})
-		}
-		return true
-	})
-	s.lockNamesrv.Unlock()
-}
-
-// key is topic, value is TopicPublishInfo
-type TopicPublishInfo struct {
-	OrderTopic          bool
-	HaveTopicRouterInfo bool
-	MqList              []*primitive.MessageQueue
-	RouteData           *TopicRouteData
-	TopicQueueIndex     int32
-}
-
-func (info *TopicPublishInfo) isOK() (bIsTopicOk bool) {
-	return len(info.MqList) > 0
-}
-
-func (info *TopicPublishInfo) fetchQueueIndex() int {
-	length := len(info.MqList)
-	if length <= 0 {
-		return -1
-	}
-	qIndex := atomic.AddInt32(&info.TopicQueueIndex, 1)
-	return int(qIndex) % length
-}
-
-func (s *namesrvs) UpdateTopicRouteInfo(topic string) (*TopicRouteData, bool, error) {
-	return s.UpdateTopicRouteInfoWithDefault(topic, "", 0)
-}
-
-func (s *namesrvs) UpdateTopicRouteInfoWithDefault(topic string, defaultTopic string, defaultQueueNum int) (*TopicRouteData, bool, error) {
-	s.lockNamesrv.Lock()
-	defer s.lockNamesrv.Unlock()
-
-	var (
-		routeData *TopicRouteData
-		err       error
-	)
-
-	t := topic
-	if len(defaultTopic) > 0 {
-		t = defaultTopic
-	}
-	routeData, err = s.queryTopicRouteInfoFromServer(t)
-
-	if err != nil {
-		rlog.Warning("query topic route from server error", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-	}
-
-	if routeData == nil {
-		rlog.Warning("queryTopicRouteInfoFromServer return nil", map[string]interface{}{
-			rlog.LogKeyTopic: topic,
-		})
-		return nil, false, err
-	}
-
-	if len(defaultTopic) > 0 {
-		for _, q := range routeData.QueueDataList {
-			if q.ReadQueueNums > defaultQueueNum {
-				q.ReadQueueNums = defaultQueueNum
-				q.WriteQueueNums = defaultQueueNum
-			}
-		}
-	}
-
-	oldRouteData, exist := s.routeDataMap.Load(topic)
-
-	changed := true
-	if exist {
-		changed = s.topicRouteDataIsChange(oldRouteData.(*TopicRouteData), routeData)
-	}
-
-	if changed {
-		if s.bundleClient != nil {
-			s.bundleClient.producerMap.Range(func(key, value interface{}) bool {
-				p := value.(InnerProducer)
-				updated := changed
-				if !updated {
-					updated = p.IsPublishTopicNeedUpdate(topic)
-				}
-				if updated {
-					publishInfo := s.bundleClient.GetNameSrv().(*namesrvs).routeData2PublishInfo(topic, routeData)
-					publishInfo.HaveTopicRouterInfo = true
-					p.UpdateTopicPublishInfo(topic, publishInfo)
-				}
-				return true
-			})
-			s.bundleClient.consumerMap.Range(func(key, value interface{}) bool {
-				consumer := value.(InnerConsumer)
-				updated := changed
-				if !updated {
-					updated = consumer.IsSubscribeTopicNeedUpdate(topic)
-				}
-				if updated {
-					consumer.UpdateTopicSubscribeInfo(topic, routeData2SubscribeInfo(topic, routeData))
-				}
-
-				return true
-			})
-			rlog.Info("change the route for clients", nil)
-		}
-
-		s.routeDataMap.Store(topic, routeData)
-		rlog.Info("the topic route info changed", map[string]interface{}{
-			rlog.LogKeyTopic:            topic,
-			rlog.LogKeyValueChangedFrom: oldRouteData,
-			rlog.LogKeyValueChangedTo:   routeData.String(),
-		})
-		for _, brokerData := range routeData.BrokerDataList {
-			s.brokerAddressesMap.Store(brokerData.BrokerName, brokerData)
-		}
-	}
-
-	return routeData.clone(), changed, nil
-}
-
-func (s *namesrvs) AddBroker(routeData *TopicRouteData) {
-	for _, brokerData := range routeData.BrokerDataList {
-		s.brokerAddressesMap.Store(brokerData.BrokerName, brokerData)
-	}
-}
-
-func (s *namesrvs) FindBrokerAddrByTopic(topic string) string {
-	v, exist := s.routeDataMap.Load(topic)
-	if !exist {
-		return ""
-	}
-	routeData := v.(*TopicRouteData)
-	if len(routeData.BrokerDataList) == 0 {
-		return ""
-	}
-	i := utils.AbsInt(rand.Int())
-	bd := routeData.BrokerDataList[i%len(routeData.BrokerDataList)]
-	addr := bd.BrokerAddresses[MasterId]
-	if addr == "" && len(bd.BrokerAddresses) > 0 {
-		i = i % len(bd.BrokerAddresses)
-		for _, v := range bd.BrokerAddresses {
-			if i <= 0 {
-				addr = v
-				break
-			}
-			i--
-		}
-	}
-	return addr
-}
-
-func (s *namesrvs) FindBrokerAddrByName(brokerName string) string {
-	bd, exist := s.brokerAddressesMap.Load(brokerName)
-
-	if !exist {
-		return ""
-	}
-
-	return bd.(*BrokerData).BrokerAddresses[MasterId]
-}
-
-func (s *namesrvs) FindBrokerAddressInSubscribe(brokerName string, brokerId int64, onlyThisBroker bool) *FindBrokerResult {
-	var (
-		brokerAddr = ""
-		slave      = false
-		found      = false
-	)
-
-	rlog.Debug("broker id "+strconv.FormatInt(brokerId, 10), nil)
-
-	v, exist := s.brokerAddressesMap.Load(brokerName)
-
-	if !exist {
-		return nil
-	}
-	data := v.(*BrokerData)
-	if len(data.BrokerAddresses) == 0 {
-		return nil
-	}
-
-	brokerAddr = data.BrokerAddresses[brokerId]
-	slave = brokerId != MasterId
-	if brokerAddr != "" {
-		found = true
-	}
-
-	// not found && read from slave, try again use next brokerId
-	if !found && slave {
-		rlog.Debug("Not found broker addr and slave "+strconv.FormatBool(slave), nil)
-		brokerAddr = data.BrokerAddresses[brokerId+1]
-		found = brokerAddr != ""
-	}
-
-	// still not found && cloud use other broker addr, find anyone in BrokerAddresses
-	if !found && !onlyThisBroker {
-		rlog.Debug("STILL Not found broker addr", nil)
-		for k, v := range data.BrokerAddresses {
-			if v != "" {
-				brokerAddr = v
-				found = true
-				slave = k != MasterId
-				break
-			}
-		}
-	}
-
-	if found {
-		rlog.Debug("Find broker addr "+brokerAddr, nil)
-	}
-
-	var result *FindBrokerResult
-	if found {
-		result = &FindBrokerResult{
-			BrokerAddr:    brokerAddr,
-			Slave:         slave,
-			BrokerVersion: s.findBrokerVersion(brokerName, brokerAddr),
-		}
-	}
-
-	return result
-}
-
-func (s *namesrvs) FetchSubscribeMessageQueues(topic string) ([]*primitive.MessageQueue, error) {
-	routeData, err := s.queryTopicRouteInfoFromServer(topic)
-
-	if err != nil {
-		return nil, err
-	}
-
-	mqs := make([]*primitive.MessageQueue, 0)
-
-	for _, qd := range routeData.QueueDataList {
-		if queueIsReadable(qd.Perm) {
-			for i := 0; i < qd.ReadQueueNums; i++ {
-				mqs = append(mqs, &primitive.MessageQueue{Topic: topic, BrokerName: qd.BrokerName, QueueId: i})
-			}
-		}
-	}
-	return mqs, nil
-}
-
-func (s *namesrvs) FetchPublishMessageQueues(topic string) ([]*primitive.MessageQueue, error) {
-	var (
-		err       error
-		routeData *TopicRouteData
-	)
-
-	v, exist := s.routeDataMap.Load(topic)
-	if !exist {
-		routeData, err = s.queryTopicRouteInfoFromServer(topic)
-		if err != nil {
-			rlog.Error("queryTopicRouteInfoFromServer failed", map[string]interface{}{
-				rlog.LogKeyTopic: topic,
-			})
-			return nil, err
-		}
-		s.routeDataMap.Store(topic, routeData)
-		s.AddBroker(routeData)
-	} else {
-		routeData = v.(*TopicRouteData)
-	}
-
-	if err != nil {
-		return nil, err
-	}
-	publishInfo := s.routeData2PublishInfo(topic, routeData)
-
-	return publishInfo.MqList, nil
-}
-
-func (s *namesrvs) AddBrokerVersion(brokerName, brokerAddr string, version int32) {
-	s.brokerLock.Lock()
-	defer s.brokerLock.Unlock()
-
-	m, exist := s.brokerVersionMap[brokerName]
-	if !exist {
-		m = make(map[string]int32, 4)
-		s.brokerVersionMap[brokerName] = m
-	}
-	m[brokerAddr] = version
-}
-
-func (s *namesrvs) findBrokerVersion(brokerName, brokerAddr string) int32 {
-	s.brokerLock.RLock()
-	defer s.brokerLock.RUnlock()
-
-	versions, exist := s.brokerVersionMap[brokerName]
-
-	if !exist {
-		return 0
-	}
-
-	return versions[brokerAddr]
-}
-
-func (s *namesrvs) queryTopicRouteInfoFromServer(topic string) (*TopicRouteData, error) {
-	request := &GetRouteInfoRequestHeader{
-		Topic: topic,
-	}
-
-	var (
-		response *remote.RemotingCommand
-		err      error
-	)
-
-	//if s.Size() == 0, response will be nil, lead to panic below.
-	if s.Size() == 0 {
-		rlog.Error("namesrv list empty. UpdateNameServerAddress should be called first.", map[string]interface{}{
-			"namesrv": s,
-			"topic":   topic,
-		})
-		return nil, primitive.NewRemotingErr("namesrv list empty")
-	}
-
-	for i := 0; i < s.Size(); i++ {
-		rc := remote.NewRemotingCommand(ReqGetRouteInfoByTopic, request, nil)
-		ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
-		response, err = s.nameSrvClient.InvokeSync(ctx, s.getNameServerAddress(), rc)
-
-		if err == nil {
-			cancel()
-			break
-		}
-		cancel()
-	}
-	if err != nil {
-		rlog.Error("connect to namesrv failed.", map[string]interface{}{
-			"namesrv": s,
-			"topic":   topic,
-		})
-		return nil, primitive.NewRemotingErr(err.Error())
-	}
-
-	switch response.Code {
-	case ResSuccess:
-		if response.Body == nil {
-			return nil, primitive.NewMQClientErr(response.Code, response.Remark)
-		}
-		routeData := &TopicRouteData{}
-
-		err = routeData.decode(string(response.Body))
-		if err != nil {
-			rlog.Warning("decode TopicRouteData error: %s", map[string]interface{}{
-				rlog.LogKeyUnderlayError: err,
-				"topic":                  topic,
-			})
-			return nil, err
-		}
-		return routeData, nil
-	case ResTopicNotExist:
-		return nil, errors.ErrTopicNotExist
-	default:
-		return nil, primitive.NewMQClientErr(response.Code, response.Remark)
-	}
-}
-
-func (s *namesrvs) topicRouteDataIsChange(oldData *TopicRouteData, newData *TopicRouteData) bool {
-	if oldData == nil || newData == nil {
-		return true
-	}
-	oldDataCloned := oldData.clone()
-	newDataCloned := newData.clone()
-
-	sort.Slice(oldDataCloned.QueueDataList, func(i, j int) bool {
-		return strings.Compare(oldDataCloned.QueueDataList[i].BrokerName, oldDataCloned.QueueDataList[j].BrokerName) > 0
-	})
-	sort.Slice(oldDataCloned.BrokerDataList, func(i, j int) bool {
-		return strings.Compare(oldDataCloned.BrokerDataList[i].BrokerName, oldDataCloned.BrokerDataList[j].BrokerName) > 0
-	})
-	sort.Slice(newDataCloned.QueueDataList, func(i, j int) bool {
-		return strings.Compare(newDataCloned.QueueDataList[i].BrokerName, newDataCloned.QueueDataList[j].BrokerName) > 0
-	})
-	sort.Slice(newDataCloned.BrokerDataList, func(i, j int) bool {
-		return strings.Compare(newDataCloned.BrokerDataList[i].BrokerName, newDataCloned.BrokerDataList[j].BrokerName) > 0
-	})
-
-	return !oldDataCloned.equals(newDataCloned)
-}
-
-func (s *namesrvs) routeData2PublishInfo(topic string, data *TopicRouteData) *TopicPublishInfo {
-	publishInfo := &TopicPublishInfo{
-		RouteData:  data,
-		OrderTopic: false,
-	}
-
-	if data.OrderTopicConf != "" {
-		brokers := strings.Split(data.OrderTopicConf, ";")
-		for _, broker := range brokers {
-			item := strings.Split(broker, ":")
-			nums, _ := strconv.Atoi(item[1])
-			for i := 0; i < nums; i++ {
-				mq := &primitive.MessageQueue{
-					Topic:      topic,
-					BrokerName: item[0],
-					QueueId:    i,
-				}
-				publishInfo.MqList = append(publishInfo.MqList, mq)
-			}
-		}
-
-		publishInfo.OrderTopic = true
-		return publishInfo
-	}
-
-	qds := data.QueueDataList
-	sort.Slice(qds, func(i, j int) bool {
-		return i-j >= 0
-	})
-
-	for _, qd := range qds {
-		if !queueIsWriteable(qd.Perm) {
-			continue
-		}
-
-		var bData *BrokerData
-		for _, bd := range data.BrokerDataList {
-			if bd.BrokerName == qd.BrokerName {
-				bData = bd
-				break
-			}
-		}
-
-		if bData == nil || bData.BrokerAddresses[MasterId] == "" {
-			continue
-		}
-
-		for i := 0; i < qd.WriteQueueNums; i++ {
-			mq := &primitive.MessageQueue{
-				Topic:      topic,
-				BrokerName: qd.BrokerName,
-				QueueId:    i,
-			}
-			publishInfo.MqList = append(publishInfo.MqList, mq)
-		}
-	}
-
-	return publishInfo
-}
-
-// TopicRouteData TopicRouteData
-type TopicRouteData struct {
-	OrderTopicConf string
-	QueueDataList  []*QueueData  `json:"queueDatas"`
-	BrokerDataList []*BrokerData `json:"brokerDatas"`
-}
-
-func (routeData *TopicRouteData) decode(data string) error {
-	res := gjson.Parse(data)
-	err := jsoniter.Unmarshal([]byte(res.Get("queueDatas").String()), &routeData.QueueDataList)
-
-	if err != nil {
-		return err
-	}
-
-	bds := res.Get("brokerDatas").Array()
-	routeData.BrokerDataList = make([]*BrokerData, len(bds))
-	for idx, v := range bds {
-		bd := &BrokerData{
-			BrokerName:      v.Get("brokerName").String(),
-			Cluster:         v.Get("cluster").String(),
-			BrokerAddresses: make(map[int64]string, 0),
-		}
-		addrs := v.Get("brokerAddrs").String()
-		strs := strings.Split(addrs[1:len(addrs)-1], ",")
-		if strs != nil {
-			for _, str := range strs {
-				i := strings.Index(str, ":")
-				if i < 0 {
-					continue
-				}
-				id, _ := strconv.ParseInt(str[0:i], 10, 64)
-				bd.BrokerAddresses[id] = strings.Replace(str[i+1:], "\"", "", -1)
-			}
-		}
-		routeData.BrokerDataList[idx] = bd
-	}
-	return nil
-}
-
-func (routeData *TopicRouteData) clone() *TopicRouteData {
-	cloned := &TopicRouteData{
-		OrderTopicConf: routeData.OrderTopicConf,
-		QueueDataList:  make([]*QueueData, len(routeData.QueueDataList)),
-		BrokerDataList: make([]*BrokerData, len(routeData.BrokerDataList)),
-	}
-
-	for index, value := range routeData.QueueDataList {
-		cloned.QueueDataList[index] = value
-	}
-
-	for index, value := range routeData.BrokerDataList {
-		cloned.BrokerDataList[index] = value
-	}
-
-	return cloned
-}
-
-func (routeData *TopicRouteData) equals(data *TopicRouteData) bool {
-	if len(routeData.BrokerDataList) != len(data.BrokerDataList) {
-		return false
-	}
-	if len(routeData.QueueDataList) != len(data.QueueDataList) {
-		return false
-	}
-
-	for idx := range routeData.BrokerDataList {
-		if !routeData.BrokerDataList[idx].Equals(data.BrokerDataList[idx]) {
-			return false
-		}
-	}
-
-	for idx := range routeData.QueueDataList {
-		if !routeData.QueueDataList[idx].Equals(data.QueueDataList[idx]) {
-			return false
-		}
-	}
-	return true
-}
-
-func (routeData *TopicRouteData) String() string {
-	data, _ := jsoniter.Marshal(routeData)
-	return string(data)
-}
-
-// QueueData QueueData
-type QueueData struct {
-	BrokerName     string `json:"brokerName"`
-	ReadQueueNums  int    `json:"readQueueNums"`
-	WriteQueueNums int    `json:"writeQueueNums"`
-	Perm           int    `json:"perm"`
-	TopicSynFlag   int    `json:"topicSynFlag"`
-}
-
-func (q *QueueData) Equals(qd *QueueData) bool {
-	if q.BrokerName != qd.BrokerName {
-		return false
-	}
-
-	if q.ReadQueueNums != qd.ReadQueueNums {
-		return false
-	}
-
-	if q.WriteQueueNums != qd.WriteQueueNums {
-		return false
-	}
-
-	if q.Perm != qd.Perm {
-		return false
-	}
-
-	if q.TopicSynFlag != qd.TopicSynFlag {
-		return false
-	}
-
-	return true
-}
-
-// BrokerData BrokerData
-type BrokerData struct {
-	Cluster             string           `json:"cluster"`
-	BrokerName          string           `json:"brokerName"`
-	BrokerAddresses     map[int64]string `json:"brokerAddrs"`
-	brokerAddressesLock sync.RWMutex
-}
-
-func (b *BrokerData) Equals(bd *BrokerData) bool {
-	if b.Cluster != bd.Cluster {
-		return false
-	}
-
-	if b.BrokerName != bd.BrokerName {
-		return false
-	}
-
-	if len(b.BrokerAddresses) != len(bd.BrokerAddresses) {
-		return false
-	}
-
-	for k, v := range b.BrokerAddresses {
-		if bd.BrokerAddresses[k] != v {
-			return false
-		}
-	}
-
-	return true
-}
diff --git a/internal/route_test.go b/internal/route_test.go
deleted file mode 100644
index a1ebec4..0000000
--- a/internal/route_test.go
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"sync"
-	"testing"
-
-	"github.com/golang/mock/gomock"
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/stretchr/testify/assert"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func TestQueryTopicRouteInfoFromServer(t *testing.T) {
-	Convey("marshal of TraceContext", t, func() {
-
-		ctrl := gomock.NewController(t)
-		defer ctrl.Finish()
-
-		remotingCli := remote.NewMockRemotingClient(ctrl)
-
-		addr, err := primitive.NewNamesrvAddr("1.1.1.1:8880", "1.1.1.2:8880", "1.1.1.3:8880")
-		assert.Nil(t, err)
-
-		namesrv, err := NewNamesrv(primitive.NewPassthroughResolver(addr))
-		assert.Nil(t, err)
-		namesrv.nameSrvClient = remotingCli
-
-		Convey("When marshal producer trace data", func() {
-
-			count := 0
-			remotingCli.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
-				func(ctx context.Context, addr string, request *remote.RemotingCommand) (*remote.RemotingCommand, error) {
-					count++
-					if count < 3 {
-						return nil, errors.ErrNotExisted
-					}
-					return &remote.RemotingCommand{
-						Code: ResTopicNotExist,
-					}, nil
-				}).Times(3)
-
-			data, err := namesrv.queryTopicRouteInfoFromServer("notexisted")
-			assert.Nil(t, data)
-			assert.Equal(t, errors.ErrTopicNotExist, err)
-		})
-	})
-}
-
-func TestAddBrokerVersion(t *testing.T) {
-	s := &namesrvs{}
-	s.brokerVersionMap = make(map[string]map[string]int32, 0)
-	s.brokerLock = new(sync.RWMutex)
-
-	v := s.findBrokerVersion("b1", "addr1")
-	assert.Equal(t, v, int32(0))
-
-	s.AddBrokerVersion("b1", "addr1", 1)
-	v = s.findBrokerVersion("b1", "addr1")
-	assert.Equal(t, v, int32(1))
-
-	v = s.findBrokerVersion("b1", "addr2")
-	assert.Equal(t, v, int32(0))
-}
-
-func TestFindBrokerAddressInSubscribe(t *testing.T) {
-	s := &namesrvs{}
-	s.brokerVersionMap = make(map[string]map[string]int32, 0)
-	s.brokerLock = new(sync.RWMutex)
-
-	brokerDataRaft1 := &BrokerData{
-		Cluster:    "cluster",
-		BrokerName: "raft01",
-		BrokerAddresses: map[int64]string{
-			0: "127.0.0.1:10911",
-			1: "127.0.0.1:10912",
-			2: "127.0.0.1:10913",
-		},
-	}
-	s.brokerAddressesMap.Store(brokerDataRaft1.BrokerName, brokerDataRaft1)
-	brokerDataRaft2 := &BrokerData{
-		Cluster:    "cluster",
-		BrokerName: "raft02",
-		BrokerAddresses: map[int64]string{
-			0: "127.0.0.1:10911",
-			2: "127.0.0.1:10912",
-			3: "127.0.0.1:10913",
-		},
-	}
-	s.brokerAddressesMap.Store(brokerDataRaft2.BrokerName, brokerDataRaft2)
-
-	Convey("Request master broker", t, func() {
-		result := s.FindBrokerAddressInSubscribe(brokerDataRaft1.BrokerName, 0, false)
-		assert.NotNil(t, result)
-		assert.Equal(t, result.BrokerAddr, brokerDataRaft1.BrokerAddresses[0])
-		assert.Equal(t, result.Slave, false)
-	})
-
-	Convey("Request slave broker from normal broker group", t, func() {
-		result := s.FindBrokerAddressInSubscribe(brokerDataRaft1.BrokerName, 1, false)
-		assert.NotNil(t, result)
-		assert.Equal(t, result.BrokerAddr, brokerDataRaft1.BrokerAddresses[1])
-		assert.Equal(t, result.Slave, true)
-	})
-
-	Convey("Request slave broker from non normal broker group", t, func() {
-		result := s.FindBrokerAddressInSubscribe(brokerDataRaft2.BrokerName, 1, false)
-		assert.NotNil(t, result)
-		assert.Equal(t, result.BrokerAddr, brokerDataRaft2.BrokerAddresses[2])
-		assert.Equal(t, result.Slave, true)
-	})
-
-	Convey("Request not exist broker", t, func() {
-		result := s.FindBrokerAddressInSubscribe(brokerDataRaft1.BrokerName, 4, false)
-		assert.NotNil(t, result)
-	})
-}
diff --git a/internal/trace.go b/internal/trace.go
deleted file mode 100644
index 753a4d1..0000000
--- a/internal/trace.go
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	"runtime"
-	"strconv"
-	"strings"
-	"sync/atomic"
-	"time"
-
-	"github.com/pkg/errors"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type TraceBean struct {
-	Topic       string
-	MsgId       string
-	OffsetMsgId string
-	Tags        string
-	Keys        string
-	StoreHost   string
-	ClientHost  string
-	StoreTime   int64
-	RetryTimes  int
-	BodyLength  int
-	MsgType     primitive.MessageType
-}
-
-type TraceTransferBean struct {
-	transData string
-	// not duplicate
-	transKey []string
-}
-
-type TraceType string
-
-const (
-	Pub       TraceType = "Pub"
-	SubBefore TraceType = "SubBefore"
-	SubAfter  TraceType = "SubAfter"
-
-	contentSplitter = '\001'
-	fieldSplitter   = '\002'
-)
-
-type TraceContext struct {
-	TraceType   TraceType
-	TimeStamp   int64
-	RegionId    string
-	RegionName  string
-	GroupName   string
-	CostTime    int64
-	IsSuccess   bool
-	RequestId   string
-	ContextCode int
-	TraceBeans  []TraceBean
-}
-
-func (ctx *TraceContext) marshal2Bean() *TraceTransferBean {
-	buffer := bytes.NewBufferString("")
-	switch ctx.TraceType {
-	case Pub:
-		bean := ctx.TraceBeans[0]
-		buffer.WriteString(string(ctx.TraceType))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(strconv.FormatInt(ctx.TimeStamp, 10))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(ctx.RegionId)
-		buffer.WriteRune(contentSplitter)
-		ss := strings.Split(ctx.GroupName, "%")
-		if len(ss) == 2 {
-			buffer.WriteString(ss[1])
-		} else {
-			buffer.WriteString(ctx.GroupName)
-		}
-
-		buffer.WriteRune(contentSplitter)
-		ssTopic := strings.Split(bean.Topic, "%")
-		if len(ssTopic) == 2 {
-			buffer.WriteString(ssTopic[1])
-		} else {
-			buffer.WriteString(bean.Topic)
-		}
-		//buffer.WriteString(bean.Topic)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.MsgId)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.Tags)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.Keys)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.StoreHost)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(strconv.Itoa(bean.BodyLength))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(strconv.FormatInt(ctx.CostTime, 10))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(strconv.Itoa(int(bean.MsgType)))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.OffsetMsgId)
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(strconv.FormatBool(ctx.IsSuccess))
-		buffer.WriteRune(contentSplitter)
-		buffer.WriteString(bean.ClientHost)
-		buffer.WriteRune(fieldSplitter)
-	case SubBefore:
-		for _, bean := range ctx.TraceBeans {
-			buffer.WriteString(string(ctx.TraceType))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.FormatInt(ctx.TimeStamp, 10))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(ctx.RegionId)
-			buffer.WriteRune(contentSplitter)
-			ss := strings.Split(ctx.GroupName, "%")
-			if len(ss) == 2 {
-				buffer.WriteString(ss[1])
-			} else {
-				buffer.WriteString(ctx.GroupName)
-			}
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(ctx.RequestId)
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(bean.MsgId)
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.Itoa(bean.RetryTimes))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(nullWrap(bean.Keys))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(bean.ClientHost)
-			buffer.WriteRune(fieldSplitter)
-		}
-	case SubAfter:
-		for _, bean := range ctx.TraceBeans {
-			buffer.WriteString(string(ctx.TraceType))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(ctx.RequestId)
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(bean.MsgId)
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.FormatInt(ctx.CostTime, 10))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.FormatBool(ctx.IsSuccess))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(nullWrap(bean.Keys))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.Itoa(ctx.ContextCode))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(strconv.FormatInt(ctx.TimeStamp, 10))
-			buffer.WriteRune(contentSplitter)
-			buffer.WriteString(ctx.GroupName)
-			buffer.WriteRune(fieldSplitter)
-		}
-	}
-	transferBean := new(TraceTransferBean)
-	transferBean.transData = buffer.String()
-	for _, bean := range ctx.TraceBeans {
-		transferBean.transKey = append(transferBean.transKey, bean.MsgId)
-		if len(bean.Keys) > 0 {
-			transferBean.transKey = append(transferBean.transKey, bean.Keys)
-		}
-	}
-	return transferBean
-}
-
-// compatible with java console.
-func nullWrap(s string) string {
-	if len(s) == 0 {
-		return "null"
-	}
-	return s
-}
-
-type traceDispatcherType int
-
-const (
-	RmqSysTraceTopic = "RMQ_SYS_TRACE_TOPIC"
-
-	ProducerType traceDispatcherType = iota
-	ConsumerType
-
-	maxMsgSize = 128000 - 10*1000
-	batchSize  = 100
-
-	TraceTopicPrefix = SystemTopicPrefix + "TRACE_DATA_"
-	TraceGroupName   = "_INNER_TRACE_PRODUCER"
-)
-
-type TraceDispatcher interface {
-	GetTraceTopicName() string
-
-	Start()
-	Append(ctx TraceContext) bool
-	Close()
-}
-
-type traceDispatcher struct {
-	ctx     context.Context
-	cancel  context.CancelFunc
-	running bool
-
-	traceTopic string
-	access     primitive.AccessChannel
-
-	ticker  *time.Ticker
-	input   chan TraceContext
-	batchCh chan []*TraceContext
-
-	discardCount int64
-
-	// support deliver trace message to other cluster.
-	namesrvs *namesrvs
-	// round robin index
-	rrindex int32
-	cli     RMQClient
-}
-
-func NewTraceDispatcher(traceCfg *primitive.TraceConfig) *traceDispatcher {
-	ctx := context.Background()
-	ctx, cancel := context.WithCancel(ctx)
-
-	t := traceCfg.TraceTopic
-	if len(t) == 0 {
-		t = RmqSysTraceTopic
-	}
-
-	if traceCfg.Access == primitive.Cloud {
-		t = TraceTopicPrefix + traceCfg.TraceTopic
-	}
-
-	if len(traceCfg.NamesrvAddrs) == 0 && traceCfg.Resolver == nil {
-		panic("no NamesrvAddrs or Resolver configured")
-	}
-
-	var srvs *namesrvs
-	var err error
-	if len(traceCfg.NamesrvAddrs) > 0 {
-		srvs, err = NewNamesrv(primitive.NewPassthroughResolver(traceCfg.NamesrvAddrs))
-	} else {
-		srvs, err = NewNamesrv(traceCfg.Resolver)
-	}
-
-	if err != nil {
-		panic(errors.Wrap(err, "new Namesrv failed."))
-	}
-	if !traceCfg.Credentials.IsEmpty() {
-		srvs.SetCredentials(traceCfg.Credentials)
-	}
-
-	cliOp := DefaultClientOptions()
-	cliOp.GroupName = traceCfg.GroupName
-	cliOp.NameServerAddrs = traceCfg.NamesrvAddrs
-	cliOp.InstanceName = "INNER_TRACE_CLIENT_DEFAULT"
-	cliOp.RetryTimes = 0
-	cliOp.Namesrv = srvs
-	cliOp.Credentials = traceCfg.Credentials
-	cli := GetOrNewRocketMQClient(cliOp, nil)
-	if cli == nil {
-		return nil
-	}
-	cliOp.Namesrv = cli.GetNameSrv()
-	return &traceDispatcher{
-		ctx:    ctx,
-		cancel: cancel,
-
-		traceTopic: t,
-		access:     traceCfg.Access,
-		input:      make(chan TraceContext, 1024),
-		batchCh:    make(chan []*TraceContext, 2048),
-		cli:        cli,
-		namesrvs:   srvs,
-	}
-}
-
-func (td *traceDispatcher) GetTraceTopicName() string {
-	return td.traceTopic
-}
-
-func (td *traceDispatcher) Start() {
-	td.running = true
-	td.cli.Start()
-	go primitive.WithRecover(func() {
-		td.process()
-	})
-}
-
-func (td *traceDispatcher) Close() {
-	td.running = false
-	td.ticker.Stop()
-	td.cancel()
-}
-
-func (td *traceDispatcher) Append(ctx TraceContext) bool {
-	if !td.running {
-		rlog.Error("traceDispatcher is closed.", nil)
-		return false
-	}
-	select {
-	case td.input <- ctx:
-		return true
-	default:
-		rlog.Warning("buffer full", map[string]interface{}{
-			"discardCount": atomic.AddInt64(&td.discardCount, 1),
-			"TraceContext": ctx,
-		})
-		return false
-	}
-}
-
-// process
-func (td *traceDispatcher) process() {
-	var count int
-	var batch []TraceContext
-	maxWaitDuration := 5 * time.Millisecond
-	maxWaitTime := maxWaitDuration.Nanoseconds()
-	td.ticker = time.NewTicker(maxWaitDuration)
-	lastput := time.Now()
-	for {
-		select {
-		case ctx := <-td.input:
-			count++
-			lastput = time.Now()
-			batch = append(batch, ctx)
-			if count == batchSize {
-				count = 0
-				batchSend := batch
-				go primitive.WithRecover(func() {
-					td.batchCommit(batchSend)
-				})
-				batch = make([]TraceContext, 0)
-			}
-		case <-td.ticker.C:
-			delta := time.Since(lastput).Nanoseconds()
-			if delta > maxWaitTime {
-				count++
-				lastput = time.Now()
-				if len(batch) > 0 {
-					batchSend := batch
-					go primitive.WithRecover(func() {
-						td.batchCommit(batchSend)
-					})
-					batch = make([]TraceContext, 0)
-				}
-			}
-		case <-td.ctx.Done():
-			batchSend := batch
-			go primitive.WithRecover(func() {
-				td.batchCommit(batchSend)
-			})
-			batch = make([]TraceContext, 0)
-
-			now := time.Now().UnixNano() / int64(time.Millisecond)
-			end := now + 500
-			for now < end {
-				now = time.Now().UnixNano() / int64(time.Millisecond)
-				runtime.Gosched()
-			}
-			rlog.Info(fmt.Sprintf("------end trace send %v %v", td.input, td.batchCh), nil)
-		}
-	}
-}
-
-// batchCommit commit slice of TraceContext. convert the ctxs to keyed pair(key is Topic + regionid).
-// flush according key one by one.
-func (td *traceDispatcher) batchCommit(ctxs []TraceContext) {
-	keyedCtxs := make(map[string][]TraceTransferBean)
-	for _, ctx := range ctxs {
-		if len(ctx.TraceBeans) == 0 {
-			return
-		}
-		topic := ctx.TraceBeans[0].Topic
-		regionID := ctx.RegionId
-		key := topic
-		if len(regionID) > 0 {
-			key = fmt.Sprintf("%s%c%s", topic, contentSplitter, regionID)
-		}
-		keyedCtxs[key] = append(keyedCtxs[key], *ctx.marshal2Bean())
-	}
-
-	for k, v := range keyedCtxs {
-		arr := strings.Split(k, string([]byte{contentSplitter}))
-		topic := k
-		regionID := ""
-		if len(arr) > 1 {
-			topic = arr[0]
-			regionID = arr[1]
-		}
-		td.flush(topic, regionID, v)
-	}
-}
-
-type Keyset map[string]struct{}
-
-func (ks Keyset) slice() []string {
-	slice := make([]string, len(ks))
-	for k, _ := range ks {
-		slice = append(slice, k)
-	}
-	return slice
-}
-
-// flush data in batch.
-func (td *traceDispatcher) flush(topic, regionID string, data []TraceTransferBean) {
-	if len(data) == 0 {
-		return
-	}
-
-	keyset := make(Keyset)
-	var builder strings.Builder
-	flushed := true
-	for _, bean := range data {
-		for _, k := range bean.transKey {
-			keyset[k] = struct{}{}
-		}
-		builder.WriteString(bean.transData)
-		flushed = false
-
-		if builder.Len() > maxMsgSize {
-			td.sendTraceDataByMQ(keyset, regionID, builder.String())
-			builder.Reset()
-			keyset = make(Keyset)
-			flushed = true
-		}
-	}
-	if !flushed {
-		td.sendTraceDataByMQ(keyset, regionID, builder.String())
-	}
-}
-
-func (td *traceDispatcher) sendTraceDataByMQ(keySet Keyset, regionID string, data string) {
-	traceTopic := td.traceTopic
-	if td.access == primitive.Cloud {
-		traceTopic = td.traceTopic + regionID
-	}
-	msg := primitive.NewMessage(traceTopic, []byte(data))
-	msg.WithKeys(keySet.slice())
-
-	mq, addr := td.findMq(regionID)
-	if mq == nil {
-		return
-	}
-
-	var req = td.buildSendRequest(mq, msg)
-	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-	defer cancel()
-	err := td.cli.InvokeAsync(ctx, addr, req, func(command *remote.RemotingCommand, e error) {
-		resp := primitive.NewSendResult()
-		if e != nil {
-			rlog.Info("send trace data error.", map[string]interface{}{
-				"traceData": data,
-			})
-		} else {
-			td.cli.ProcessSendResponse(mq.BrokerName, command, resp, msg)
-			rlog.Debug("send trace data success:", map[string]interface{}{
-				"SendResult": resp,
-				"traceData":  data,
-			})
-		}
-	})
-	if err != nil {
-		rlog.Info("send trace data error when invoke", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-	}
-}
-
-func (td *traceDispatcher) findMq(regionID string) (*primitive.MessageQueue, string) {
-	traceTopic := td.traceTopic
-	if td.access == primitive.Cloud {
-		traceTopic = td.traceTopic + regionID
-	}
-	mqs, err := td.namesrvs.FetchPublishMessageQueues(traceTopic)
-	if err != nil {
-		rlog.Error("fetch publish message queues failed", map[string]interface{}{
-			rlog.LogKeyUnderlayError: err,
-		})
-		return nil, ""
-	}
-	i := atomic.AddInt32(&td.rrindex, 1)
-	if i < 0 {
-		i = 0
-		atomic.StoreInt32(&td.rrindex, 0)
-	}
-	i %= int32(len(mqs))
-	mq := mqs[i]
-
-	brokerName := mq.BrokerName
-	addr := td.namesrvs.FindBrokerAddrByName(brokerName)
-
-	return mq, addr
-}
-
-func (td *traceDispatcher) buildSendRequest(mq *primitive.MessageQueue,
-	msg *primitive.Message) *remote.RemotingCommand {
-	req := &SendMessageRequestHeader{
-		ProducerGroup: TraceGroupName,
-		Topic:         mq.Topic,
-		QueueId:       mq.QueueId,
-		BornTimestamp: time.Now().UnixNano() / int64(time.Millisecond),
-		Flag:          msg.Flag,
-		Properties:    msg.MarshallProperties(),
-	}
-
-	return remote.NewRemotingCommand(ReqSendMessage, req, msg.Body)
-}
diff --git a/internal/trace_test.go b/internal/trace_test.go
deleted file mode 100644
index a636b38..0000000
--- a/internal/trace_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"testing"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestMarshal2Bean(t *testing.T) {
-
-	Convey("marshal of TraceContext", t, func() {
-
-		Convey("When marshal producer trace data", func() {
-			traceCtx := TraceContext{
-				TraceType: Pub,
-				TimeStamp: 1563780533299,
-				RegionId:  "DefaultRegion",
-				GroupName: "ProducerGroupName",
-				CostTime:  3572,
-				IsSuccess: true,
-				RequestId: "0A5DE93A815518B4AAC26F77F8330001",
-				TraceBeans: []TraceBean{
-					{
-						Topic:       "TopicTest",
-						MsgId:       "0A5DE93A833B18B4AAC26F842A2F0000",
-						OffsetMsgId: "0A5DE93A00002A9F000000000042E322",
-						Tags:        "TagA",
-						Keys:        "OrderID1882",
-						StoreHost:   "10.93.233.58:10911",
-						ClientHost:  "10.93.233.58",
-						StoreTime:   1563780535085,
-						BodyLength:  11,
-						MsgType:     primitive.NormalMsg,
-					},
-				},
-			}
-			bean := traceCtx.marshal2Bean()
-			assert.Equal(t, "Pub1563780533299DefaultRegionProducerGroupNameTopicTest0A5DE93A833B18B4AAC26F842A2F0000TagAOrderID188210.93.233.58:1091111357200A5DE93A00002A9F000000000042E322true10.93.233.58\x02",
-				bean.transData)
-			assert.Equal(t, []string{"0A5DE93A833B18B4AAC26F842A2F0000", "OrderID1882"}, bean.transKey)
-
-			// consumer before test
-			traceCtx = TraceContext{
-				TraceType: SubBefore,
-				TimeStamp: 1563789119096,
-				GroupName: "CID_JODIE_1",
-				IsSuccess: true,
-				RequestId: "0A5DE93A96A818B4AAC26FFAFA780007",
-				TraceBeans: []TraceBean{
-					{
-						Topic:      "TopicTest",
-						MsgId:      "0A5DE93A973418B4AAC26FFAFA5A0000",
-						Tags:       "TagA",
-						Keys:       "OrderID1882",
-						StoreHost:  "10.93.233.58",
-						ClientHost: "10.93.233.58",
-						StoreTime:  1563789119092,
-						BodyLength: 190,
-					},
-				},
-			}
-			bean = traceCtx.marshal2Bean()
-
-			Convey("transData should equal to expected", func() {
-				So(bean.transData, ShouldEqual, "SubBefore1563789119096CID_JODIE_10A5DE93A96A818B4AAC26FFAFA7800070A5DE93A973418B4AAC26FFAFA5A00000OrderID188210.93.233.58")
-			})
-
-			Convey("transkey should equal to expected", func() {
-				expectedKey := []string{"0A5DE93A973418B4AAC26FFAFA5A0000", "OrderID1882"}
-				So(bean.transKey[0], ShouldEqual, expectedKey[0])
-				So(bean.transKey[1], ShouldEqual, expectedKey[1])
-			})
-		})
-
-		Convey("When marshal consumer trace data", func() {
-			traceCtx := TraceContext{
-				TraceType: SubAfter,
-				TimeStamp: 1563789119096,
-				GroupName: "CID_JODIE_1",
-				IsSuccess: true,
-				RequestId: "0A5DE93A96A818B4AAC26FFAFA780007",
-				TraceBeans: []TraceBean{
-					{
-						Topic:      "TopicTest",
-						MsgId:      "0A5DE93A973418B4AAC26FFAFA5A0000",
-						Tags:       "TagA",
-						Keys:       "OrderID1882",
-						StoreHost:  "10.93.233.58",
-						ClientHost: "10.93.233.58",
-						StoreTime:  1563789119092,
-						BodyLength: 190,
-					},
-				},
-			}
-			bean := traceCtx.marshal2Bean()
-			Convey("transData should equal to expected", func() {
-				So(bean.transData, ShouldEqual, "SubAfter0A5DE93A96A818B4AAC26FFAFA7800070A5DE93A973418B4AAC26FFAFA5A00000trueOrderID188201563789119096CID_JODIE_1")
-			})
-			Convey("transkey should equal to expected", func() {
-				expectedKey := []string{"0A5DE93A973418B4AAC26FFAFA5A0000", "OrderID1882"}
-				So(bean.transKey[0], ShouldEqual, expectedKey[0])
-				So(bean.transKey[1], ShouldEqual, expectedKey[1])
-			})
-		})
-	})
-}
diff --git a/internal/transaction.go b/internal/transaction.go
deleted file mode 100644
index 5cd9835..0000000
--- a/internal/transaction.go
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-type TransactionListener interface {
-}
diff --git a/internal/utils/compression.go b/internal/utils/compression.go
deleted file mode 100644
index 162864f..0000000
--- a/internal/utils/compression.go
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"bytes"
-	"compress/zlib"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"io/ioutil"
-	"sync"
-)
-
-var zlibWriterPools []sync.Pool
-
-var bufPool = sync.Pool{
-	New: func() interface{} {
-		return &bytes.Buffer{}
-	},
-}
-
-func init() {
-	zlibWriterPools = make([]sync.Pool, zlib.BestCompression)
-	for i := 0; i < zlib.BestCompression; i++ {
-		compressLevel := i
-		zlibWriterPools[i] = sync.Pool{
-			New: func() interface{} {
-				z, _ := zlib.NewWriterLevel(nil, compressLevel+1)
-				return z
-			},
-		}
-	}
-}
-
-func Compress(raw []byte, compressLevel int) ([]byte, error) {
-	if compressLevel < zlib.BestSpeed || compressLevel > zlib.BestCompression {
-		return nil, errors.ErrCompressLevel
-	}
-
-	buf := bufPool.Get().(*bytes.Buffer)
-	defer bufPool.Put(buf)
-	writerPool := &zlibWriterPools[compressLevel-1]
-	writer := writerPool.Get().(*zlib.Writer)
-	defer writerPool.Put(writer)
-	buf.Reset()
-	writer.Reset(buf)
-	_, e := writer.Write(raw)
-	if e != nil {
-		return nil, e
-	}
-
-	e = writer.Close()
-	if e != nil {
-		return nil, e
-	}
-	result := make([]byte, buf.Len())
-	buf.Read(result)
-	return result, nil
-}
-
-func UnCompress(data []byte) []byte {
-	rdata := bytes.NewReader(data)
-	r, err := zlib.NewReader(rdata)
-	if err != nil {
-		return data
-	}
-	retData, err := ioutil.ReadAll(r)
-	if err != nil {
-		return data
-	}
-	return retData
-}
diff --git a/internal/utils/compression_test.go b/internal/utils/compression_test.go
deleted file mode 100644
index 4d10893..0000000
--- a/internal/utils/compression_test.go
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"bytes"
-	"compress/zlib"
-	"encoding/json"
-	"fmt"
-	"math/rand"
-	"testing"
-)
-
-func TestUnCompress(t *testing.T) {
-	var b bytes.Buffer
-	var oriStr string = "hello, go"
-	zr := zlib.NewWriter(&b)
-	zr.Write([]byte(oriStr))
-	zr.Close()
-
-	retBytes := UnCompress(b.Bytes())
-	if string(retBytes) != oriStr {
-		t.Errorf("UnCompress was incorrect, got %s, want: %s .", retBytes, []byte(oriStr))
-	}
-}
-
-func TestCompress(t *testing.T) {
-	raw := []byte("The quick brown fox jumps over the lazy dog")
-	for i := zlib.BestSpeed; i <= zlib.BestCompression; i++ {
-		compressed, e := Compress(raw, i)
-		if e != nil {
-			t.Errorf("Compress data:%s returns error: %v", string(raw), e)
-			return
-		}
-		decompressed := UnCompress(compressed)
-		if string(decompressed) != string(raw) {
-			t.Errorf("data is corrupt, got: %s, want: %s", string(decompressed), string(raw))
-		}
-	}
-}
-
-func testCase(data []byte, level int, t *testing.T) {
-	compressed, e := Compress(data, level)
-	if e != nil {
-		t.Errorf("Compress data:%v returns error: %v", data, e)
-	}
-	decompressed := UnCompress(compressed)
-	if string(data) != string(decompressed) {
-		t.Errorf("data is corrupt, got: %s, want: %s", string(decompressed), string(data))
-	}
-}
-
-func generateRandTestData(n int) []byte {
-	data := make([]byte, n)
-	rand.Read(data)
-	return data
-}
-
-func generateJsonString(n int) []byte {
-	x := make(map[string]string)
-	for i := 0; i < n; i++ {
-		k := fmt.Sprintf("compression_key_%d", i)
-		v := fmt.Sprintf("compression_value_%d", i)
-		x[k] = v
-	}
-	data, _ := json.Marshal(x)
-	return data
-}
-
-func TestCompressThreadSafe(t *testing.T) {
-	for i := 0; i < 100; i++ {
-		data := generateRandTestData(i * 100)
-		level := i%zlib.BestCompression + 1
-		go testCase(data, level, t)
-	}
-
-	for i := 0; i < 100; i++ {
-		data := generateJsonString(i * 100)
-		level := i%zlib.BestCompression + 1
-		go testCase(data, level, t)
-	}
-}
diff --git a/internal/utils/errors.go b/internal/utils/errors.go
deleted file mode 100644
index 0887a37..0000000
--- a/internal/utils/errors.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-func CheckError(action string, err error) {
-	if err != nil {
-		rlog.Error(action, map[string]interface{}{
-			rlog.LogKeyUnderlayError: err.Error(),
-		})
-	}
-}
diff --git a/internal/utils/files.go b/internal/utils/files.go
deleted file mode 100644
index 2583d11..0000000
--- a/internal/utils/files.go
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"errors"
-	"fmt"
-	"os"
-	"path/filepath"
-)
-
-func FileReadAll(path string) ([]byte, error) {
-	stat, err := os.Stat(path)
-	if err != nil {
-		return nil, err
-	}
-	file, err := os.Open(path)
-	if err != nil {
-		return nil, err
-	}
-	data := make([]byte, stat.Size())
-	_, err = file.Read(data)
-	if err != nil {
-		return nil, err
-	}
-	return data, nil
-}
-
-func ensureDir(path string) error {
-	info, err := os.Stat(path)
-	if err != nil {
-		if os.IsNotExist(err) {
-			err = os.MkdirAll(path, 0755)
-		}
-		return err
-	}
-	if !info.IsDir() {
-		return errors.New(path + " is a file")
-	}
-	return nil
-}
-
-func WriteToFile(path string, data []byte) error {
-	if err := ensureDir(filepath.Dir(path)); err != nil {
-		return err
-	}
-	tmpFile, err := os.Create(path + ".tmp")
-	if err != nil {
-		return err
-	}
-	_, err = tmpFile.Write(data)
-	if err != nil {
-		return err
-	}
-	CheckError(fmt.Sprintf("close %s", tmpFile.Name()), tmpFile.Close())
-
-	prevContent, err := FileReadAll(path)
-	if err == nil {
-		bakFile, err := os.Create(path + ".bak")
-		if err != nil {
-			_, err = bakFile.Write(prevContent)
-		}
-		if err != nil {
-			return err
-		}
-		CheckError(fmt.Sprintf("close %s", bakFile.Name()), bakFile.Close())
-	}
-
-	_, err = os.Stat(path)
-	if err == nil {
-		CheckError(fmt.Sprintf("remove %s", path), os.Remove(path))
-	}
-	return os.Rename(path+".tmp", path)
-}
diff --git a/internal/utils/math.go b/internal/utils/math.go
deleted file mode 100644
index 816631e..0000000
--- a/internal/utils/math.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-func AbsInt(i int) int {
-	if i >= 0 {
-		return i
-	}
-	return -i
-}
-
-func MinInt(a, b int) int {
-	if a < b {
-		return a
-	}
-	return b
-}
diff --git a/internal/utils/net.go b/internal/utils/net.go
deleted file mode 100644
index a4eeb56..0000000
--- a/internal/utils/net.go
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"net"
-	"strconv"
-	"time"
-)
-
-var (
-	LocalIP string
-)
-
-func init() {
-	ip, err := ClientIP4()
-	if err != nil {
-		LocalIP = ""
-	} else {
-		LocalIP = fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
-	}
-}
-
-func ClientIP4() ([]byte, error) {
-	if ifaces, err := net.Interfaces(); err == nil && ifaces != nil {
-		for _, iface := range ifaces {
-			if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
-				continue
-			}
-			if addrs, err := iface.Addrs(); err == nil && addrs != nil {
-				for _, addr := range addrs {
-					if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
-						if ip4 := ipnet.IP.To4(); ip4 != nil {
-							return ip4, nil
-						}
-					}
-				}
-			}
-		}
-	}
-	return nil, errors.ErrUnknownIP
-}
-
-func FakeIP() []byte {
-	buf := bytes.NewBufferString("")
-	buf.WriteString(strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10))
-	return buf.Bytes()[4:8]
-}
-
-func GetAddressByBytes(data []byte) string {
-	return net.IPv4(data[0], data[1], data[2], data[3]).String()
-}
diff --git a/internal/utils/net_test.go b/internal/utils/net_test.go
deleted file mode 100644
index 3e65a75..0000000
--- a/internal/utils/net_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import "testing"
-
-func TestLocalIP2(t *testing.T) {
-	t.Log(LocalIP)
-}
diff --git a/internal/utils/set.go b/internal/utils/set.go
deleted file mode 100644
index e90fb36..0000000
--- a/internal/utils/set.go
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"bytes"
-	"encoding/json"
-	"sort"
-)
-
-type UniqueItem interface {
-	UniqueID() string
-}
-
-type StringUnique string
-
-func (str StringUnique) UniqueID() string {
-	return string(str)
-}
-
-type Set struct {
-	items map[string]UniqueItem
-}
-
-func NewSet() Set {
-	return Set{
-		items: make(map[string]UniqueItem, 0),
-	}
-}
-
-func (s *Set) Add(v UniqueItem) {
-	s.items[v.UniqueID()] = v
-}
-
-func (s *Set) AddKV(k, v string) {
-	s.items[k] = StringUnique(v)
-}
-
-func (s *Set) Contains(k string) (UniqueItem, bool) {
-	v, ok := s.items[k]
-	return v, ok
-}
-
-func (s *Set) Len() int {
-	return len(s.items)
-}
-
-var _ json.Marshaler = &Set{}
-
-func (s *Set) MarshalJSON() ([]byte, error) {
-	if len(s.items) == 0 {
-		return []byte("[]"), nil
-	}
-
-	buffer := new(bytes.Buffer)
-	buffer.WriteByte('[')
-	keys := make([]string, 0)
-	for _, k := range s.items {
-		var key string
-		switch kval := k.(type) {
-		case StringUnique:
-			key = "\"" + string(kval) + "\""
-		default:
-			v, err := json.Marshal(k)
-			if err != nil {
-				return nil, err
-			}
-			key = string(v)
-		}
-		keys = append(keys, key)
-	}
-	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
-
-	for i, key := range keys {
-		if i > 0 {
-			buffer.WriteByte(',')
-		}
-		buffer.WriteString(key)
-	}
-
-	buffer.WriteByte(']')
-
-	return buffer.Bytes(), nil
-}
-
-func (s Set) UnmarshalJSON(data []byte) (err error) {
-	return nil
-}
diff --git a/internal/utils/string.go b/internal/utils/string.go
deleted file mode 100644
index f347397..0000000
--- a/internal/utils/string.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-// HashString hashes a string to a unique hashcode.
-func HashString(s string) int {
-	val := []byte(s)
-	var h int32
-
-	for idx := range val {
-		h = 31*h + int32(val[idx])
-	}
-
-	return int(h)
-}
diff --git a/internal/validators.go b/internal/validators.go
deleted file mode 100644
index ac51db2..0000000
--- a/internal/validators.go
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package internal
-
-import (
-	"regexp"
-
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-const (
-	_ValidPattern       = "^[%|a-zA-Z0-9_-]+$"
-	_CharacterMaxLength = 255
-)
-
-var (
-	_Pattern, _ = regexp.Compile(_ValidPattern)
-)
-
-func ValidateGroup(group string) {
-	if group == "" {
-		rlog.Fatal("consumerGroup is empty", nil)
-	}
-
-	if len(group) > _CharacterMaxLength {
-		rlog.Fatal("the specified group is longer than group max length 255.", nil)
-	}
-}
diff --git a/primitive/auth.go b/primitive/auth.go
deleted file mode 100644
index 772bc4d..0000000
--- a/primitive/auth.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-type Credentials struct {
-	AccessKey     string
-	SecretKey     string
-	SecurityToken string
-}
-
-func (c Credentials) IsEmpty() bool {
-	return c.AccessKey == "" || c.SecretKey == ""
-}
diff --git a/primitive/base.go b/primitive/base.go
deleted file mode 100644
index a45fbb9..0000000
--- a/primitive/base.go
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"regexp"
-	"strings"
-)
-
-var (
-	ipv4Regex, _ = regexp.Compile(`^((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))`)
-	ipv6Regex, _ = regexp.Compile(`(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`)
-)
-
-type NamesrvAddr []string
-
-func NewNamesrvAddr(s ...string) (NamesrvAddr, error) {
-	if len(s) == 0 {
-		return nil, errors.ErrNoNameserver
-	}
-
-	ss := s
-	if len(ss) == 1 {
-		// compatible with multi server env string: "a;b;c"
-		ss = strings.Split(s[0], ";")
-	}
-
-	for _, srv := range ss {
-		if err := verifyIP(srv); err != nil {
-			return nil, err
-		}
-	}
-
-	addrs := make(NamesrvAddr, 0)
-	addrs = append(addrs, ss...)
-	return addrs, nil
-}
-
-func (addr NamesrvAddr) Check() error {
-	for _, srv := range addr {
-		if err := verifyIP(srv); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-var (
-	httpPrefixRegex, _ = regexp.Compile("^(http|https)://")
-)
-
-func verifyIP(ip string) error {
-	if httpPrefixRegex.MatchString(ip) {
-		return nil
-	}
-	if strings.Contains(ip, ";") {
-		return errors.ErrMultiIP
-	}
-	ipV4s := ipv4Regex.FindAllString(ip, -1)
-	ipV6s := ipv6Regex.FindAllString(ip, -1)
-
-	if len(ipV4s) == 0 && len(ipV6s) == 0 {
-		return errors.ErrIllegalIP
-	}
-
-	if len(ipV4s) > 1 || len(ipV6s) > 1 {
-		return errors.ErrMultiIP
-	}
-	return nil
-}
-
-var PanicHandler func(interface{})
-
-func WithRecover(fn func()) {
-	defer func() {
-		handler := PanicHandler
-		if handler != nil {
-			if err := recover(); err != nil {
-				handler(err)
-			}
-		}
-	}()
-
-	fn()
-}
-
-func Diff(origin, latest []string) bool {
-	if len(origin) != len(latest) {
-		return true
-	}
-
-	// check added
-	originFilter := make(map[string]struct{}, len(origin))
-	for _, srv := range origin {
-		originFilter[srv] = struct{}{}
-	}
-
-	latestFilter := make(map[string]struct{}, len(latest))
-	for _, srv := range latest {
-		if _, ok := originFilter[srv]; !ok {
-			return true // added
-		}
-		latestFilter[srv] = struct{}{}
-	}
-
-	// check delete
-	for _, srv := range origin {
-		if _, ok := latestFilter[srv]; !ok {
-			return true // deleted
-		}
-	}
-	return false
-}
diff --git a/primitive/base_test.go b/primitive/base_test.go
deleted file mode 100644
index db947c4..0000000
--- a/primitive/base_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestVerifyIP(t *testing.T) {
-	IPs := "127.0.0.1:9876"
-	err := verifyIP(IPs)
-	assert.Nil(t, err)
-
-	IPs = "12.24.123.243:10911"
-	err = verifyIP(IPs)
-	assert.Nil(t, err)
-
-	IPs = "xa2.0.0.1:9876"
-	err = verifyIP(IPs)
-	assert.Equal(t, "IP addr error", err.Error())
-
-	IPs = "333.0.0.1:9876"
-	err = verifyIP(IPs)
-	assert.Equal(t, "IP addr error", err.Error())
-
-	IPs = "127.0.0.1:9876;12.24.123.243:10911"
-	err = verifyIP(IPs)
-	assert.Equal(t, "multiple IP addr does not support", err.Error())
-
-	IPs = "bdbd:bdbd:ff:1:1:2:3:4:8888"
-	err = verifyIP(IPs)
-	assert.Nil(t, err)
-
-	IPs = "[bdbd:bdbd:ff:1:1:2:3:4]:8888"
-	err = verifyIP(IPs)
-	assert.Nil(t, err)
-
-	IPs = "[bdbd:bdbd:ff:1:1:2:3:4]:8888;[bdbd:bdbd:ff:1:1:2:3:4]:8889"
-	err = verifyIP(IPs)
-	assert.Equal(t, "multiple IP addr does not support", err.Error())
-}
-
-func TestBase(t *testing.T) {
-	a := []string{}
-	b := []string{}
-	assert.False(t, Diff(a, b))
-
-	a = []string{"a"}
-	b = []string{"a", "b"}
-	assert.True(t, Diff(a, b))
-
-	a = []string{"a", "b", "c"}
-	b = []string{"c", "a", "b"}
-	assert.False(t, Diff(a, b))
-
-	a = []string{"b", "a"}
-	b = []string{"a", "c"}
-	assert.True(t, Diff(a, b))
-}
diff --git a/primitive/ctx.go b/primitive/ctx.go
deleted file mode 100644
index 936b54c..0000000
--- a/primitive/ctx.go
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/*
- * Define the ctx key and value type.
- */
-package primitive
-
-import (
-	"context"
-	"math"
-
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type CtxKey int
-
-type CommunicationMode string
-
-type ConsumeReturnType string
-
-func (c ConsumeReturnType) Ordinal() int {
-	switch c {
-	case SuccessReturn:
-		return 0
-	case TimeoutReturn:
-		return 1
-	case ExceptionReturn:
-		return 2
-	case NullReturn:
-		return 3
-	case FailedReturn:
-		return 4
-	default:
-		rlog.Error("Illegal Consumer Return Type", map[string]interface{}{
-			"type": c,
-		})
-		return 0
-	}
-}
-
-const (
-	method CtxKey = iota
-	msgCtx
-	orderlyCtx
-	concurrentlyCtx
-	producerCtx
-
-	// method name in  producer
-	SendSync   CommunicationMode = "SendSync"
-	SendOneway CommunicationMode = "SendOneway"
-	SendAsync  CommunicationMode = "SendAsync"
-	// method name in consumer
-	ConsumerPush = "ConsumerPush"
-	ConsumerPull = "ConsumerPull"
-
-	PropCtxType                       = "ConsumeContextType"
-	SuccessReturn   ConsumeReturnType = "SUCCESS"
-	TimeoutReturn   ConsumeReturnType = "TIMEOUT"
-	ExceptionReturn ConsumeReturnType = "EXCEPTION"
-	NullReturn      ConsumeReturnType = "RETURNNULL"
-	FailedReturn    ConsumeReturnType = "FAILED"
-)
-
-type ConsumeMessageContext struct {
-	ConsumerGroup string
-	Msgs          []*MessageExt
-	MQ            *MessageQueue
-	Success       bool
-	Status        string
-	// mqTractContext
-	Properties map[string]string
-}
-
-// WithMethod set call method name
-func WithMethod(ctx context.Context, m CommunicationMode) context.Context {
-	return context.WithValue(ctx, method, m)
-}
-
-// GetMethod get call method name
-func GetMethod(ctx context.Context) CommunicationMode {
-	return ctx.Value(method).(CommunicationMode)
-}
-
-// WithConsumerCtx set ConsumeMessageContext in PushConsumer
-func WithConsumerCtx(ctx context.Context, c *ConsumeMessageContext) context.Context {
-	return context.WithValue(ctx, msgCtx, c)
-}
-
-// GetConsumerCtx get ConsumeMessageContext, only legal in PushConsumer. so should add bool return param indicate
-// whether exist.
-func GetConsumerCtx(ctx context.Context) (*ConsumeMessageContext, bool) {
-	c, exist := ctx.Value(msgCtx).(*ConsumeMessageContext)
-	return c, exist
-}
-
-type ConsumeOrderlyContext struct {
-	MQ                            MessageQueue
-	AutoCommit                    bool
-	SuspendCurrentQueueTimeMillis int
-}
-
-func NewConsumeOrderlyContext() *ConsumeOrderlyContext {
-	return &ConsumeOrderlyContext{
-		AutoCommit:                    true,
-		SuspendCurrentQueueTimeMillis: -1,
-	}
-}
-
-func WithOrderlyCtx(ctx context.Context, c *ConsumeOrderlyContext) context.Context {
-	return context.WithValue(ctx, orderlyCtx, c)
-}
-
-func GetOrderlyCtx(ctx context.Context) (*ConsumeOrderlyContext, bool) {
-	c, exist := ctx.Value(orderlyCtx).(*ConsumeOrderlyContext)
-	return c, exist
-}
-
-type ConsumeConcurrentlyContext struct {
-	MQ                        MessageQueue
-	DelayLevelWhenNextConsume int
-	AckIndex                  int32
-}
-
-func NewConsumeConcurrentlyContext() *ConsumeConcurrentlyContext {
-	return &ConsumeConcurrentlyContext{
-		AckIndex: math.MaxInt32,
-	}
-}
-
-func WithConcurrentlyCtx(ctx context.Context, c *ConsumeConcurrentlyContext) context.Context {
-	return context.WithValue(ctx, concurrentlyCtx, c)
-}
-
-func GetConcurrentlyCtx(ctx context.Context) (*ConsumeConcurrentlyContext, bool) {
-	c, exist := ctx.Value(concurrentlyCtx).(*ConsumeConcurrentlyContext)
-	return c, exist
-}
-
-type ProducerCtx struct {
-	ProducerGroup     string
-	Message           Message
-	MQ                MessageQueue
-	BrokerAddr        string
-	BornHost          string
-	CommunicationMode CommunicationMode
-	SendResult        *SendResult
-	Props             map[string]string
-	MsgType           MessageType
-	Namespace         string
-}
-
-func WithProducerCtx(ctx context.Context, c *ProducerCtx) context.Context {
-	return context.WithValue(ctx, producerCtx, c)
-}
-
-func GetProducerCtx(ctx context.Context) *ProducerCtx {
-	return ctx.Value(producerCtx).(*ProducerCtx)
-}
diff --git a/primitive/errors.go b/primitive/errors.go
deleted file mode 100644
index 0fc8a7f..0000000
--- a/primitive/errors.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"strconv"
-)
-
-type MQBrokerErr struct {
-	ResponseCode int16
-	ErrorMessage string
-}
-
-func (e MQBrokerErr) Error() string {
-	return "CODE: " + strconv.Itoa(int(e.ResponseCode)) + "  DESC: " + e.ErrorMessage
-}
-
-func NewRemotingErr(s string) error {
-	return &RemotingErr{s: s}
-}
-
-type RemotingErr struct {
-	s string
-}
-
-func (e *RemotingErr) Error() string {
-	return e.s
-}
-
-func NewMQClientErr(code int16, msg string) error {
-	return &MQClientErr{code: code, msg: msg}
-}
-
-type MQClientErr struct {
-	code int16
-	msg  string
-}
-
-func (e MQClientErr) Error() string {
-	return "CODE: " + strconv.Itoa(int(e.code)) + "  DESC: " + e.msg
-}
-
-func IsRemotingErr(err error) bool {
-	_, ok := err.(*RemotingErr)
-	return ok
-}
diff --git a/primitive/interceptor.go b/primitive/interceptor.go
deleted file mode 100644
index 878aab5..0000000
--- a/primitive/interceptor.go
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"context"
-)
-
-// Invoker finish a message invoke on producer/consumer.
-type Invoker func(ctx context.Context, req, reply interface{}) error
-
-// Interceptor intercepts the invoke of a producer/consumer on messages.
-// In PushConsumer call, the req is []*MessageExt type and the reply is ConsumeResultHolder,
-// use type assert to get real type.
-type Interceptor func(ctx context.Context, req, reply interface{}, next Invoker) error
-
-func ChainInterceptors(interceptors ...Interceptor) Interceptor {
-	if len(interceptors) == 0 {
-		return nil
-	}
-	if len(interceptors) == 1 {
-		return interceptors[0]
-	}
-	return func(ctx context.Context, req, reply interface{}, invoker Invoker) error {
-		return interceptors[0](ctx, req, reply, getChainedInterceptor(interceptors, 0, invoker))
-	}
-}
-
-func getChainedInterceptor(interceptors []Interceptor, cur int, finalInvoker Invoker) Invoker {
-	if cur == len(interceptors)-1 {
-		return finalInvoker
-	}
-	return func(ctx context.Context, req, reply interface{}) error {
-		return interceptors[cur+1](ctx, req, reply, getChainedInterceptor(interceptors, cur+1, finalInvoker))
-	}
-}
diff --git a/primitive/message.go b/primitive/message.go
deleted file mode 100644
index b8e8f83..0000000
--- a/primitive/message.go
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"bytes"
-	"encoding/binary"
-	"encoding/hex"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-)
-
-const (
-	PropertyKeySeparator                   = " "
-	PropertyKeys                           = "KEYS"
-	PropertyTags                           = "TAGS"
-	PropertyWaitStoreMsgOk                 = "WAIT"
-	PropertyDelayTimeLevel                 = "DELAY"
-	PropertyRetryTopic                     = "RETRY_TOPIC"
-	PropertyRealTopic                      = "REAL_TOPIC"
-	PropertyRealQueueId                    = "REAL_QID"
-	PropertyTransactionPrepared            = "TRAN_MSG"
-	PropertyProducerGroup                  = "PGROUP"
-	PropertyMinOffset                      = "MIN_OFFSET"
-	PropertyMaxOffset                      = "MAX_OFFSET"
-	PropertyBuyerId                        = "BUYER_ID"
-	PropertyOriginMessageId                = "ORIGIN_MESSAGE_ID"
-	PropertyTransferFlag                   = "TRANSFER_FLAG"
-	PropertyCorrectionFlag                 = "CORRECTION_FLAG"
-	PropertyMQ2Flag                        = "MQ2_FLAG"
-	PropertyReconsumeTime                  = "RECONSUME_TIME"
-	PropertyMsgRegion                      = "MSG_REGION"
-	PropertyTraceSwitch                    = "TRACE_ON"
-	PropertyUniqueClientMessageIdKeyIndex  = "UNIQ_KEY"
-	PropertyMaxReconsumeTimes              = "MAX_RECONSUME_TIMES"
-	PropertyConsumeStartTime               = "CONSUME_START_TIME"
-	PropertyTranscationPreparedQueueOffset = "TRAN_PREPARED_QUEUE_OFFSET"
-	PropertyTranscationCheckTimes          = "TRANSACTION_CHECK_TIMES"
-	PropertyCheckImmunityTimeInSeconds     = "CHECK_IMMUNITY_TIME_IN_SECONDS"
-	PropertyShardingKey                    = "SHARDING_KEY"
-	PropertyTransactionID                  = "__transactionId__"
-)
-
-type Message struct {
-	Topic         string
-	Body          []byte
-	Flag          int32
-	TransactionId string
-	Batch         bool
-	Compress      bool
-	// Queue is the queue that messages will be sent to. the value must be set if want to custom the queue of message,
-	// just ignore if not.
-	Queue *MessageQueue
-
-	properties map[string]string
-	mutex      sync.RWMutex
-}
-
-func (m *Message) WithProperties(p map[string]string) {
-	m.mutex.Lock()
-	m.properties = p
-	m.mutex.Unlock()
-}
-
-func (m *Message) WithProperty(key, value string) {
-	if key == "" || value == "" {
-		return
-	}
-	m.mutex.Lock()
-	if m.properties == nil {
-		m.properties = make(map[string]string)
-	}
-	m.properties[key] = value
-	m.mutex.Unlock()
-}
-
-func (m *Message) GetProperty(key string) string {
-	m.mutex.RLock()
-	v := m.properties[key]
-	m.mutex.RUnlock()
-	return v
-}
-
-func (m *Message) RemoveProperty(key string) string {
-	m.mutex.Lock()
-	defer m.mutex.Unlock()
-	value, exist := m.properties[key]
-	if !exist {
-		return ""
-	}
-	delete(m.properties, key)
-	return value
-}
-func (m *Message) MarshallProperties() string {
-	m.mutex.RLock()
-	defer m.mutex.RUnlock()
-	buffer := bytes.NewBufferString("")
-	for k, v := range m.properties {
-		buffer.WriteString(k)
-		buffer.WriteRune(nameValueSeparator)
-		buffer.WriteString(v)
-		buffer.WriteRune(propertySeparator)
-	}
-	return buffer.String()
-}
-
-// unmarshalProperties parse data into property kv pairs.
-func (m *Message) UnmarshalProperties(data []byte) {
-	m.mutex.Lock()
-	defer m.mutex.Unlock()
-	if m.properties == nil {
-		m.properties = make(map[string]string)
-	}
-	items := bytes.Split(data, []byte{propertySeparator})
-	for _, item := range items {
-		kv := bytes.Split(item, []byte{nameValueSeparator})
-		if len(kv) == 2 {
-			m.properties[string(kv[0])] = string(kv[1])
-		}
-	}
-}
-
-func (m *Message) GetProperties() map[string]string {
-	m.mutex.Lock()
-	defer m.mutex.Unlock()
-	result := make(map[string]string, len(m.properties))
-	for k, v := range m.properties {
-		result[k] = v
-	}
-	return result
-}
-
-func NewMessage(topic string, body []byte) *Message {
-	msg := &Message{
-		Topic:      topic,
-		Body:       body,
-		properties: make(map[string]string),
-	}
-	//msg.properties[PropertyWaitStoreMsgOk] = strconv.FormatBool(true)
-	return msg
-}
-
-// WithDelayTimeLevel set message delay time to consume.
-// reference delay level definition: 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
-// delay level starts from 1. for example, if we set param level=1, then the delay time is 1s.
-func (m *Message) WithDelayTimeLevel(level int) *Message {
-	m.WithProperty(PropertyDelayTimeLevel, strconv.Itoa(level))
-	return m
-}
-
-func (m *Message) WithTag(tags string) *Message {
-	m.WithProperty(PropertyTags, tags)
-	return m
-}
-
-func (m *Message) WithKeys(keys []string) *Message {
-	var sb strings.Builder
-	for _, k := range keys {
-		sb.WriteString(k)
-		sb.WriteString(PropertyKeySeparator)
-	}
-
-	m.WithProperty(PropertyKeys, sb.String())
-	return m
-}
-
-func (m *Message) WithShardingKey(key string) *Message {
-	m.WithProperty(PropertyShardingKey, key)
-	return m
-}
-
-func (m *Message) GetTags() string {
-	return m.GetProperty(PropertyTags)
-}
-
-func (m *Message) GetKeys() string {
-	return m.GetProperty(PropertyKeys)
-}
-
-func (m *Message) GetShardingKey() string {
-	return m.GetProperty(PropertyShardingKey)
-}
-
-func (m *Message) String() string {
-	return fmt.Sprintf("[topic=%s, body=%s, Flag=%d, properties=%v, TransactionId=%s]",
-		m.Topic, string(m.Body), m.Flag, m.properties, m.TransactionId)
-}
-
-func (m *Message) Marshal() []byte {
-	// storeSize all size of message info.
-	// TOTALSIZE  MAGICCOD BODYCRC FLAG BODYSIZE BODY PROPERTYSIZE PROPERTY
-	v := m.MarshallProperties()
-	properties := []byte(v)
-	storeSize := 4 + 4 + 4 + 4 + 4 + len(m.Body) + 2 + len(properties)
-
-	buffer := make([]byte, storeSize)
-	pos := 0
-	binary.BigEndian.PutUint32(buffer[pos:], uint32(storeSize)) // 1. TOTALSIZE
-	pos += 4
-	binary.BigEndian.PutUint32(buffer[pos:], 0) // 2. MAGICCODE
-	pos += 4
-	binary.BigEndian.PutUint32(buffer[pos:], 0) // 3. BODYCRC
-	pos += 4
-	binary.BigEndian.PutUint32(buffer[pos:], uint32(m.Flag)) // 4. FLAG
-	pos += 4
-	binary.BigEndian.PutUint32(buffer[pos:], uint32(len(m.Body))) // 5. BODYSIZE
-	pos += 4
-	copy(buffer[pos:], m.Body)
-	pos += len(m.Body)
-
-	binary.BigEndian.PutUint16(buffer[pos:], uint16(len(properties))) // 7. PROPERTYSIZE
-	pos += 2
-	copy(buffer[pos:], properties)
-
-	return buffer
-}
-
-type MessageExt struct {
-	Message
-	MsgId                     string
-	OffsetMsgId               string
-	StoreSize                 int32
-	QueueOffset               int64
-	SysFlag                   int32
-	BornTimestamp             int64
-	BornHost                  string
-	StoreTimestamp            int64
-	StoreHost                 string
-	CommitLogOffset           int64
-	BodyCRC                   int32
-	ReconsumeTimes            int32
-	PreparedTransactionOffset int64
-}
-
-func (msgExt *MessageExt) GetTags() string {
-	return msgExt.GetProperty(PropertyTags)
-}
-
-func (msgExt *MessageExt) GetRegionID() string {
-	return msgExt.GetProperty(PropertyMsgRegion)
-}
-
-func (msgExt *MessageExt) IsTraceOn() string {
-	return msgExt.GetProperty(PropertyTraceSwitch)
-}
-
-func (msgExt *MessageExt) String() string {
-	return fmt.Sprintf("[Message=%s, MsgId=%s, OffsetMsgId=%s,QueueId=%d, StoreSize=%d, QueueOffset=%d, SysFlag=%d, "+
-		"BornTimestamp=%d, BornHost=%s, StoreTimestamp=%d, StoreHost=%s, CommitLogOffset=%d, BodyCRC=%d, "+
-		"ReconsumeTimes=%d, PreparedTransactionOffset=%d]", msgExt.Message.String(), msgExt.MsgId, msgExt.OffsetMsgId, msgExt.Queue.QueueId,
-		msgExt.StoreSize, msgExt.QueueOffset, msgExt.SysFlag, msgExt.BornTimestamp, msgExt.BornHost,
-		msgExt.StoreTimestamp, msgExt.StoreHost, msgExt.CommitLogOffset, msgExt.BodyCRC, msgExt.ReconsumeTimes,
-		msgExt.PreparedTransactionOffset)
-}
-
-func DecodeMessage(data []byte) []*MessageExt {
-	msgs := make([]*MessageExt, 0)
-	buf := bytes.NewBuffer(data)
-	count := 0
-	for count < len(data) {
-		msg := &MessageExt{}
-		msg.Queue = &MessageQueue{}
-
-		// 1. total size
-		binary.Read(buf, binary.BigEndian, &msg.StoreSize)
-		count += 4
-
-		// 2. magic code
-		buf.Next(4)
-		count += 4
-
-		// 3. body CRC32
-		binary.Read(buf, binary.BigEndian, &msg.BodyCRC)
-		count += 4
-
-		// 4. queueID
-		var qId int32
-		binary.Read(buf, binary.BigEndian, &qId)
-		msg.Queue.QueueId = int(qId)
-		count += 4
-
-		// 5. Flag
-		binary.Read(buf, binary.BigEndian, &msg.Flag)
-		count += 4
-
-		// 6. QueueOffset
-		binary.Read(buf, binary.BigEndian, &msg.QueueOffset)
-		count += 8
-
-		// 7. physical offset
-		binary.Read(buf, binary.BigEndian, &msg.CommitLogOffset)
-		count += 8
-
-		// 8. SysFlag
-		binary.Read(buf, binary.BigEndian, &msg.SysFlag)
-		count += 4
-
-		// 9. BornTimestamp
-		binary.Read(buf, binary.BigEndian, &msg.BornTimestamp)
-		count += 8
-
-		var (
-			port      int32
-			hostBytes []byte
-		)
-		// 10. born host
-		if msg.SysFlag&FlagBornHostV6 == FlagBornHostV6 {
-			hostBytes = buf.Next(16)
-			binary.Read(buf, binary.BigEndian, &port)
-			msg.BornHost = fmt.Sprintf("%s:%d", utils.GetAddressByBytes(hostBytes), port)
-			count += 20
-		} else {
-			hostBytes = buf.Next(4)
-			binary.Read(buf, binary.BigEndian, &port)
-			msg.BornHost = fmt.Sprintf("%s:%d", utils.GetAddressByBytes(hostBytes), port)
-			count += 8
-		}
-
-		// 11. store timestamp
-		binary.Read(buf, binary.BigEndian, &msg.StoreTimestamp)
-		count += 8
-
-		// 12. store host
-		if msg.SysFlag&FlagStoreHostV6 == FlagStoreHostV6 {
-			hostBytes = buf.Next(16)
-			binary.Read(buf, binary.BigEndian, &port)
-			msg.StoreHost = fmt.Sprintf("%s:%d", utils.GetAddressByBytes(hostBytes), port)
-			count += 20
-		} else {
-			hostBytes = buf.Next(4)
-			binary.Read(buf, binary.BigEndian, &port)
-			msg.StoreHost = fmt.Sprintf("%s:%d", utils.GetAddressByBytes(hostBytes), port)
-			count += 8
-		}
-
-		// 13. reconsume times
-		binary.Read(buf, binary.BigEndian, &msg.ReconsumeTimes)
-		count += 4
-
-		// 14. prepared transaction offset
-		binary.Read(buf, binary.BigEndian, &msg.PreparedTransactionOffset)
-		count += 8
-
-		// 15. body
-		var length int32
-		binary.Read(buf, binary.BigEndian, &length)
-		msg.Body = buf.Next(int(length))
-		if (msg.SysFlag & FlagCompressed) == FlagCompressed {
-			msg.Body = utils.UnCompress(msg.Body)
-		}
-		count += 4 + int(length)
-
-		// 16. topic
-		_byte, _ := buf.ReadByte()
-		msg.Topic = string(buf.Next(int(_byte)))
-		count += 1 + int(_byte)
-
-		// 17. properties
-		var propertiesLength int16
-		binary.Read(buf, binary.BigEndian, &propertiesLength)
-		if propertiesLength > 0 {
-			msg.UnmarshalProperties(buf.Next(int(propertiesLength)))
-		}
-		count += 2 + int(propertiesLength)
-
-		msg.OffsetMsgId = CreateMessageId(hostBytes, port, msg.CommitLogOffset)
-		//count += 16
-		if msg.properties == nil {
-			msg.properties = make(map[string]string, 0)
-		}
-		msgID := msg.GetProperty(PropertyUniqueClientMessageIdKeyIndex)
-		if len(msgID) == 0 {
-			msg.MsgId = msg.OffsetMsgId
-		} else {
-			msg.MsgId = msgID
-		}
-		msgs = append(msgs, msg)
-	}
-
-	return msgs
-}
-
-// MessageQueue message queue
-type MessageQueue struct {
-	Topic      string `json:"topic"`
-	BrokerName string `json:"brokerName"`
-	QueueId    int    `json:"queueId"`
-}
-
-func (mq *MessageQueue) String() string {
-	return fmt.Sprintf("MessageQueue [topic=%s, brokerName=%s, queueId=%d]", mq.Topic, mq.BrokerName, mq.QueueId)
-}
-
-func (mq *MessageQueue) HashCode() int {
-	result := 1
-	result = 31*result + utils.HashString(mq.BrokerName)
-	result = 31*result + mq.QueueId
-	result = 31*result + utils.HashString(mq.Topic)
-
-	return result
-}
-
-type AccessChannel int
-
-const (
-	// connect to private IDC cluster.
-	Local AccessChannel = iota
-	// connect to Cloud service.
-	Cloud
-)
-
-type MessageType int
-
-const (
-	NormalMsg MessageType = iota
-	TransMsgHalf
-	TransMsgCommit
-	DelayMsg
-)
-
-type LocalTransactionState int
-
-const (
-	CommitMessageState LocalTransactionState = iota + 1
-	RollbackMessageState
-	UnknowState
-)
-
-type TransactionListener interface {
-	//  When send transactional prepare(half) message succeed, this method will be invoked to execute local transaction.
-	ExecuteLocalTransaction(*Message) LocalTransactionState
-
-	// When no response to prepare(half) message. broker will send check message to check the transaction status, and this
-	// method will be invoked to get local transaction status.
-	CheckLocalTransaction(*MessageExt) LocalTransactionState
-}
-
-type MessageID struct {
-	Addr   string
-	Port   int
-	Offset int64
-}
-
-func CreateMessageId(addr []byte, port int32, offset int64) string {
-	buffer := GetBuffer()
-	defer BackBuffer(buffer)
-	buffer.Write(addr)
-	_ = binary.Write(buffer, binary.BigEndian, port)
-	_ = binary.Write(buffer, binary.BigEndian, offset)
-	return strings.ToUpper(hex.EncodeToString(buffer.Bytes()))
-}
-
-func UnmarshalMsgID(id []byte) (*MessageID, error) {
-	if len(id) < 32 {
-		return nil, fmt.Errorf("%s len < 32", string(id))
-	}
-	var (
-		ipBytes     = make([]byte, 4)
-		portBytes   = make([]byte, 4)
-		offsetBytes = make([]byte, 8)
-	)
-	hex.Decode(ipBytes, id[0:8])
-	hex.Decode(portBytes, id[8:16])
-	hex.Decode(offsetBytes, id[16:32])
-
-	return &MessageID{
-		Addr:   utils.GetAddressByBytes(ipBytes),
-		Port:   int(binary.BigEndian.Uint32(portBytes)),
-		Offset: int64(binary.BigEndian.Uint64(offsetBytes)),
-	}, nil
-}
-
-var (
-	CompressedFlag = 0x1
-
-	MultiTagsFlag = 0x1 << 1
-
-	TransactionNotType = 0
-
-	TransactionPreparedType = 0x1 << 2
-
-	TransactionCommitType = 0x2 << 2
-
-	TransactionRollbackType = 0x3 << 2
-)
-
-func GetTransactionValue(flag int) int {
-	return flag & TransactionRollbackType
-}
-
-func ResetTransactionValue(flag int, typeFlag int) int {
-	return (flag & (^TransactionRollbackType)) | typeFlag
-}
-
-func ClearCompressedFlag(flag int) int {
-	return flag & (^CompressedFlag)
-}
-
-func SetCompressedFlag(flag int) int {
-	return flag | CompressedFlag
-}
-
-var (
-	counter        int16 = 0
-	startTimestamp int64 = 0
-	nextTimestamp  int64 = 0
-	prefix         string
-	locker         sync.Mutex
-	classLoadId    int32 = 0
-)
-
-func init() {
-	buf := new(bytes.Buffer)
-
-	ip, err := utils.ClientIP4()
-	if err != nil {
-		ip = utils.FakeIP()
-	}
-	_, _ = buf.Write(ip)
-	_ = binary.Write(buf, binary.BigEndian, Pid())
-	_ = binary.Write(buf, binary.BigEndian, classLoadId)
-	prefix = strings.ToUpper(hex.EncodeToString(buf.Bytes()))
-}
-
-func CreateUniqID() string {
-	locker.Lock()
-	defer locker.Unlock()
-
-	if time.Now().Unix() > nextTimestamp {
-		updateTimestamp()
-	}
-	counter++
-	buf := new(bytes.Buffer)
-	_ = binary.Write(buf, binary.BigEndian, int32((time.Now().Unix()-startTimestamp)*1000))
-	_ = binary.Write(buf, binary.BigEndian, counter)
-
-	return prefix + hex.EncodeToString(buf.Bytes())
-}
-
-func updateTimestamp() {
-	year, month := time.Now().Year(), time.Now().Month()
-	startTimestamp = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix()
-	nextTimestamp = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0).Unix()
-}
-
-func Pid() int16 {
-	return int16(os.Getpid())
-}
diff --git a/primitive/message_test.go b/primitive/message_test.go
deleted file mode 100644
index e47a298..0000000
--- a/primitive/message_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import "testing"
-
-func TestMessageID(t *testing.T) {
-	id := []byte("0AAF0895000078BF000000000009BB4A")
-	msgID, err := UnmarshalMsgID(id)
-	if err != nil {
-		t.Fatalf("unmarshal msg id error, ms is: %s", err.Error())
-	}
-	if msgID.Addr != "10.175.8.149" {
-		t.Fatalf("parse messageID %s error", id)
-	}
-	if msgID.Port != 30911 {
-		t.Fatalf("parse messageID %s error", id)
-	}
-	if msgID.Offset != 637770 {
-		t.Fatalf("parse messageID %s error", id)
-	}
-	t.Log(msgID)
-}
diff --git a/primitive/nsresolver.go b/primitive/nsresolver.go
deleted file mode 100644
index 4e5917c..0000000
--- a/primitive/nsresolver.go
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-package primitive
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"os/user"
-	"path"
-	"strings"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-// resolver for nameserver, monitor change of nameserver and notify client
-// consul or domain is common
-type NsResolver interface {
-	Resolve() []string
-	Description() string
-}
-
-type StaticResolver struct {
-}
-
-var _ NsResolver = (*EnvResolver)(nil)
-
-func NewEnvResolver() *EnvResolver {
-	return &EnvResolver{}
-}
-
-type EnvResolver struct {
-}
-
-func (e *EnvResolver) Resolve() []string {
-	if v := os.Getenv("NAMESRV_ADDR"); v != "" {
-		return strings.Split(v, ";")
-	}
-	return nil
-}
-
-func (e *EnvResolver) Description() string {
-	return "env resolver of var NAMESRV_ADDR"
-}
-
-type passthroughResolver struct {
-	addr     []string
-	failback NsResolver
-}
-
-func NewPassthroughResolver(addr []string) *passthroughResolver {
-	return &passthroughResolver{
-		addr:     addr,
-		failback: NewEnvResolver(),
-	}
-}
-
-func (p *passthroughResolver) Resolve() []string {
-	if p.addr != nil {
-		return p.addr
-	}
-	return p.failback.Resolve()
-}
-
-func (p *passthroughResolver) Description() string {
-	return fmt.Sprintf("passthrough resolver of %v", p.addr)
-}
-
-const (
-	DEFAULT_NAMESRV_ADDR = "http://jmenv.tbsite.net:8080/rocketmq/nsaddr"
-)
-
-var _ NsResolver = (*HttpResolver)(nil)
-
-type HttpResolver struct {
-	domain   string
-	instance string
-	cli      http.Client
-	failback NsResolver
-}
-
-func NewHttpResolver(instance string, domain ...string) *HttpResolver {
-	d := DEFAULT_NAMESRV_ADDR
-	if len(domain) > 0 {
-		d = domain[0]
-	}
-	client := http.Client{Timeout: 10 * time.Second}
-
-	h := &HttpResolver{
-		domain:   d,
-		instance: instance,
-		cli:      client,
-		failback: NewEnvResolver(),
-	}
-	return h
-}
-
-func (h *HttpResolver) Resolve() []string {
-	addrs := h.get()
-	if len(addrs) > 0 {
-		return addrs
-	}
-
-	addrs = h.loadSnapshot()
-	if len(addrs) > 0 {
-		return addrs
-	}
-	return h.failback.Resolve()
-}
-
-func (h *HttpResolver) Description() string {
-	return fmt.Sprintf("passthrough resolver of domain:%v instance:%v", h.domain, h.instance)
-}
-
-func (h *HttpResolver) get() []string {
-	resp, err := h.cli.Get(h.domain)
-	if err != nil || resp == nil || resp.StatusCode != 200 {
-		data := map[string]interface{}{
-			"NameServerDomain": h.domain,
-			"err":              err,
-		}
-		if resp != nil {
-			data["StatusCode"] = resp.StatusCode
-		}
-		rlog.Error("name server http fetch failed", data)
-		return nil
-	}
-
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		rlog.Error("name server read http response failed", map[string]interface{}{
-			"NameServerDomain": h.domain,
-			"err":              err,
-		})
-		return nil
-	}
-
-	bodyStr := string(body)
-	if bodyStr == "" {
-		return nil
-	}
-
-	h.saveSnapshot(body)
-
-	return strings.Split(string(body), ";")
-}
-
-func (h *HttpResolver) saveSnapshot(body []byte) error {
-	filePath := h.getSnapshotFilePath(h.instance)
-	err := ioutil.WriteFile(filePath, body, 0644)
-	if err != nil {
-		rlog.Error("name server snapshot save failed", map[string]interface{}{
-			"filePath": filePath,
-			"err":      err,
-		})
-		return err
-	}
-
-	rlog.Info("name server snapshot save successfully", map[string]interface{}{
-		"filePath": filePath,
-	})
-	return nil
-}
-
-func (h *HttpResolver) loadSnapshot() []string {
-	filePath := h.getSnapshotFilePath(h.instance)
-	_, err := os.Stat(filePath)
-	if os.IsNotExist(err) {
-		rlog.Warning("name server snapshot local file not exists", map[string]interface{}{
-			"filePath": filePath,
-		})
-		return nil
-	}
-
-	bs, err := ioutil.ReadFile(filePath)
-	if err != nil {
-		return nil
-	}
-
-	rlog.Info("load the name server snapshot local file", map[string]interface{}{
-		"filePath": filePath,
-	})
-	return strings.Split(string(bs), ";")
-}
-
-func (h *HttpResolver) getSnapshotFilePath(instanceName string) string {
-	homeDir := ""
-	if usr, err := user.Current(); err == nil {
-		homeDir = usr.HomeDir
-	} else {
-		rlog.Error("name server domain, can't get user home directory", map[string]interface{}{
-			"err": err,
-		})
-	}
-	storePath := path.Join(homeDir, "/logs/rocketmq-go/snapshot")
-	if _, err := os.Stat(storePath); os.IsNotExist(err) {
-		if err = os.MkdirAll(storePath, 0755); err != nil {
-			rlog.Fatal("can't create name server snapshot directory", map[string]interface{}{
-				"path": storePath,
-				"err":  err,
-			})
-		}
-	}
-	filePath := path.Join(storePath, fmt.Sprintf("nameserver_addr-%s", instanceName))
-	return filePath
-}
diff --git a/primitive/nsresolver_test.go b/primitive/nsresolver_test.go
deleted file mode 100644
index d42d2c6..0000000
--- a/primitive/nsresolver_test.go
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-package primitive
-
-import (
-	"fmt"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-	"io/ioutil"
-	"net"
-	"net/http"
-	"os"
-	"strings"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestEnvResolver(t *testing.T) {
-	Convey("Test UpdateNameServerAddress Use Env", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-
-		resolver := NewEnvResolver()
-		os.Setenv("NAMESRV_ADDR", strings.Join(srvs, ";"))
-
-		addrs := resolver.Resolve()
-
-		So(Diff(srvs, addrs), ShouldBeFalse)
-	})
-}
-
-func TestHttpResolverWithGet(t *testing.T) {
-	Convey("Test UpdateNameServerAddress Save Local Snapshot", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-		http.HandleFunc("/nameserver/addrs2", func(w http.ResponseWriter, r *http.Request) {
-			fmt.Fprintf(w, strings.Join(srvs, ";"))
-		})
-		server := &http.Server{Addr: ":0", Handler: nil}
-		listener, _ := net.Listen("tcp", ":0")
-		go server.Serve(listener)
-
-		port := listener.Addr().(*net.TCPAddr).Port
-		nameServerDommain := fmt.Sprintf("http://127.0.0.1:%d/nameserver/addrs2", port)
-		rlog.Info("Temporary Nameserver", map[string]interface{}{
-			"domain": nameServerDommain,
-		})
-
-		resolver := NewHttpResolver("DEFAULT", nameServerDommain)
-		resolver.Resolve()
-
-		// check snapshot saved
-		filePath := resolver.getSnapshotFilePath("DEFAULT")
-		body := strings.Join(srvs, ";")
-		bs, _ := ioutil.ReadFile(filePath)
-		So(string(bs), ShouldEqual, body)
-	})
-}
-
-func TestHttpResolverWithSnapshotFile(t *testing.T) {
-	Convey("Test UpdateNameServerAddress Use Local Snapshot", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-
-		resolver := NewHttpResolver("DEFAULT", "http://127.0.0.1:80/error/nsaddrs")
-
-		os.Setenv("NAMESRV_ADDR", "") // clear env
-		// setup local snapshot file
-		filePath := resolver.getSnapshotFilePath("DEFAULT")
-		body := strings.Join(srvs, ";")
-		_ = ioutil.WriteFile(filePath, []byte(body), 0644)
-
-		addrs := resolver.Resolve()
-
-		So(Diff(addrs, srvs), ShouldBeFalse)
-	})
-}
-
-func TesHttpReslverWithSnapshotFileOnce(t *testing.T) {
-	Convey("Test UpdateNameServerAddress Load Local Snapshot Once", t, func() {
-		srvs := []string{
-			"192.168.100.1",
-			"192.168.100.2",
-			"192.168.100.3",
-			"192.168.100.4",
-			"192.168.100.5",
-		}
-
-		resolver := NewHttpResolver("DEFAULT", "http://127.0.0.1:80/error/nsaddrs")
-
-		os.Setenv("NAMESRV_ADDR", "") // clear env
-		// setup local snapshot file
-		filePath := resolver.getSnapshotFilePath("DEFAULT")
-		body := strings.Join(srvs, ";")
-		_ = ioutil.WriteFile(filePath, []byte(body), 0644)
-		// load local snapshot file first time
-		addrs1 := resolver.Resolve()
-
-		// change the local snapshot file to check load once
-		_ = ioutil.WriteFile(filePath, []byte("127.0.0.1;127.0.0.2"), 0644)
-
-		addrs2 := resolver.Resolve()
-
-		So(Diff(addrs1, addrs2), ShouldBeFalse)
-		So(Diff(addrs1, srvs), ShouldBeFalse)
-	})
-}
diff --git a/primitive/pool.go b/primitive/pool.go
deleted file mode 100644
index 29cd834..0000000
--- a/primitive/pool.go
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"bytes"
-	"sync"
-)
-
-var headerPool = sync.Pool{}
-var bufferPool = sync.Pool{}
-
-func init() {
-	headerPool.New = func() interface{} {
-		b := make([]byte, 4)
-		return &b
-	}
-	bufferPool.New = func() interface{} {
-		return new(bytes.Buffer)
-	}
-}
-
-func GetHeader() *[]byte {
-	d := headerPool.Get().(*[]byte)
-	//d = (d)[:0]
-	return d
-}
-
-func BackHeader(d *[]byte) {
-	headerPool.Put(d)
-}
-
-func GetBuffer() *bytes.Buffer {
-	b := bufferPool.Get().(*bytes.Buffer)
-	b.Reset()
-	return b
-}
-
-func BackBuffer(b *bytes.Buffer) {
-	b.Reset()
-	bufferPool.Put(b)
-}
diff --git a/primitive/result.go b/primitive/result.go
deleted file mode 100644
index 20d393a..0000000
--- a/primitive/result.go
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"fmt"
-)
-
-// SendStatus of message
-type SendStatus int
-
-const (
-	SendOK SendStatus = iota
-	SendFlushDiskTimeout
-	SendFlushSlaveTimeout
-	SendSlaveNotAvailable
-	SendUnknownError
-
-	FlagCompressed  = 0x1
-	FlagBornHostV6  = 0x1 << 4
-	FlagStoreHostV6 = 0x1 << 5
-	MsgIdLength     = 8 + 8
-
-	propertySeparator  = '\002'
-	nameValueSeparator = '\001'
-)
-
-// SendResult RocketMQ send result
-type SendResult struct {
-	Status        SendStatus
-	MsgID         string
-	MessageQueue  *MessageQueue
-	QueueOffset   int64
-	TransactionID string
-	OffsetMsgID   string
-	RegionID      string
-	TraceOn       bool
-}
-
-func NewSendResult() *SendResult {
-	return &SendResult{Status: SendUnknownError}
-}
-
-// SendResult send message result to string(detail result)
-func (result *SendResult) String() string {
-	return fmt.Sprintf("SendResult [sendStatus=%d, msgIds=%s, offsetMsgId=%s, queueOffset=%d, messageQueue=%s]",
-		result.Status, result.MsgID, result.OffsetMsgID, result.QueueOffset, result.MessageQueue.String())
-}
-
-// SendResult RocketMQ send result
-type TransactionSendResult struct {
-	*SendResult
-	State LocalTransactionState
-}
-
-// PullStatus pull Status
-type PullStatus int
-
-// predefined pull Status
-const (
-	PullFound PullStatus = iota
-	PullNoNewMsg
-	PullNoMsgMatched
-	PullOffsetIllegal
-	PullBrokerTimeout
-)
-
-// PullResult the pull result
-type PullResult struct {
-	NextBeginOffset      int64
-	MinOffset            int64
-	MaxOffset            int64
-	Status               PullStatus
-	SuggestWhichBrokerId int64
-
-	// messageExts message info
-	messageExts []*MessageExt
-	//
-	body []byte
-}
-
-func (result *PullResult) GetMessageExts() []*MessageExt {
-	return result.messageExts
-}
-
-func (result *PullResult) SetMessageExts(msgExts []*MessageExt) {
-	result.messageExts = msgExts
-}
-
-func (result *PullResult) GetMessages() []*Message {
-	if len(result.messageExts) == 0 {
-		return make([]*Message, 0)
-	}
-	return toMessages(result.messageExts)
-}
-
-func (result *PullResult) SetBody(data []byte) {
-	result.body = data
-}
-
-func (result *PullResult) GetBody() []byte {
-	return result.body
-}
-
-func (result *PullResult) String() string {
-	return ""
-}
-
-func toMessages(messageExts []*MessageExt) []*Message {
-	msgs := make([]*Message, 0)
-
-	return msgs
-}
diff --git a/primitive/result_test.go b/primitive/result_test.go
deleted file mode 100644
index fcc03cf..0000000
--- a/primitive/result_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-import (
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestProperties(t *testing.T) {
-	msg1 := NewMessage("test", nil)
-	msg1.properties = map[string]string{
-		"k1": "v1",
-		"k2": "v2",
-	}
-	str := msg1.MarshallProperties()
-	msg2 := NewMessage("test", nil)
-	msg2.UnmarshalProperties([]byte(str))
-	assert.Equal(t, msg1.properties, msg2.properties)
-}
-
-func TestCreateMessageId(t *testing.T) {
-	Convey("MessageId gen", t, func() {
-		b := []byte{10, 93, 233, 58}
-		port := int32(10911)
-		offset := int64(4391252)
-		id := CreateMessageId(b, port, offset)
-		Convey("generated messageId should be equal to expected", func() {
-			assert.Equal(t, "0A5DE93A00002A9F0000000000430154", id)
-		})
-
-		b2 := []byte("127.0.0.1")
-		port2 := int32(11)
-		offset2 := int64(12)
-		id2 := CreateMessageId(b2, port2, offset2)
-		Convey("new generated messageId should be equal to expected", func() {
-			assert.Equal(t, "3132372E302E302E310000000B000000000000000C", id2)
-		})
-
-		Convey("ex-generated messageId should not change", func() {
-			assert.Equal(t, "0A5DE93A00002A9F0000000000430154", id)
-		})
-	})
-
-}
-
-func TestGetProperties(t *testing.T) {
-	msg1 := NewMessage("test", nil)
-	msg1.properties = map[string]string{
-		"k1": "v1",
-		"k2": "v2",
-	}
-	assert.Equal(t, msg1.GetProperties(), map[string]string{
-		"k1": "v1",
-		"k2": "v2",
-	})
-}
diff --git a/primitive/trace.go b/primitive/trace.go
deleted file mode 100644
index 53a13f0..0000000
--- a/primitive/trace.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package primitive
-
-// config for message trace.
-type TraceConfig struct {
-	TraceTopic   string
-	GroupName    string
-	Access       AccessChannel
-	NamesrvAddrs []string
-	Resolver     NsResolver
-	Credentials  // acl config for trace. omit if acl is closed on broker.
-}
diff --git a/producer/interceptor.go b/producer/interceptor.go
deleted file mode 100644
index 71eb8e7..0000000
--- a/producer/interceptor.go
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/**
- * builtin interceptor
- */
-package producer
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-// WithTrace support rocketmq trace: https://github.com/apache/rocketmq/wiki/RIP-6-Message-Trace.
-func WithTrace(traceCfg *primitive.TraceConfig) Option {
-	return func(options *producerOptions) {
-
-		ori := options.Interceptors
-		options.Interceptors = make([]primitive.Interceptor, 0)
-		options.Interceptors = append(options.Interceptors, newTraceInterceptor(traceCfg))
-		options.Interceptors = append(options.Interceptors, ori...)
-	}
-}
-
-func newTraceInterceptor(traceCfg *primitive.TraceConfig) primitive.Interceptor {
-	dispatcher := internal.NewTraceDispatcher(traceCfg)
-	if dispatcher != nil {
-		dispatcher.Start()
-	}
-
-	return func(ctx context.Context, req, reply interface{}, next primitive.Invoker) error {
-		if dispatcher == nil {
-			return fmt.Errorf("GetOrNewRocketMQClient faild")
-		}
-		beginT := time.Now()
-		err := next(ctx, req, reply)
-
-		producerCtx := primitive.GetProducerCtx(ctx)
-		if producerCtx.Message.Topic == dispatcher.GetTraceTopicName() {
-			return err
-		}
-
-		// SendOneway && SendAsync has no reply.
-		if reply == nil {
-			return err
-		}
-
-		result := reply.(*primitive.SendResult)
-		if result.RegionID == "" || !result.TraceOn {
-			return err
-		}
-
-		sendSuccess := result.Status == primitive.SendOK
-		costT := time.Since(beginT).Nanoseconds() / int64(time.Millisecond)
-		storeT := beginT.UnixNano()/int64(time.Millisecond) + costT/2
-
-		traceBean := internal.TraceBean{
-			Topic:       producerCtx.Message.Topic,
-			Tags:        producerCtx.Message.GetTags(),
-			Keys:        producerCtx.Message.GetKeys(),
-			StoreHost:   producerCtx.BrokerAddr,
-			ClientHost:  utils.LocalIP,
-			BodyLength:  len(producerCtx.Message.Body),
-			MsgType:     producerCtx.MsgType,
-			MsgId:       result.MsgID,
-			OffsetMsgId: result.OffsetMsgID,
-			StoreTime:   storeT,
-		}
-
-		traceCtx := internal.TraceContext{
-			RequestId: primitive.CreateUniqID(), // set id
-			TimeStamp: time.Now().UnixNano() / int64(time.Millisecond),
-
-			TraceType:  internal.Pub,
-			GroupName:  producerCtx.ProducerGroup,
-			RegionId:   result.RegionID,
-			TraceBeans: []internal.TraceBean{traceBean},
-			CostTime:   costT,
-			IsSuccess:  sendSuccess,
-		}
-		dispatcher.Append(traceCtx)
-		return err
-	}
-}
diff --git a/producer/option.go b/producer/option.go
deleted file mode 100644
index ae76511..0000000
--- a/producer/option.go
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package producer
-
-import (
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func defaultProducerOptions() producerOptions {
-	opts := producerOptions{
-		ClientOptions:              internal.DefaultClientOptions(),
-		Selector:                   NewRoundRobinQueueSelector(),
-		SendMsgTimeout:             3 * time.Second,
-		DefaultTopicQueueNums:      4,
-		CreateTopicKey:             "TBW102",
-		Resolver:                   primitive.NewHttpResolver("DEFAULT"),
-		CompressMsgBodyOverHowmuch: 4096,
-		CompressLevel:              5,
-	}
-	opts.ClientOptions.GroupName = "DEFAULT_PRODUCER"
-	return opts
-}
-
-type producerOptions struct {
-	internal.ClientOptions
-	Selector              QueueSelector
-	SendMsgTimeout        time.Duration
-	DefaultTopicQueueNums int
-	CreateTopicKey        string // "TBW102" Will be created at broker when isAutoCreateTopicEnable. when topic is not created,
-	// and broker open isAutoCreateTopicEnable, topic will use "TBW102" config to create topic
-	Resolver                   primitive.NsResolver
-	CompressMsgBodyOverHowmuch int
-	CompressLevel              int
-}
-
-type Option func(*producerOptions)
-
-// WithGroupName set group name address
-func WithGroupName(group string) Option {
-	return func(opts *producerOptions) {
-		if group == "" {
-			return
-		}
-		opts.GroupName = group
-	}
-}
-
-func WithInstanceName(name string) Option {
-	return func(opts *producerOptions) {
-		opts.InstanceName = name
-	}
-}
-
-// WithNamespace set the namespace of producer
-func WithNamespace(namespace string) Option {
-	return func(opts *producerOptions) {
-		opts.Namespace = namespace
-	}
-}
-
-func WithSendMsgTimeout(duration time.Duration) Option {
-	return func(opts *producerOptions) {
-		opts.SendMsgTimeout = duration
-	}
-}
-
-func WithVIPChannel(enable bool) Option {
-	return func(opts *producerOptions) {
-		opts.VIPChannelEnabled = enable
-	}
-}
-
-// WithRetry return a Option that specifies the retry times when send failed.
-// TODO: use retry middleware instead
-func WithRetry(retries int) Option {
-	return func(opts *producerOptions) {
-		opts.RetryTimes = retries
-	}
-}
-
-func WithInterceptor(f ...primitive.Interceptor) Option {
-	return func(opts *producerOptions) {
-		opts.Interceptors = append(opts.Interceptors, f...)
-	}
-}
-
-func WithQueueSelector(s QueueSelector) Option {
-	return func(options *producerOptions) {
-		options.Selector = s
-	}
-}
-
-func WithCredentials(c primitive.Credentials) Option {
-	return func(options *producerOptions) {
-		options.ClientOptions.Credentials = c
-	}
-}
-
-func WithDefaultTopicQueueNums(queueNum int) Option {
-	return func(options *producerOptions) {
-		options.DefaultTopicQueueNums = queueNum
-	}
-}
-
-func WithCreateTopicKey(topic string) Option {
-	return func(options *producerOptions) {
-		options.CreateTopicKey = topic
-	}
-}
-
-// WithNsResolver set nameserver resolver to fetch nameserver addr
-func WithNsResolver(resolver primitive.NsResolver) Option {
-	return func(options *producerOptions) {
-		options.Resolver = resolver
-	}
-}
-
-// WithNameServer set NameServer address, only support one NameServer cluster in alpha2
-func WithNameServer(nameServers primitive.NamesrvAddr) Option {
-	return func(options *producerOptions) {
-		options.Resolver = primitive.NewPassthroughResolver(nameServers)
-	}
-}
-
-// WithNameServerDomain set NameServer domain
-func WithNameServerDomain(nameServerUrl string) Option {
-	return func(opts *producerOptions) {
-		opts.Resolver = primitive.NewHttpResolver("DEFAULT", nameServerUrl)
-	}
-}
-
-// WithCompressMsgBodyOverHowmuch set compression threshold
-func WithCompressMsgBodyOverHowmuch(threshold int) Option {
-	return func(opts *producerOptions) {
-		opts.CompressMsgBodyOverHowmuch = threshold
-	}
-}
-
-// WithCompressLevel set compress level (0~9)
-// 0 stands for best speed
-// 9 stands for best compression ratio
-func WithCompressLevel(level int) Option {
-	return func(opts *producerOptions) {
-		opts.CompressLevel = level
-	}
-}
diff --git a/producer/producer.go b/producer/producer.go
deleted file mode 100644
index 3c875c6..0000000
--- a/producer/producer.go
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package producer
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	errors2 "github.com/apache/rocketmq-client-go/v2/errors"
-	"strconv"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"github.com/pkg/errors"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/internal/utils"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-	"github.com/apache/rocketmq-client-go/v2/rlog"
-)
-
-type defaultProducer struct {
-	group       string
-	client      internal.RMQClient
-	state       int32
-	options     producerOptions
-	publishInfo sync.Map
-	callbackCh  chan interface{}
-
-	interceptor primitive.Interceptor
-}
-
-func NewDefaultProducer(opts ...Option) (*defaultProducer, error) {
-	defaultOpts := defaultProducerOptions()
-	for _, apply := range opts {
-		apply(&defaultOpts)
-	}
-	srvs, err := internal.NewNamesrv(defaultOpts.Resolver)
-	if err != nil {
-		return nil, errors.Wrap(err, "new Namesrv failed.")
-	}
-	if !defaultOpts.Credentials.IsEmpty() {
-		srvs.SetCredentials(defaultOpts.Credentials)
-	}
-	defaultOpts.Namesrv = srvs
-
-	producer := &defaultProducer{
-		group:      defaultOpts.GroupName,
-		callbackCh: make(chan interface{}),
-		options:    defaultOpts,
-	}
-	producer.client = internal.GetOrNewRocketMQClient(defaultOpts.ClientOptions, producer.callbackCh)
-	if producer.client == nil {
-		return nil, fmt.Errorf("GetOrNewRocketMQClient faild")
-	}
-	defaultOpts.Namesrv = producer.client.GetNameSrv()
-
-	producer.interceptor = primitive.ChainInterceptors(producer.options.Interceptors...)
-
-	return producer, nil
-}
-
-func (p *defaultProducer) Start() error {
-	if p == nil || p.client == nil {
-		return fmt.Errorf("client instance is nil, can not start producer")
-	}
-	atomic.StoreInt32(&p.state, int32(internal.StateRunning))
-	err := p.client.RegisterProducer(p.group, p)
-	if err != nil {
-		return err
-	}
-	p.client.Start()
-	return nil
-}
-
-func (p *defaultProducer) Shutdown() error {
-	atomic.StoreInt32(&p.state, int32(internal.StateShutdown))
-	p.client.UnregisterProducer(p.group)
-	p.client.Shutdown()
-	return nil
-}
-
-func (p *defaultProducer) checkMsg(msgs ...*primitive.Message) error {
-	if atomic.LoadInt32(&p.state) != int32(internal.StateRunning) {
-		return errors2.ErrNotRunning
-	}
-
-	if len(msgs) == 0 {
-		return errors2.ErrMessageEmpty
-	}
-
-	if len(msgs[0].Topic) == 0 {
-		return errors2.ErrTopicEmpty
-	}
-
-	topic := msgs[0].Topic
-	for _, msg := range msgs {
-		if msg.Topic != topic {
-			return errors2.ErrMultipleTopics
-		}
-	}
-
-	return nil
-}
-
-func (p *defaultProducer) encodeBatch(msgs ...*primitive.Message) *primitive.Message {
-	if len(msgs) == 1 {
-		return msgs[0]
-	}
-
-	// encode batch
-	batch := new(primitive.Message)
-	batch.Topic = msgs[0].Topic
-	batch.Queue = msgs[0].Queue
-	if len(msgs) > 1 {
-		batch.Body = MarshalMessageBatch(msgs...)
-		batch.Batch = true
-	} else {
-		batch.Body = msgs[0].Body
-		batch.Flag = msgs[0].Flag
-		batch.WithProperties(msgs[0].GetProperties())
-		batch.TransactionId = msgs[0].TransactionId
-	}
-	return batch
-}
-
-func MarshalMessageBatch(msgs ...*primitive.Message) []byte {
-	buffer := bytes.NewBufferString("")
-	for _, msg := range msgs {
-		data := msg.Marshal()
-		buffer.Write(data)
-	}
-	return buffer.Bytes()
-}
-
-func (p *defaultProducer) SendSync(ctx context.Context, msgs ...*primitive.Message) (*primitive.SendResult, error) {
-	if err := p.checkMsg(msgs...); err != nil {
-		return nil, err
-	}
-
-	p.messagesWithNamespace(msgs...)
-
-	msg := p.encodeBatch(msgs...)
-
-	resp := primitive.NewSendResult()
-	if p.interceptor != nil {
-		primitive.WithMethod(ctx, primitive.SendSync)
-		producerCtx := &primitive.ProducerCtx{
-			ProducerGroup:     p.group,
-			CommunicationMode: primitive.SendSync,
-			BornHost:          utils.LocalIP,
-			Message:           *msg,
-			SendResult:        resp,
-		}
-		ctx = primitive.WithProducerCtx(ctx, producerCtx)
-
-		err := p.interceptor(ctx, msg, resp, func(ctx context.Context, req, reply interface{}) error {
-			var err error
-			realReq := req.(*primitive.Message)
-			realReply := reply.(*primitive.SendResult)
-			err = p.sendSync(ctx, realReq, realReply)
-			return err
-		})
-		return resp, err
-	}
-
-	err := p.sendSync(ctx, msg, resp)
-	return resp, err
-}
-
-func (p *defaultProducer) sendSync(ctx context.Context, msg *primitive.Message, resp *primitive.SendResult) error {
-
-	retryTime := 1 + p.options.RetryTimes
-
-	var (
-		err error
-	)
-
-	var producerCtx *primitive.ProducerCtx
-	for retryCount := 0; retryCount < retryTime; retryCount++ {
-		mq := p.selectMessageQueue(msg)
-		if mq == nil {
-			err = fmt.Errorf("the topic=%s route info not found", msg.Topic)
-			continue
-		}
-
-		addr := p.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-		if addr == "" {
-			return fmt.Errorf("topic=%s route info not found", mq.Topic)
-		}
-
-		if p.interceptor != nil {
-			producerCtx = primitive.GetProducerCtx(ctx)
-			producerCtx.BrokerAddr = addr
-			producerCtx.MQ = *mq
-		}
-
-		res, _err := p.client.InvokeSync(ctx, addr, p.buildSendRequest(mq, msg), 3*time.Second)
-		if _err != nil {
-			err = _err
-			continue
-		}
-		return p.client.ProcessSendResponse(mq.BrokerName, res, resp, msg)
-	}
-	return err
-}
-
-func (p *defaultProducer) SendAsync(ctx context.Context, f func(context.Context, *primitive.SendResult, error), msgs ...*primitive.Message) error {
-	if err := p.checkMsg(msgs...); err != nil {
-		return err
-	}
-
-	p.messagesWithNamespace(msgs...)
-
-	msg := p.encodeBatch(msgs...)
-
-	if p.interceptor != nil {
-		primitive.WithMethod(ctx, primitive.SendAsync)
-
-		return p.interceptor(ctx, msg, nil, func(ctx context.Context, req, reply interface{}) error {
-			return p.sendAsync(ctx, msg, f)
-		})
-	}
-	return p.sendAsync(ctx, msg, f)
-}
-
-func (p *defaultProducer) sendAsync(ctx context.Context, msg *primitive.Message, h func(context.Context, *primitive.SendResult, error)) error {
-
-	mq := p.selectMessageQueue(msg)
-	if mq == nil {
-		return errors.Errorf("the topic=%s route info not found", msg.Topic)
-	}
-
-	addr := p.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-	if addr == "" {
-		return errors.Errorf("topic=%s route info not found", mq.Topic)
-	}
-
-	ctx, _ = context.WithTimeout(ctx, 3*time.Second)
-	return p.client.InvokeAsync(ctx, addr, p.buildSendRequest(mq, msg), func(command *remote.RemotingCommand, err error) {
-		resp := primitive.NewSendResult()
-		if err != nil {
-			h(ctx, nil, err)
-		} else {
-			p.client.ProcessSendResponse(mq.BrokerName, command, resp, msg)
-			h(ctx, resp, nil)
-		}
-	})
-}
-
-func (p *defaultProducer) SendOneWay(ctx context.Context, msgs ...*primitive.Message) error {
-	if err := p.checkMsg(msgs...); err != nil {
-		return err
-	}
-
-	p.messagesWithNamespace(msgs...)
-
-	msg := p.encodeBatch(msgs...)
-
-	if p.interceptor != nil {
-		primitive.WithMethod(ctx, primitive.SendOneway)
-		return p.interceptor(ctx, msg, nil, func(ctx context.Context, req, reply interface{}) error {
-			return p.SendOneWay(ctx, msg)
-		})
-	}
-
-	return p.sendOneWay(ctx, msg)
-}
-
-func (p *defaultProducer) sendOneWay(ctx context.Context, msg *primitive.Message) error {
-	retryTime := 1 + p.options.RetryTimes
-
-	var err error
-	for retryCount := 0; retryCount < retryTime; retryCount++ {
-		mq := p.selectMessageQueue(msg)
-		if mq == nil {
-			err = fmt.Errorf("the topic=%s route info not found", msg.Topic)
-			continue
-		}
-
-		addr := p.client.GetNameSrv().FindBrokerAddrByName(mq.BrokerName)
-		if addr == "" {
-			return fmt.Errorf("topic=%s route info not found", mq.Topic)
-		}
-
-		_err := p.client.InvokeOneWay(ctx, addr, p.buildSendRequest(mq, msg), 3*time.Second)
-		if _err != nil {
-			err = _err
-			continue
-		}
-		return nil
-	}
-	return err
-}
-
-func (p *defaultProducer) messagesWithNamespace(msgs ...*primitive.Message) {
-
-	if p.options.Namespace == "" {
-		return
-	}
-
-	for _, msg := range msgs {
-		msg.Topic = p.options.Namespace + "%" + msg.Topic
-	}
-}
-
-func (p *defaultProducer) tryCompressMsg(msg *primitive.Message) bool {
-	if msg.Compress {
-		return true
-	}
-	if msg.Batch {
-		return false
-	}
-	if len(msg.Body) < p.options.CompressMsgBodyOverHowmuch {
-		return false
-	}
-	compressedBody, e := utils.Compress(msg.Body, p.options.CompressLevel)
-	if e != nil {
-		return false
-	}
-	msg.Body = compressedBody
-	msg.Compress = true
-	return true
-}
-
-func (p *defaultProducer) buildSendRequest(mq *primitive.MessageQueue,
-	msg *primitive.Message) *remote.RemotingCommand {
-	if !msg.Batch && msg.GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex) == "" {
-		msg.WithProperty(primitive.PropertyUniqueClientMessageIdKeyIndex, primitive.CreateUniqID())
-	}
-	sysFlag := 0
-	if p.tryCompressMsg(msg) {
-		sysFlag = primitive.SetCompressedFlag(sysFlag)
-	}
-	v := msg.GetProperty(primitive.PropertyTransactionPrepared)
-	if v != "" {
-		tranMsg, err := strconv.ParseBool(v)
-		if err == nil && tranMsg {
-			sysFlag |= primitive.TransactionPreparedType
-		}
-	}
-
-	req := &internal.SendMessageRequestHeader{
-		ProducerGroup:  p.group,
-		Topic:          mq.Topic,
-		QueueId:        mq.QueueId,
-		SysFlag:        sysFlag,
-		BornTimestamp:  time.Now().UnixNano() / int64(time.Millisecond),
-		Flag:           msg.Flag,
-		Properties:     msg.MarshallProperties(),
-		ReconsumeTimes: 0,
-		UnitMode:       p.options.UnitMode,
-		Batch:          msg.Batch,
-	}
-	cmd := internal.ReqSendMessage
-	if msg.Batch {
-		cmd = internal.ReqSendBatchMessage
-		reqv2 := &internal.SendMessageRequestV2Header{SendMessageRequestHeader: req}
-		return remote.NewRemotingCommand(cmd, reqv2, msg.Body)
-	}
-
-	return remote.NewRemotingCommand(cmd, req, msg.Body)
-}
-
-func (p *defaultProducer) selectMessageQueue(msg *primitive.Message) *primitive.MessageQueue {
-	topic := msg.Topic
-
-	v, exist := p.publishInfo.Load(topic)
-	if !exist {
-		data, changed, err := p.client.GetNameSrv().UpdateTopicRouteInfo(topic)
-		if err != nil && primitive.IsRemotingErr(err) {
-			return nil
-		}
-		p.client.UpdatePublishInfo(topic, data, changed)
-		v, exist = p.publishInfo.Load(topic)
-	}
-
-	if !exist {
-		data, changed, _ := p.client.GetNameSrv().UpdateTopicRouteInfoWithDefault(topic, p.options.CreateTopicKey, p.options.DefaultTopicQueueNums)
-		p.client.UpdatePublishInfo(topic, data, changed)
-		v, exist = p.publishInfo.Load(topic)
-	}
-
-	if !exist {
-		return nil
-	}
-
-	result := v.(*internal.TopicPublishInfo)
-	if result == nil || !result.HaveTopicRouterInfo {
-		return nil
-	}
-
-	if len(result.MqList) <= 0 {
-		rlog.Error("can not find proper message queue", nil)
-		return nil
-	}
-
-	return p.options.Selector.Select(msg, result.MqList)
-}
-
-func (p *defaultProducer) PublishTopicList() []string {
-	topics := make([]string, 0)
-	p.publishInfo.Range(func(key, value interface{}) bool {
-		topics = append(topics, key.(string))
-		return true
-	})
-	return topics
-}
-
-func (p *defaultProducer) UpdateTopicPublishInfo(topic string, info *internal.TopicPublishInfo) {
-	if topic == "" || info == nil {
-		return
-	}
-	p.publishInfo.Store(topic, info)
-}
-
-func (p *defaultProducer) IsPublishTopicNeedUpdate(topic string) bool {
-	v, exist := p.publishInfo.Load(topic)
-	if !exist {
-		return true
-	}
-	info := v.(*internal.TopicPublishInfo)
-	return info.MqList == nil || len(info.MqList) == 0
-}
-
-func (p *defaultProducer) IsUnitMode() bool {
-	return false
-}
-
-type transactionProducer struct {
-	producer *defaultProducer
-	listener primitive.TransactionListener
-}
-
-// TODO: checkLocalTransaction
-func NewTransactionProducer(listener primitive.TransactionListener, opts ...Option) (*transactionProducer, error) {
-	producer, err := NewDefaultProducer(opts...)
-	if err != nil {
-		return nil, errors.Wrap(err, "NewDefaultProducer failed.")
-	}
-	return &transactionProducer{
-		producer: producer,
-		listener: listener,
-	}, nil
-}
-
-func (tp *transactionProducer) Start() error {
-	go primitive.WithRecover(func() {
-		tp.checkTransactionState()
-	})
-	return tp.producer.Start()
-}
-func (tp *transactionProducer) Shutdown() error {
-	return tp.producer.Shutdown()
-}
-
-// TODO: check addr
-func (tp *transactionProducer) checkTransactionState() {
-	for ch := range tp.producer.callbackCh {
-		switch callback := ch.(type) {
-		case *internal.CheckTransactionStateCallback:
-			localTransactionState := tp.listener.CheckLocalTransaction(callback.Msg)
-			uniqueKey := callback.Msg.GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex)
-			if uniqueKey == "" {
-				uniqueKey = callback.Msg.MsgId
-			}
-			transactionId := callback.Msg.GetProperty(primitive.PropertyTransactionID)
-			if transactionId == "" {
-				transactionId = callback.Header.TransactionId
-			}
-			if transactionId == "" {
-				transactionId = callback.Msg.TransactionId
-			}
-			header := &internal.EndTransactionRequestHeader{
-				CommitLogOffset:      callback.Header.CommitLogOffset,
-				ProducerGroup:        tp.producer.group,
-				TranStateTableOffset: callback.Header.TranStateTableOffset,
-				FromTransactionCheck: true,
-				MsgID:                uniqueKey,
-				TransactionId:        transactionId,
-				CommitOrRollback:     tp.transactionState(localTransactionState),
-			}
-
-			req := remote.NewRemotingCommand(internal.ReqENDTransaction, header, nil)
-			req.Remark = tp.errRemark(nil)
-
-			err := tp.producer.client.InvokeOneWay(context.Background(), callback.Addr.String(), req,
-				tp.producer.options.SendMsgTimeout)
-			if err != nil {
-				rlog.Error("send ReqENDTransaction to broker error", map[string]interface{}{
-					"callback":               callback.Addr.String(),
-					"request":                req.String(),
-					rlog.LogKeyUnderlayError: err,
-				})
-			}
-		default:
-			rlog.Error(fmt.Sprintf("unknown type %v", ch), nil)
-		}
-	}
-}
-
-func (tp *transactionProducer) SendMessageInTransaction(ctx context.Context, msg *primitive.Message) (*primitive.TransactionSendResult, error) {
-	msg.WithProperty(primitive.PropertyTransactionPrepared, "true")
-	msg.WithProperty(primitive.PropertyProducerGroup, tp.producer.options.GroupName)
-
-	rsp, err := tp.producer.SendSync(ctx, msg)
-	if err != nil {
-		return nil, err
-	}
-	localTransactionState := primitive.UnknowState
-	switch rsp.Status {
-	case primitive.SendOK:
-		if len(rsp.TransactionID) > 0 {
-			msg.WithProperty("__transactionId__", rsp.TransactionID)
-		}
-		transactionId := msg.GetProperty(primitive.PropertyUniqueClientMessageIdKeyIndex)
-		if len(transactionId) > 0 {
-			msg.TransactionId = transactionId
-		}
-		localTransactionState = tp.listener.ExecuteLocalTransaction(msg)
-		if localTransactionState != primitive.CommitMessageState {
-			rlog.Error("executeLocalTransaction but state unexpected", map[string]interface{}{
-				"localState": localTransactionState,
-				"message":    msg,
-			})
-		}
-
-	case primitive.SendFlushDiskTimeout, primitive.SendFlushSlaveTimeout, primitive.SendSlaveNotAvailable:
-		localTransactionState = primitive.RollbackMessageState
-	default:
-	}
-
-	tp.endTransaction(*rsp, err, localTransactionState)
-
-	transactionSendResult := &primitive.TransactionSendResult{
-		SendResult: rsp,
-		State:      localTransactionState,
-	}
-
-	return transactionSendResult, nil
-}
-
-func (tp *transactionProducer) endTransaction(result primitive.SendResult, err error, state primitive.LocalTransactionState) error {
-	var msgID *primitive.MessageID
-	if len(result.OffsetMsgID) > 0 {
-		msgID, _ = primitive.UnmarshalMsgID([]byte(result.OffsetMsgID))
-	} else {
-		msgID, _ = primitive.UnmarshalMsgID([]byte(result.MsgID))
-	}
-	// 估计没有反序列化回来
-	brokerAddr := tp.producer.client.GetNameSrv().FindBrokerAddrByName(result.MessageQueue.BrokerName)
-	requestHeader := &internal.EndTransactionRequestHeader{
-		TransactionId:        result.TransactionID,
-		CommitLogOffset:      msgID.Offset,
-		ProducerGroup:        tp.producer.group,
-		TranStateTableOffset: result.QueueOffset,
-		MsgID:                result.MsgID,
-		CommitOrRollback:     tp.transactionState(state),
-	}
-
-	req := remote.NewRemotingCommand(internal.ReqENDTransaction, requestHeader, nil)
-	req.Remark = tp.errRemark(err)
-
-	return tp.producer.client.InvokeOneWay(context.Background(), brokerAddr, req, tp.producer.options.SendMsgTimeout)
-}
-
-func (tp *transactionProducer) errRemark(err error) string {
-	if err != nil {
-		return "executeLocalTransactionBranch exception: " + err.Error()
-	}
-	return ""
-}
-
-func (tp *transactionProducer) transactionState(state primitive.LocalTransactionState) int {
-	switch state {
-	case primitive.CommitMessageState:
-		return primitive.TransactionCommitType
-	case primitive.RollbackMessageState:
-		return primitive.TransactionRollbackType
-	case primitive.UnknowState:
-		return primitive.TransactionNotType
-	default:
-		return primitive.TransactionNotType
-	}
-}
diff --git a/producer/producer_test.go b/producer/producer_test.go
deleted file mode 100644
index e1d72dd..0000000
--- a/producer/producer_test.go
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package producer
-
-import (
-	"context"
-	"github.com/apache/rocketmq-client-go/v2/errors"
-	"testing"
-
-	"github.com/golang/mock/gomock"
-	"github.com/stretchr/testify/assert"
-
-	"github.com/apache/rocketmq-client-go/v2/internal"
-	"github.com/apache/rocketmq-client-go/v2/internal/remote"
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-const (
-	topic          = "TopicTest"
-	namespaceTopic = "Test%TopicTest"
-)
-
-func TestShutdown(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	client.EXPECT().Shutdown().Return()
-	client.EXPECT().UnregisterProducer(gomock.Any()).Return()
-	err = p.Shutdown()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msg := new(primitive.Message)
-
-	r, err := p.SendSync(ctx, msg)
-	assert.Equal(t, errors.ErrNotRunning, err)
-	assert.Nil(t, r)
-
-	err = p.SendOneWay(ctx, msg)
-	assert.Equal(t, errors.ErrNotRunning, err)
-
-	f := func(context.Context, *primitive.SendResult, error) {
-		assert.False(t, true, "should not  come in")
-	}
-	err = p.SendAsync(ctx, f, msg)
-	assert.Equal(t, errors.ErrNotRunning, err)
-}
-
-func mockB4Send(p *defaultProducer) {
-	p.publishInfo.Store(topic, &internal.TopicPublishInfo{
-		HaveTopicRouterInfo: true,
-		MqList: []*primitive.MessageQueue{
-			{
-				Topic:      topic,
-				BrokerName: "aa",
-				QueueId:    0,
-			},
-		},
-	})
-	p.publishInfo.Store(namespaceTopic, &internal.TopicPublishInfo{
-		HaveTopicRouterInfo: true,
-		MqList: []*primitive.MessageQueue{
-			{
-				Topic:      namespaceTopic,
-				BrokerName: "aa",
-				QueueId:    0,
-			},
-		},
-	})
-	p.options.Namesrv.AddBroker(&internal.TopicRouteData{
-		BrokerDataList: []*internal.BrokerData{
-			{
-				Cluster:    "cluster",
-				BrokerName: "aa",
-				BrokerAddresses: map[int64]string{
-					0: "1",
-				},
-			},
-		},
-	})
-}
-
-func TestSync(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	namesrvCli := internal.NewMockNamesrvs(ctrl)
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-	client.SetNameSrv(namesrvCli)
-	namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return("a")
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msg := &primitive.Message{
-		Topic: topic,
-		Body:  []byte("this is a message body"),
-		Queue: &primitive.MessageQueue{
-			Topic:      topic,
-			BrokerName: "aa",
-			QueueId:    0,
-		},
-	}
-	msg.WithProperty("key", "value")
-
-	expectedResp := &primitive.SendResult{
-		Status:      primitive.SendOK,
-		MsgID:       "111",
-		QueueOffset: 0,
-		OffsetMsgID: "0",
-	}
-
-	mockB4Send(p)
-
-	client.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
-	client.EXPECT().ProcessSendResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(
-		func(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) {
-			resp.Status = expectedResp.Status
-			resp.MsgID = expectedResp.MsgID
-			resp.QueueOffset = expectedResp.QueueOffset
-			resp.OffsetMsgID = expectedResp.OffsetMsgID
-		})
-	resp, err := p.SendSync(ctx, msg)
-	assert.Nil(t, err)
-	assert.Equal(t, expectedResp, resp)
-}
-
-func TestASync(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	namesrvCli := internal.NewMockNamesrvs(ctrl)
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-	client.SetNameSrv(namesrvCli)
-	namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return("a")
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msg := &primitive.Message{
-		Topic: topic,
-		Body:  []byte("this is a message body"),
-		Queue: &primitive.MessageQueue{
-			Topic:      topic,
-			BrokerName: "aa",
-			QueueId:    0,
-		},
-	}
-	msg.WithProperty("key", "value")
-
-	expectedResp := &primitive.SendResult{
-		Status:      primitive.SendOK,
-		MsgID:       "111",
-		QueueOffset: 0,
-		OffsetMsgID: "0",
-	}
-
-	f := func(ctx context.Context, resp *primitive.SendResult, err error) {
-		assert.Nil(t, err)
-		assert.Equal(t, expectedResp, resp)
-	}
-
-	mockB4Send(p)
-
-	client.EXPECT().InvokeAsync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
-		func(ctx context.Context, addr string, request *remote.RemotingCommand,
-			f func(*remote.RemotingCommand, error)) error {
-			// mock invoke callback
-			f(nil, nil)
-			return nil
-		})
-	client.EXPECT().ProcessSendResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(
-		func(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) {
-			resp.Status = expectedResp.Status
-			resp.MsgID = expectedResp.MsgID
-			resp.QueueOffset = expectedResp.QueueOffset
-			resp.OffsetMsgID = expectedResp.OffsetMsgID
-		})
-
-	err = p.SendAsync(ctx, f, msg)
-	assert.Nil(t, err)
-}
-
-func TestOneway(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	namesrvCli := internal.NewMockNamesrvs(ctrl)
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-	client.SetNameSrv(namesrvCli)
-	namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return("a")
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msg := &primitive.Message{
-		Topic: topic,
-		Body:  []byte("this is a message body"),
-		Queue: &primitive.MessageQueue{
-			Topic:      topic,
-			BrokerName: "aa",
-			QueueId:    0,
-		},
-	}
-	msg.WithProperty("key", "value")
-
-	mockB4Send(p)
-
-	client.EXPECT().InvokeOneWay(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
-
-	err = p.SendOneWay(ctx, msg)
-	assert.Nil(t, err)
-}
-
-func TestSyncWithNamespace(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-		WithNamespace("Test"),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	namesrvCli := internal.NewMockNamesrvs(ctrl)
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-	client.SetNameSrv(namesrvCli)
-	namesrvCli.EXPECT().FindBrokerAddrByName(gomock.Any()).Return("a")
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msg := &primitive.Message{
-		Topic: topic,
-		Body:  []byte("this is a message body"),
-		Queue: &primitive.MessageQueue{
-			Topic:      namespaceTopic,
-			BrokerName: "aa",
-			QueueId:    0,
-		},
-	}
-	msg.WithProperty("key", "value")
-
-	expectedResp := &primitive.SendResult{
-		Status:      primitive.SendOK,
-		MsgID:       "111",
-		QueueOffset: 0,
-		OffsetMsgID: "0",
-	}
-
-	mockB4Send(p)
-
-	client.EXPECT().InvokeSync(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
-	client.EXPECT().ProcessSendResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(
-		func(brokerName string, cmd *remote.RemotingCommand, resp *primitive.SendResult, msgs ...*primitive.Message) {
-			resp.Status = expectedResp.Status
-			resp.MsgID = expectedResp.MsgID
-			resp.QueueOffset = expectedResp.QueueOffset
-			resp.OffsetMsgID = expectedResp.OffsetMsgID
-		})
-	resp, err := p.SendSync(ctx, msg)
-	assert.Nil(t, err)
-	assert.Equal(t, expectedResp, resp)
-	assert.Equal(t, namespaceTopic, msg.Topic)
-}
-
-func TestBatchSendDifferentTopics(t *testing.T) {
-	p, _ := NewDefaultProducer(
-		WithNsResolver(primitive.NewPassthroughResolver([]string{"127.0.0.1:9876"})),
-		WithRetry(2),
-		WithQueueSelector(NewManualQueueSelector()),
-	)
-
-	ctrl := gomock.NewController(t)
-	defer ctrl.Finish()
-	client := internal.NewMockRMQClient(ctrl)
-	p.client = client
-
-	client.EXPECT().RegisterProducer(gomock.Any(), gomock.Any()).Return(nil)
-	client.EXPECT().Start().Return()
-	err := p.Start()
-	assert.Nil(t, err)
-
-	ctx := context.Background()
-	msgToA := &primitive.Message{
-		Topic: "topic-A",
-		Body:  []byte("this is a message body"),
-	}
-
-	msgToB := &primitive.Message{
-		Topic: "topic-B",
-		Body:  []byte("this is a message body"),
-	}
-
-	resp, err := p.SendSync(ctx, []*primitive.Message{msgToA, msgToB}...)
-	assert.Nil(t, resp)
-	assert.NotNil(t, err)
-	assert.Equal(t, err, errors.ErrMultipleTopics)
-}
diff --git a/producer/selector.go b/producer/selector.go
deleted file mode 100644
index 74f5bad..0000000
--- a/producer/selector.go
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package producer
-
-import (
-	"hash/fnv"
-	"math/rand"
-	"sync"
-	"time"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-type QueueSelector interface {
-	Select(*primitive.Message, []*primitive.MessageQueue) *primitive.MessageQueue
-}
-
-// manualQueueSelector use the queue manually set in the provided Message's QueueID  field as the queue to send.
-type manualQueueSelector struct{}
-
-func NewManualQueueSelector() QueueSelector {
-	return new(manualQueueSelector)
-}
-
-func (manualQueueSelector) Select(message *primitive.Message, queues []*primitive.MessageQueue) *primitive.MessageQueue {
-	return message.Queue
-}
-
-// randomQueueSelector choose a random queue each time.
-type randomQueueSelector struct {
-	mux    sync.Mutex
-	rander *rand.Rand
-}
-
-func NewRandomQueueSelector() QueueSelector {
-	s := new(randomQueueSelector)
-	s.rander = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
-	return s
-}
-
-func (r *randomQueueSelector) Select(message *primitive.Message, queues []*primitive.MessageQueue) *primitive.MessageQueue {
-	r.mux.Lock()
-	i := r.rander.Intn(len(queues))
-	r.mux.Unlock()
-	return queues[i]
-}
-
-// roundRobinQueueSelector choose the queue by roundRobin.
-type roundRobinQueueSelector struct {
-	sync.Locker
-	indexer map[string]*uint32
-}
-
-func NewRoundRobinQueueSelector() QueueSelector {
-	s := &roundRobinQueueSelector{
-		Locker:  new(sync.Mutex),
-		indexer: map[string]*uint32{},
-	}
-	return s
-}
-
-func (r *roundRobinQueueSelector) Select(message *primitive.Message, queues []*primitive.MessageQueue) *primitive.MessageQueue {
-	t := message.Topic
-	var idx *uint32
-
-	r.Lock()
-	idx, exist := r.indexer[t]
-	if !exist {
-		var v uint32 = 0
-		idx = &v
-		r.indexer[t] = idx
-	}
-	*idx++
-	r.Unlock()
-
-	qIndex := *idx % uint32(len(queues))
-	return queues[qIndex]
-}
-
-type hashQueueSelector struct {
-	random QueueSelector
-}
-
-func NewHashQueueSelector() QueueSelector {
-	return &hashQueueSelector{
-		random: NewRandomQueueSelector(),
-	}
-}
-
-// hashQueueSelector choose the queue by hash if message having sharding key, otherwise choose queue by random instead.
-func (h *hashQueueSelector) Select(message *primitive.Message, queues []*primitive.MessageQueue) *primitive.MessageQueue {
-	key := message.GetShardingKey()
-	if len(key) == 0 {
-		return h.random.Select(message, queues)
-	}
-
-	hasher := fnv.New32a()
-	_, err := hasher.Write([]byte(key))
-	if err != nil {
-		return nil
-	}
-	queueId := int(hasher.Sum32()) % len(queues)
-	if queueId < 0 {
-		queueId = -queueId
-	}
-	return queues[queueId]
-}
diff --git a/producer/selector_test.go b/producer/selector_test.go
deleted file mode 100644
index 72dc469..0000000
--- a/producer/selector_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package producer
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/apache/rocketmq-client-go/v2/primitive"
-)
-
-func TestRoundRobin(t *testing.T) {
-	queues := make([]*primitive.MessageQueue, 10)
-	for i := 0; i < 10; i++ {
-		queues = append(queues, &primitive.MessageQueue{
-			QueueId: i,
-		})
-	}
-	s := NewRoundRobinQueueSelector()
-
-	m := &primitive.Message{
-		Topic: "test",
-	}
-	mrr := &primitive.Message{
-		Topic: "rr",
-	}
-	for i := 0; i < 100; i++ {
-		q := s.Select(m, queues)
-		expected := (i + 1) % len(queues)
-		assert.Equal(t, queues[expected], q, "i: %d", i)
-
-		qrr := s.Select(mrr, queues)
-		expected = (i + 1) % len(queues)
-		assert.Equal(t, queues[expected], qrr, "i: %d", i)
-	}
-}
-
-func TestHashQueueSelector(t *testing.T) {
-	queues := make([]*primitive.MessageQueue, 10)
-	for i := 0; i < 10; i++ {
-		queues = append(queues, &primitive.MessageQueue{
-			QueueId: i,
-		})
-	}
-
-	s := NewHashQueueSelector()
-
-	m1 := &primitive.Message{
-		Topic: "test",
-		Body:  []byte("one message"),
-	}
-	m1.WithShardingKey("same_key")
-	q1 := s.Select(m1, queues)
-
-	m2 := &primitive.Message{
-		Topic: "test",
-		Body:  []byte("another message"),
-	}
-	m2.WithShardingKey("same_key")
-	q2 := s.Select(m2, queues)
-	assert.Equal(t, *q1, *q2)
-}
diff --git a/rlog/log.go b/rlog/log.go
deleted file mode 100644
index a179a40..0000000
--- a/rlog/log.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package rlog
-
-import (
-	"os"
-	"strings"
-
-	"github.com/sirupsen/logrus"
-)
-
-const (
-	LogKeyProducerGroup    = "producerGroup"
-	LogKeyConsumerGroup    = "consumerGroup"
-	LogKeyTopic            = "topic"
-	LogKeyMessageQueue     = "MessageQueue"
-	LogKeyUnderlayError    = "underlayError"
-	LogKeyBroker           = "broker"
-	LogKeyValueChangedFrom = "changedFrom"
-	LogKeyValueChangedTo   = "changeTo"
-	LogKeyPullRequest      = "PullRequest"
-	LogKeyTimeStamp        = "timestamp"
-)
-
-type Logger interface {
-	Debug(msg string, fields map[string]interface{})
-	Info(msg string, fields map[string]interface{})
-	Warning(msg string, fields map[string]interface{})
-	Error(msg string, fields map[string]interface{})
-	Fatal(msg string, fields map[string]interface{})
-	Level(level string)
-	OutputPath(path string) (err error)
-}
-
-func init() {
-	r := &defaultLogger{
-		logger: logrus.New(),
-	}
-	level := os.Getenv("ROCKETMQ_GO_LOG_LEVEL")
-	switch strings.ToLower(level) {
-	case "debug":
-		r.logger.SetLevel(logrus.DebugLevel)
-	case "warn":
-		r.logger.SetLevel(logrus.WarnLevel)
-	case "error":
-		r.logger.SetLevel(logrus.ErrorLevel)
-	case "fatal":
-		r.logger.SetLevel(logrus.FatalLevel)
-	default:
-		r.logger.SetLevel(logrus.InfoLevel)
-	}
-	rLog = r
-}
-
-var rLog Logger
-
-type defaultLogger struct {
-	logger *logrus.Logger
-}
-
-func (l *defaultLogger) Debug(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	l.logger.WithFields(fields).Debug(msg)
-}
-
-func (l *defaultLogger) Info(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	l.logger.WithFields(fields).Info(msg)
-}
-
-func (l *defaultLogger) Warning(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	l.logger.WithFields(fields).Warning(msg)
-}
-
-func (l *defaultLogger) Error(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	l.logger.WithFields(fields).Error(msg)
-}
-
-func (l *defaultLogger) Fatal(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	l.logger.WithFields(fields).Fatal(msg)
-}
-
-func (l *defaultLogger) Level(level string) {
-	switch strings.ToLower(level) {
-	case "debug":
-		l.logger.SetLevel(logrus.DebugLevel)
-	case "warn":
-		l.logger.SetLevel(logrus.WarnLevel)
-	case "error":
-		l.logger.SetLevel(logrus.ErrorLevel)
-	case "fatal":
-		l.logger.SetLevel(logrus.FatalLevel)
-	default:
-		l.logger.SetLevel(logrus.InfoLevel)
-	}
-}
-
-func (l *defaultLogger) OutputPath(path string) (err error) {
-	var file *os.File
-	file, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
-	if err != nil {
-		return
-	}
-
-	l.logger.Out = file
-	return
-}
-
-// SetLogger use specified logger user customized, in general, we suggest user to replace the default logger with specified
-func SetLogger(logger Logger) {
-	rLog = logger
-}
-func SetLogLevel(level string) {
-	if level == "" {
-		return
-	}
-	rLog.Level(level)
-}
-
-func SetOutputPath(path string) (err error) {
-	if "" == path {
-		return
-	}
-
-	return rLog.OutputPath(path)
-}
-
-func Debug(msg string, fields map[string]interface{}) {
-	rLog.Debug(msg, fields)
-}
-
-func Info(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	rLog.Info(msg, fields)
-}
-
-func Warning(msg string, fields map[string]interface{}) {
-	if msg == "" && len(fields) == 0 {
-		return
-	}
-	rLog.Warning(msg, fields)
-}
-
-func Error(msg string, fields map[string]interface{}) {
-	rLog.Error(msg, fields)
-}
-
-func Fatal(msg string, fields map[string]interface{}) {
-	rLog.Fatal(msg, fields)
-}