You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by di...@apache.org on 2022/04/11 02:50:46 UTC

[rocketmq-client-go] 01/01: init new empty branch feature.

This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch feature
in repository https://gitbox.apache.org/repos/asf/rocketmq-client-go.git

commit 4999236ed73d5972fd23b1f766503aa1d9608717
Author: ShannonDing <li...@163.com>
AuthorDate: Mon Apr 11 10:50:15 2022 +0800

    init new empty branch feature.
---
 admin/admin.go                             |  210 -----
 admin/option.go                            |  131 ---
 api.go                                     |  137 ---
 benchmark/consumer.go                      |  277 ------
 benchmark/main.go                          |   76 --
 benchmark/message.go                       |   34 -
 benchmark/producer.go                      |  290 -------
 benchmark/stable.go                        |  280 -------
 config.go                                  |   17 -
 consumer/consumer.go                       | 1063 -----------------------
 consumer/consumer_test.go                  |  171 ----
 consumer/interceptor.go                    |  115 ---
 consumer/lock.go                           |   37 -
 consumer/mock_offset_store.go              |   94 ---
 consumer/offset_store.go                   |  402 ---------
 consumer/offset_store_test.go              |  243 ------
 consumer/option.go                         |  276 ------
 consumer/process_queue.go                  |  397 ---------
 consumer/pull_consumer.go                  |  256 ------
 consumer/pull_consumer_test.go             |   18 -
 consumer/push_consumer.go                  | 1254 ----------------------------
 consumer/push_consumer_test.go             |   96 ---
 consumer/statistics.go                     |  485 -----------
 consumer/statistics_test.go                |  214 -----
 consumer/strategy.go                       |  247 ------
 consumer/strategy_test.go                  |  487 -----------
 docs/Introduction.md                       |  130 ---
 docs/client-design.gliffy                  |    1 -
 docs/feature.md                            |   86 --
 docs/images/client-design.png              |  Bin 30513 -> 0 bytes
 docs/zh/native-design_zh.md                |  114 ---
 docs/zh/rocketmq-protocol_zh.md            |  117 ---
 errors/errors.go                           |   51 --
 examples/admin/topic/main.go               |   64 --
 examples/consumer/acl/main.go              |   64 --
 examples/consumer/broadcast/main.go        |   57 --
 examples/consumer/delay/main.go            |   60 --
 examples/consumer/interceptor/main.go      |   83 --
 examples/consumer/namespace/main.go        |   65 --
 examples/consumer/orderly/main.go          |   60 --
 examples/consumer/pull/main.go             |   72 --
 examples/consumer/retry/concurrent/main.go |   81 --
 examples/consumer/retry/order/main.go      |   76 --
 examples/consumer/simple/main.go           |   58 --
 examples/consumer/strategy/main.go         |   56 --
 examples/consumer/tag/main.go              |   58 --
 examples/consumer/trace/main.go            |   63 --
 examples/producer/acl/main.go              |   65 --
 examples/producer/async/main.go            |   65 --
 examples/producer/batch/main.go            |   58 --
 examples/producer/delay/main.go            |   55 --
 examples/producer/interceptor/main.go      |   74 --
 examples/producer/namespace/main.go        |   66 --
 examples/producer/simple/main.go           |   61 --
 examples/producer/tag/main.go              |   58 --
 examples/producer/trace/main.go            |   64 --
 examples/producer/transaction/main.go      |  106 ---
 go.mod                                     |   17 -
 go.sum                                     |   63 --
 internal/callback.go                       |   31 -
 internal/client.go                         |  893 --------------------
 internal/constants.go                      |   29 -
 internal/mock_client.go                    |  430 ----------
 internal/mock_namesrv.go                   |  193 -----
 internal/model.go                          |  406 ---------
 internal/model_test.go                     |  484 -----------
 internal/mq_version.go                     |   22 -
 internal/namesrv.go                        |  185 ----
 internal/namesrv_test.go                   |  149 ----
 internal/perm.go                           |   58 --
 internal/remote/codec.go                   |  521 ------------
 internal/remote/codec_test.go              |  378 ---------
 internal/remote/future.go                  |   68 --
 internal/remote/interceptor.go             |   83 --
 internal/remote/interceptor_test.go        |   29 -
 internal/remote/mock_remote_client.go      |  123 ---
 internal/remote/remote_client.go           |  316 -------
 internal/remote/remote_client_test.go      |  372 ---------
 internal/remote/rpchook.go                 |   23 -
 internal/remote/tcp_conn.go                |   61 --
 internal/request.go                        |  480 -----------
 internal/response.go                       |   49 --
 internal/route.go                          |  668 ---------------
 internal/route_test.go                     |  137 ---
 internal/trace.go                          |  526 ------------
 internal/trace_test.go                     |  125 ---
 internal/transaction.go                    |   21 -
 internal/utils/compression.go              |   86 --
 internal/utils/compression_test.go         |   97 ---
 internal/utils/errors.go                   |   30 -
 internal/utils/files.go                    |   89 --
 internal/utils/math.go                     |   32 -
 internal/utils/net.go                      |   70 --
 internal/utils/net_test.go                 |   24 -
 internal/utils/set.go                      |  103 ---
 internal/utils/string.go                   |   30 -
 internal/validators.go                     |   43 -
 primitive/auth.go                          |   28 -
 primitive/base.go                          |  129 ---
 primitive/base_test.go                     |   76 --
 primitive/ctx.go                           |  173 ----
 primitive/errors.go                        |   61 --
 primitive/interceptor.go                   |   51 --
 primitive/message.go                       |  569 -------------
 primitive/message_test.go                  |   38 -
 primitive/nsresolver.go                    |  223 -----
 primitive/nsresolver_test.go               |  136 ---
 primitive/pool.go                          |   57 --
 primitive/result.go                        |  128 ---
 primitive/result_test.go                   |   74 --
 primitive/trace.go                         |   28 -
 producer/interceptor.go                    |  103 ---
 producer/option.go                         |  164 ----
 producer/producer.go                       |  602 -------------
 producer/producer_test.go                  |  358 --------
 producer/selector.go                       |  122 ---
 producer/selector_test.go                  |   78 --
 rlog/log.go                                |  180 ----
 118 files changed, 20317 deletions(-)

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=\ [...]
\ 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
Binary files a/docs/images/client-design.png and /dev/null 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 @@
... 11153 lines suppressed ...