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 2020/05/09 09:04:33 UTC

[rocketmq-client-cpp] branch re_dev updated: feat: support Request-Reply. (#299)

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

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


The following commit(s) were added to refs/heads/re_dev by this push:
     new 11bf396  feat: support Request-Reply. (#299)
11bf396 is described below

commit 11bf3963c17de5c8ae82a8c8e3453bef8481b960
Author: James Yin <yw...@hotmail.com>
AuthorDate: Sat May 9 17:04:22 2020 +0800

    feat: support Request-Reply. (#299)
    
    * rename for Camel-Case.
    
    * remove useless code.
    
    * access MQClientConfig by Proxy.
    
    * aliasing std::shared_ptr<RPCHook> by RPCHookPtr.
    
    * expose "DataBlock.h" in include directory.
    
    * polish C api.
    
    * polish std::shared_ptr.
    
    * polish std::map.
    
    * polish MQException.
    
    * fixed typo.
    
    * polish SocketUtil.
    
    * feat: support Request-Reply.
    
    * pullTimeDelayMillsWhenException in PushConsumer
    
    * polish sockaddr.
    
    * polish network callback api.
    
    * polish MQProtos.h
    
    * fixed submitConsumeRequestLater.
    
    * polish ServiceState variable.
    
    * polish MQClientAPIImpl.
    
    * polish MQMessageListener
    
    * polish MQClientInstance
    
    * include missing header
    
    * use platform-independent type by cstdint
    
    * polish cmake script files.
    
    * fixed struct sockaddr
    
    * fixed missing header
    
    * update build.sh
    
    * fast return when select mq.
    
    * polish TopicPublishInfo.
    
    * fixed regex in Validatoors
    
    * polish pull message when slave no latest msg.
    
    * gcc 4.8 have regex bug.
    
    * polish TcpTransport
    
    * polish findConsumerIds
    
    * fixed memory leak in concurrent lib
    
    * polish BufferEvent
    
    * change log
    
    * fixed MQDecoder::createMessageId
    
    * update unit test
    
    * add coverage to CMakeLists.txt
    
    * polish TcpRemotingClient::CreateTransport
    
    * fixed TcpTransport
    
    * update CMakeLists.txt
    
    * update clang-format scripts
---
 .travis.yml                                        |   4 +-
 .travis/check-git-clang-format.sh                  |  11 +-
 CMakeLists.txt                                     | 179 +++---
 build.sh                                           | 137 ++---
 cmake/BundleStaticLibrary.cmake                    |   2 +-
 cmake/FindJsoncpp.cmake                            |  59 +-
 cmake/FindLibevent.cmake                           |  26 +-
 example/AsyncProducer.cpp                          |   2 +-
 example/BatchProducer.cpp                          |   2 +-
 example/CMakeLists.txt                             |  26 +-
 example/OrderlyProducer.cpp                        |   2 +-
 example/PullConsumer.cpp                           |   2 +-
 example/PushConsumer.cpp                           |   2 +-
 example/RequestReply.cpp                           | 114 ++++
 example/SyncProducer.cpp                           |   2 +-
 example/TransactionProducer.cpp                    |   2 +-
 example/common.h                                   |   2 +-
 format.sh                                          |  53 +-
 {src/common => include}/DataBlock.h                |  18 +-
 include/DefaultMQProducer.h                        |  67 +--
 include/DefaultMQProducerConfig.h                  |  65 +++
 include/DefaultMQProducerConfigProxy.h             |  80 +++
 include/DefaultMQPullConsumer.h                    |  18 +-
 ...tMQConsumer.h => DefaultMQPullConsumerConfig.h} |  22 +-
 include/DefaultMQPullConsumerConfigProxy.h         |  48 ++
 include/DefaultMQPushConsumer.h                    |  74 +--
 include/DefaultMQPushConsumerConfig.h              |  76 +++
 include/DefaultMQPushConsumerConfigProxy.h         |  96 ++++
 include/MQClientConfig.h                           |  71 +--
 include/MQClientConfigProxy.h                      |  73 +++
 include/MQClientException.h                        | 101 ++--
 include/MQMessage.h                                |   1 +
 include/MQMessageConst.h                           |   7 +
 include/MQMessageExt.h                             |  17 +-
 include/MQMessageListener.h                        |  24 +-
 include/MQMessageQueue.h                           |   2 +
 include/MQProducer.h                               |   3 +
 include/MQPushConsumer.h                           |   2 +
 include/{DefaultMQConsumer.h => MessageUtil.h}     |  23 +-
 include/PullResult.h                               |  11 +-
 include/RemotingCommand.h                          |  12 +-
 include/{SendCallback.h => RequestCallback.h}      |  27 +-
 include/RocketMQClient.h                           |  24 -
 include/SendCallback.h                             |   4 +-
 include/SessionCredentials.h                       |   6 +
 include/TransactionMQProducer.h                    |  23 +-
 ...tMQConsumer.h => TransactionMQProducerConfig.h} |  25 +-
 include/c/CMessage.h                               |   1 -
 include/c/CMessageExt.h                            |   1 -
 include/c/CProducer.h                              |  13 +-
 include/c/CPushConsumer.h                          |   5 +-
 package_rocketmq.mri                               |  22 -
 project/CMakeLists.txt                             |  25 +-
 src/ClientRemotingProcessor.cpp                    | 187 ++++---
 src/ClientRemotingProcessor.h                      |  21 +-
 src/MQAdminImpl.cpp                                |  42 +-
 src/MQAdminImpl.h                                  |   6 +-
 src/MQClientAPIImpl.cpp                            | 104 ++--
 src/MQClientAPIImpl.h                              |  19 +-
 src/{MQClientConfig.cpp => MQClientConfigImpl.cpp} |  50 +-
 src/MQClientConfigImpl.h                           |  70 +++
 src/MQClientImpl.cpp                               |  32 +-
 src/MQClientImpl.h                                 |  18 +-
 src/MQClientInstance.cpp                           | 244 +++++----
 src/MQClientInstance.h                             |  21 +-
 src/MQClientManager.cpp                            |  16 +-
 src/MQClientManager.h                              |   4 +-
 .../common/ClientErrorCode.h                       |  25 +-
 src/common/ClientRPCHook.cpp                       |  19 +-
 src/common/DataBlock.cpp                           |   2 +-
 src/common/InputStream.cpp                         |   4 +-
 src/common/InputStream.h                           |  10 +-
 src/common/MQVersion.cpp                           |   4 +-
 src/common/MQVersion.h                             | 606 +--------------------
 src/common/MemoryInputStream.h                     |   9 +-
 src/common/MemoryOutputStream.cpp                  |   6 +-
 src/common/MemoryOutputStream.h                    |  11 +-
 src/common/NamesrvConfig.h                         |  14 +-
 src/common/OutputStream.cpp                        |   2 +-
 src/common/OutputStream.h                          |  11 +-
 src/common/SendCallbackWrap.cpp                    |  10 +-
 src/common/SubscriptionData.h                      |   8 +-
 src/common/TopicConfig.cpp                         |   2 +-
 src/common/UtilAll.cpp                             |   8 +-
 src/common/UtilAll.h                               |   4 +
 src/common/Validators.cpp                          |  32 +-
 src/concurrent/concurrent_queue.hpp                |  15 +-
 src/concurrent/executor.hpp                        |   2 +-
 src/concurrent/executor_impl.hpp                   |   9 +-
 src/consumer/AllocateMQAveragely.h                 |   7 +-
 src/consumer/ConsumeMessageConcurrentlyService.cpp | 109 ++--
 src/consumer/ConsumeMessageOrderlyService.cpp      |   4 +-
 src/consumer/DefaultMQPullConsumer.cpp             |   8 +-
 src/consumer/DefaultMQPullConsumerImpl.cpp         |   5 +-
 src/consumer/DefaultMQPushConsumer.cpp             |  27 +-
 src/consumer/DefaultMQPushConsumerConfigImpl.cpp   | 125 +++++
 src/consumer/DefaultMQPushConsumerConfigImpl.h     |  81 +++
 src/consumer/DefaultMQPushConsumerImpl.cpp         |  41 +-
 src/consumer/DefaultMQPushConsumerImpl.h           |  12 +-
 src/consumer/MessageQueueLock.hpp                  |   8 +-
 src/consumer/OffsetStore.cpp                       |  25 +-
 src/consumer/ProcessQueue.cpp                      |   9 +-
 src/consumer/PullAPIWrapper.cpp                    |   9 +-
 ...PullMessageService.h => PullMessageService.hpp} |   9 +-
 src/consumer/PullResult.cpp                        |  12 +
 src/consumer/PullResultExt.h                       |   2 +-
 src/consumer/RebalanceImpl.cpp                     |  39 +-
 src/consumer/RebalanceImpl.h                       |   4 +-
 src/consumer/RebalancePushImpl.cpp                 |   2 +-
 src/consumer/SubscriptionData.cpp                  |   2 +-
 src/extern/CBatchMessage.cpp                       |  14 +-
 src/extern/CMessage.cpp                            |  64 ++-
 src/extern/CMessageExt.cpp                         |  30 +-
 src/extern/CProducer.cpp                           | 240 +++++---
 src/extern/CPullConsumer.cpp                       |   4 +-
 src/extern/CPushConsumer.cpp                       |  84 +--
 src/message/MQDecoder.cpp                          |  26 +-
 src/message/MQDecoder.h                            |   3 +-
 src/message/MQMessage.cpp                          |  16 +-
 src/message/MQMessageExt.cpp                       |  49 +-
 src/message/MQMessageId.h                          |  14 +-
 src/message/MessageUtil.cpp                        |  60 ++
 .../CorrelationIdUtil.hpp}                         |  20 +-
 src/producer/DefaultMQProducer.cpp                 |  34 +-
 src/producer/DefaultMQProducerConfigImpl.cpp       |  88 +++
 src/producer/DefaultMQProducerConfigImpl.h         |  63 +++
 src/producer/DefaultMQProducerImpl.cpp             | 130 ++++-
 src/producer/DefaultMQProducerImpl.h               |  16 +-
 src/producer/LatencyFaultTolerancyImpl.cpp         |   2 +-
 src/producer/MQFaultStrategy.cpp                   |   6 +-
 src/producer/MQFaultStrategy.h                     |   2 +-
 .../RequestFutureTable.cpp}                        |  27 +-
 .../producer/RequestFutureTable.h                  |  26 +-
 src/producer/RequestResponseFuture.cpp             | 104 ++++
 src/producer/RequestResponseFuture.h               |  60 ++
 src/producer/TopicPublishInfo.h                    |  53 +-
 src/producer/TransactionMQProducer.cpp             |  29 +-
 .../TransactionMQProducerConfigImpl.cpp}           |  20 +-
 .../producer/TransactionMQProducerConfigImpl.h     |  22 +-
 src/protocol/MQProtos.h                            | 180 +-----
 src/protocol/ProcessQueueInfo.h                    |   1 -
 src/protocol/RemotingCommand.cpp                   |  37 +-
 src/protocol/RemotingSerializable.cpp              |   1 +
 src/protocol/{MQProtos.h => RequestCode.h}         | 147 ++---
 src/protocol/ResponseCode.h                        |  74 +++
 src/protocol/TopicRouteData.h                      |  27 +-
 src/protocol/{ => body}/LockBatchBody.cpp          |   0
 src/protocol/{ => body}/LockBatchBody.h            |   0
 .../body/ResetOffsetBody.cpp}                      |  34 +-
 .../body/ResetOffsetBody.h}                        |  21 +-
 src/protocol/{ => header}/CommandHeader.cpp        |  38 +-
 src/protocol/{ => header}/CommandHeader.h          |  10 +-
 src/protocol/header/ReplyMessageRequestHeader.cpp  | 175 ++++++
 src/protocol/header/ReplyMessageRequestHeader.h    |  92 ++++
 src/transport/EventLoop.cpp                        | 124 ++---
 src/transport/EventLoop.h                          |  42 +-
 src/transport/RequestProcessor.h                   |   3 +-
 src/transport/ResponseFuture.cpp                   |   4 +-
 src/transport/ResponseFuture.h                     |   8 +-
 src/transport/SocketUtil.cpp                       | 156 +++---
 src/transport/SocketUtil.h                         |  13 +-
 src/transport/TcpRemotingClient.cpp                | 382 +++++++------
 src/transport/TcpRemotingClient.h                  |  37 +-
 src/transport/TcpTransport.cpp                     | 137 +++--
 src/transport/TcpTransport.h                       |  53 +-
 test/CMakeLists.txt                                | 125 +++--
 test/src/BatchMessageTest.cpp                      |  72 ---
 test/src/common/BigEndianTest.cpp                  |  85 +++
 test/src/common/ClientRPCHookTest.cpp              |  33 +-
 test/src/common/MemoryBlockTest.cpp                | 150 +++--
 test/src/common/MemoryOutputStreamTest.cpp         | 111 ++--
 test/src/common/NamesrvConfigTest.cpp              |  21 +-
 .../common/{PermNametTest.cpp => PermNameTest.cpp} |  15 +-
 test/src/common/PullSysFlagTest.cpp                |  15 +-
 test/src/common/TopicConfigTest.cpp                |  26 +-
 test/src/common/ValidatorsTest.cpp                 |  55 +-
 test/src/common/VirtualEnvUtilTest.cpp             |  31 +-
 test/src/common/big_endianTest.cpp                 | 100 ----
 test/src/extern/CMessageExtTest.cpp                |  26 +-
 test/src/extern/CMessageTest.cpp                   |  34 +-
 test/src/extern/CProducerTest.cpp                  |  86 ++-
 test/src/extern/CPullConsumerTest.cpp              |  71 +--
 test/src/extern/CPushConsumerTest.cpp              | 104 ++--
 test/src/message/MQDecoderTest.cpp                 | 224 ++++----
 test/src/message/MQMessageExtTest.cpp              | 159 +++---
 test/src/message/MQMessageIdTest.cpp               |  40 +-
 test/src/message/MQMessageQueueTest.cpp            |  58 +-
 test/src/message/MQMessageTest.cpp                 |  85 ++-
 test/src/message/MessageBatchTest.cpp              |  62 +++
 .../MessageClientIDSetterTest.cpp}                 |  28 +-
 test/src/protocol/CommandHeaderTest.cpp            | 131 ++---
 test/src/protocol/ConsumerRunningInfoTest.cpp      |  35 +-
 test/src/protocol/HeartbeatDataTest.cpp            |  25 +-
 test/src/protocol/KVTableTest.cpp                  |  26 +-
 test/src/protocol/LockBatchBodyTest.cpp            |  61 +--
 test/src/protocol/MessageQueueTest.cpp             |  71 +--
 test/src/protocol/ProcessQueueInfoTest.cpp         |  19 +-
 test/src/protocol/RemotingCommandTest.cpp          | 170 ++----
 test/src/protocol/TopicRouteDataTest.cpp           |  40 +-
 test/src/transport/ClientRemotingProcessorTest.cpp | 336 ++++++------
 test/src/transport/ResponseFutureTest.cpp          | 105 ++--
 test/src/transport/SocketUtilTest.cpp              |  34 +-
 202 files changed, 5209 insertions(+), 4663 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 237b2a4..75ac46b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -52,8 +52,8 @@ matrix:
       dist: trusty
       env: LINT=1 PYTHON=2.7
       before_install:
-        - sudo apt-get update -qq
-        - sudo apt-get install -qq clang-format-3.8
+        - sudo apt-get update
+        - sudo apt-get install -y clang-format-3.8
       install: []
       script:
         - sudo sh .travis/check-git-clang-format.sh
diff --git a/.travis/check-git-clang-format.sh b/.travis/check-git-clang-format.sh
index b8d3d1f..8416fa3 100644
--- a/.travis/check-git-clang-format.sh
+++ b/.travis/check-git-clang-format.sh
@@ -1,3 +1,6 @@
+#!/usr/bin/env bash
+
+# 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
@@ -12,17 +15,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#!/bin/bash
-
- if [ "$TRAVIS_PULL_REQUEST" = "true" ]; then
+if [ "$TRAVIS_PULL_REQUEST" = "true" ]; then
     base_commit="$TRAVIS_BRANCH"
 else
     base_commit="HEAD^"
 fi
 
- output="$(sudo python .travis/git-clang-format --binary clang-format-3.8 --commit $base_commit --diff)"
+output="$(python .travis/git-clang-format --binary clang-format-3.8 --commit $base_commit --diff --style file)"
 
- if [ "$output" = "no modified files to format" ] || [ "$output" = "clang-format did not modify any files" ]; then
+if [ "$output" = "no modified files to format" ] || [ "$output" = "clang-format did not modify any files" ]; then
     echo "clang-format passed."
     exit 0
 else
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 49e6a4d..e39910e 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,10 +15,6 @@
 
 cmake_minimum_required(VERSION 2.8)
 
-if (APPLE)
-    set(CMAKE_MACOSX_RPATH 1)
-endif (APPLE)
-
 # CMake complains if we don't have this.
 if (COMMAND cmake_policy)
     cmake_policy(SET CMP0003 NEW)
@@ -34,103 +30,99 @@ endif ()
 
 # First, declare project (important for prerequisite checks).
 project(rocketmq-client-cpp)
+
 if (NOT CMAKE_BUILD_TYPE)
     set(CMAKE_BUILD_TYPE "Release")
 endif ()
 if (NOT CMAKE_CONFIGURATION_TYPES)
     set(CMAKE_CONFIGURATION_TYPES "Release")
 endif ()
+
 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
+
 set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
 set(CMAKE_VERBOSE_MAKEFILE 1)
 
-option(BUILD_ROCKETMQ_STATIC "build rocketmq-client static library" OFF)
-option(BUILD_ROCKETMQ_SHARED "build rocketmq-client shared library" ON)
+if (APPLE)
+    set(CMAKE_MACOSX_RPATH 1)
+endif (APPLE)
+
+# put binaries in a different dir to make them easier to find.
+set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
+set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
 
-# Find dependency
+# Find dependencies
 #find_package(spdlog REQUIRED)
+if (NOT spdlog_FOUND)
+    include_directories(${CMAKE_SOURCE_DIR}/bin/include)
+endif ()
 
 option(Libevent_USE_STATIC_LIBS "only find libevent static libs" OFF) # only find static libs
+if (NOT LIBEVENT_ROOT)
+    set(LIBEVENT_ROOT ${CMAKE_SOURCE_DIR}/bin)
+endif ()
 find_package(Libevent 2.0.21 REQUIRED)
-include_directories(${LIBEVENT_INCLUDE_DIRS})
 message(STATUS "** LIBEVENT_INCLUDE_DIR: ${LIBEVENT_INCLUDE_DIR}")
 message(STATUS "** LIBEVENT_LIBRARIES: ${LIBEVENT_LIBRARIES}")
 
 option(JSONCPP_USE_STATIC_LIBS "only find jsoncpp static libs" OFF) # only find static libs
+if (NOT JSONCPP_ROOT)
+    set(JSONCPP_ROOT ${CMAKE_SOURCE_DIR}/bin)
+endif ()
 find_package(Jsoncpp 0.10.6 REQUIRED)
-include_directories(${JSONCPP_INCLUDE_DIRS})
 message(STATUS "** JSONCPP_INCLUDE_DIRS: ${JSONCPP_INCLUDE_DIRS}")
 message(STATUS "** JSONCPP_LIBRARIES: ${JSONCPP_LIBRARIES}")
 
-# put binaries in a different dir to make them easier to find.
-set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
-set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
-
-# for unix, put debug files in a separate bin "debug" dir.
-# release bin files should stay in the root of the bin dir.
-# if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
-#     if (CMAKE_BUILD_TYPE STREQUAL Debug)
-#         set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/debug)
-#         set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/debug)
-#     endif()
-# endif()
+# Set compile options
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+CHECK_C_COMPILER_FLAG("-std=c99" COMPILER_SUPPORTS_C99)
+CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+if (COMPILER_SUPPORTS_C99 AND COMPILER_SUPPORTS_CXX11)
+    if (NOT (CMAKE_VERSION VERSION_LESS "3.1"))
+        set(CMAKE_C_STANDARD 99)
+        set(CMAKE_CXX_STANDARD 11)
+        message(STATUS "** set CMAKE_C_STANDARD to 99")
+        message(STATUS "** set CMAKE_CXX_STANDARD to 11")
+    else ()
+        if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+            set(C_STANDARD_FLAG "-std=gnu99")
+            set(CXX_STANDARD_FLAG "-std=gnu++11")
+        else ()
+            set(C_STANDARD_FLAG "-std=c99")
+            set(CXX_STANDARD_FLAG "-std=c++11")
+        endif ()
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_STANDARD_FLAG}")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD_FLAG}")
+        message(STATUS "** set CMAKE_C_FLAGS with ${C_STANDARD_FLAG}")
+        message(STATUS "** set CMAKE_CXX_FLAGS with ${CXX_STANDARD_FLAG}")
+    endif ()
+else ()
+    message(FATAL_ERROR "The compiler has no C99 or C++11 support.")
+endif ()
 
-IF (WIN32)
+if (WIN32)
     add_definitions(-DWIN32 -DROCKETMQCLIENT_EXPORTS)
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
-    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
-    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
-ELSE ()
-    set(C_FLAGS
-            -Wall
-            -Wno-deprecated
-            -fPIC
-            -fno-strict-aliasing
-            )
-    set(CXX_FLAGS
-            -Wall
-            -Wno-deprecated
-            -fPIC
-            -fno-strict-aliasing
-            -std=c++11
-            -Wno-unused-local-typedef
-            -Wno-expansion-to-defined
-            # -finline-limit=1000
-            # -Wextra
-            # -pedantic
-            # -pedantic-errors
-            # -D_FILE_OFFSET_BITS=64
-            # -DVALGRIND
-            # -DCHECK_PTHREAD_RETURN_VALUE
-            # -Werror
-            # -Wconversion
-            # -Wno-unused-parameter
-            # -Wunused-but-set-variable
-            # -Wold-style-cast
-            # -Woverloaded-virtual
-            # -Wpointer-arith
-            # -Wshadow
-            # -Wwrite-strings
-            # -Wdeprecated-declarations
-            # -march=native
-            # -MMD
-            # -std=c++0x
-            # -rdynamic
-            )
+    add_compile_options(/EHsc)
+    if (CMAKE_BUILD_TYPE EQUAL "Release")
+        add_compile_options(/MT)
+    else ()
+        add_compile_options(/MTd)
+    endif ()
+else ()
+    add_compile_options(-Wall
+        -Wno-deprecated
+        -fPIC
+        -fno-strict-aliasing
+        -Wno-unused-local-typedef
+        -Wno-expansion-to-defined)
 
     if (CMAKE_BUILD_BITS EQUAL 32)
-        list(APPEND CXX_FLAGS "-m32")
+        add_compile_options(-m32)
     else () #not-condition
-        list(APPEND CXX_FLAGS "-m64")
+        add_compile_options(-m64)
     endif ()
 
-    string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}")
-    string(REPLACE ";" " " CMAKE_C_FLAGS "${C_FLAGS}")
-
-    set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG")
-    set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
-
-
     # Declare deplibs, so we can use list in linker later. There's probably
     # a more elegant way of doing this; with SCons, when you check for the
     # lib, it is automatically passed to the linker.
@@ -146,40 +138,35 @@ ELSE ()
     endif ()
     list(APPEND deplibs z)
 
+    option(CODE_COVERAGE "Enable coverage reporting" OFF)
+    if (CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+        # Add required flags (GCC & LLVM/Clang)
+        # Code Coverage Configuration
+        add_library(coverage_config INTERFACE)
+        target_compile_options(coverage_config INTERFACE
+                -O0        # no optimization
+                -g         # generate debug info
+                --coverage # sets all required flags
+                )
+        if (NOT (CMAKE_VERSION VERSION_LESS "3.13"))
+            target_link_options(coverage_config INTERFACE --coverage)
+        else ()
+            target_link_libraries(coverage_config INTERFACE --coverage)
+        endif ()
+        list(APPEND deplibs coverage_config)
+    endif (CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+
     # add include dir for bsd (posix uses /usr/include/)
     set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH}:/usr/local/include")
-ENDIF ()
-
-# For config.h, set some static values; it may be a good idea to make
-# these values dynamic for non-standard UNIX compilers.
-set(ACCEPT_TYPE_ARG3 socklen_t)
-set(HAVE_CXX_BOOL 1)
-set(HAVE_CXX_CASTS 1)
-set(HAVE_CXX_EXCEPTIONS 1)
-set(HAVE_CXX_MUTABLE 1)
-set(HAVE_CXX_STDLIB 1)
-set(HAVE_PTHREAD_SIGNAL 1)
-set(SELECT_TYPE_ARG1 int)
-set(SELECT_TYPE_ARG234 "(fd_set *)")
-set(SELECT_TYPE_ARG5 "(struct timeval *)")
-set(STDC_HEADERS 1)
-set(TIME_WITH_SYS_TIME 1)
-set(HAVE_SOCKLEN_T 1)
-
-# For config.h, save the results based on a template (config.h.in).
-# configure_file(res/config.h.in ${root_dir}/config.h)
-
-# add_definitions(-DSYSAPI_UNIX=1 -DHAVE_CONFIG_H)
+endif ()
 
 add_subdirectory(libs)
 add_subdirectory(project)
 add_subdirectory(example)
 
-
 option(RUN_UNIT_TEST "RUN_UNIT_TEST" OFF)
-
 if (RUN_UNIT_TEST)
     message(STATUS "** RUN_UNIT_TEST: Do execution testing")
+    enable_testing()
     add_subdirectory(test)
 endif ()
-
diff --git a/build.sh b/build.sh
index 6b0407e..ee1cbfa 100755
--- a/build.sh
+++ b/build.sh
@@ -15,6 +15,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+set -e
+
 basepath=$(
   cd $(dirname $0)
   pwd
@@ -23,24 +25,24 @@ down_dir="${basepath}/tmp_down_dir"
 build_dir="${basepath}/tmp_build_dir"
 packet_dir="${basepath}/tmp_packet_dir"
 install_lib_dir="${basepath}/bin"
+fname_spdlog="spdlog*.zip"
 fname_libevent="libevent*.zip"
 fname_jsoncpp="jsoncpp*.zip"
-fname_boost="boost*.tar.gz"
+fname_spdlog_down="v1.5.0.zip"
 fname_libevent_down="release-2.1.11-stable.zip"
 fname_jsoncpp_down="0.10.6.zip"
-fname_boost_down="1.58.0/boost_1_58_0.tar.gz"
 
 PrintParams() {
   echo "=========================================one key build help============================================"
-  echo "sh build.sh [no build libevent:noEvent] [no build json:noJson] [no build boost:noBoost] [ execution test:test]"
-  echo "usage: sh build.sh noJson noEvent noBoost test"
+  echo "sh build.sh [no build spdlog:noLog] [no build libevent:noEvent] [no build json:noJson] [ execution test:test]"
+  echo "usage: sh build.sh noLog noJson noEvent test"
   echo "=========================================one key build help============================================"
   echo ""
 }
 
+need_build_spdlog=1
 need_build_jsoncpp=1
 need_build_libevent=1
-need_build_boost=1
 test=0
 verbose=1
 codecov=0
@@ -49,15 +51,15 @@ cpu_num=4
 pasres_arguments() {
   for var in "$@"; do
     case "$var" in
+    noLog)
+      need_build_spdlog=0
+      ;;
     noJson)
       need_build_jsoncpp=0
       ;;
     noEvent)
       need_build_libevent=0
       ;;
-    noBoost)
-      need_build_boost=0
-      ;;
     noVerbose)
       verbose=0
       ;;
@@ -75,6 +77,13 @@ pasres_arguments $@
 
 PrintParams() {
   echo "###########################################################################"
+
+  if [ $need_build_spdlog -eq 0 ]; then
+    echo "no need build spdlog lib"
+  else
+    echo "need build spdlog lib"
+  fi
+
   if [ $need_build_libevent -eq 0 ]; then
     echo "no need build libevent lib"
   else
@@ -87,19 +96,16 @@ PrintParams() {
     echo "need build jsoncpp lib"
   fi
 
-  if [ $need_build_boost -eq 0 ]; then
-    echo "no need build boost lib"
-  else
-    echo "need build boost lib"
-  fi
   if [ $test -eq 1 ]; then
     echo "build unit tests"
   else
     echo "without build unit tests"
   fi
+
   if [ $codecov -eq 1 ]; then
     echo "run unit tests with code coverage"
   fi
+
   if [ $verbose -eq 0 ]; then
     echo "no need print detail logs"
   else
@@ -113,13 +119,16 @@ PrintParams() {
 Prepare() {
   if [ -e ${down_dir} ]; then
     echo "${down_dir} is exist"
-    #cd ${down_dir}
-    #ls |grep -v ${fname_libevent} |grep -v ${fname_jsoncpp} | grep -v ${fname_boost} |xargs rm -rf
   else
     mkdir -p ${down_dir}
   fi
 
   cd ${basepath}
+
+  if [ -e ${fname_spdlog} ]; then
+    mv -f ${basepath}/${fname_spdlog} ${down_dir}
+  fi
+
   if [ -e ${fname_libevent} ]; then
     mv -f ${basepath}/${fname_libevent} ${down_dir}
   fi
@@ -128,20 +137,14 @@ Prepare() {
     mv -f ${basepath}/${fname_jsoncpp} ${down_dir}
   fi
 
-  if [ -e ${fname_boost} ]; then
-    mv -f ${basepath}/${fname_boost} ${down_dir}
-  fi
-
   if [ -e ${build_dir} ]; then
     echo "${build_dir} is exist"
-    #rm -rf ${build_dir}/*
   else
     mkdir -p ${build_dir}
   fi
 
   if [ -e ${packet_dir} ]; then
     echo "${packet_dir} is exist"
-    #rm -rf ${packet_dir}/*
   else
     mkdir -p ${packet_dir}
   fi
@@ -153,6 +156,30 @@ Prepare() {
   fi
 }
 
+BuildSpdlog() {
+  if [ $need_build_spdlog -eq 0 ]; then
+    echo "no need build spdlog lib"
+    return 0
+  fi
+
+  cd ${down_dir}
+  if [ -e ${fname_spdlog} ]; then
+    echo "${fname_spdlog} is exist"
+  else
+    wget https://github.com/gabime/spdlog/archive/${fname_spdlog_down} -O spdlog-${fname_spdlog_down}
+  fi
+  unzip -o ${fname_spdlog} >unzipspdlog.txt 2>&1
+  if [ $? -ne 0 ]; then
+    exit 1
+  fi
+
+  spdlog_dir=$(ls | grep spdlog | grep .*[^zip]$)
+  cd ${spdlog_dir}
+  cp -r include ${install_lib_dir}
+
+  echo "build spdlog success."
+}
+
 BuildLibevent() {
   if [ $need_build_libevent -eq 0 ]; then
     echo "no need build libevent lib"
@@ -198,7 +225,7 @@ BuildLibevent() {
     exit 1
   fi
   make install
-  echo "build linevent success."
+  echo "build libevent success."
 }
 
 BuildJsonCPP() {
@@ -251,51 +278,16 @@ BuildJsonCPP() {
   fi
 }
 
-BuildBoost() {
-  if [ $need_build_boost -eq 0 ]; then
-    echo "no need build boost lib"
-    return 0
-  fi
-
-  cd ${down_dir}
-  if [ -e ${fname_boost} ]; then
-    echo "${fname_boost} is exist"
-  else
-    wget http://sourceforge.net/projects/boost/files/boost/${fname_boost_down}
-  fi
-  tar -zxvf ${fname_boost} >unzipboost.txt 2>&1
-  boost_dir=$(ls | grep boost | grep .*[^gz]$)
-  cd ${boost_dir}
-  if [ $? -ne 0 ]; then
-    exit 1
-  fi
-  ./bootstrap.sh
-  if [ $? -ne 0 ]; then
-    exit 1
-  fi
-  echo "build boost static #####################"
-  pwd
-  if [ $verbose -eq 0 ]; then
-    echo "build boost without detail log."
-    ./b2 -j$cpu_num cflags=-fPIC cxxflags=-fPIC --with-atomic --with-thread --with-system --with-chrono --with-date_time --with-log --with-regex --with-serialization --with-filesystem --with-locale --with-iostreams threading=multi link=static release install --prefix=${install_lib_dir} >boostbuild.txt 2>&1
-  else
-    ./b2 -j$cpu_num cflags=-fPIC cxxflags=-fPIC --with-atomic --with-thread --with-system --with-chrono --with-date_time --with-log --with-regex --with-serialization --with-filesystem --with-locale --with-iostreams threading=multi link=static release install --prefix=${install_lib_dir}
-  fi
-  if [ $? -ne 0 ]; then
-    exit 1
-  fi
-}
-
 BuildRocketMQClient() {
   cd ${build_dir}
   echo "============start to build rocketmq client cpp.========="
   if [ $test -eq 0 ]; then
-    cmake ..
+    cmake -DLibevent_USE_STATIC_LIBS=ON -DJSONCPP_USE_STATIC_LIBS=ON -DBUILD_ROCKETMQ_STATIC=ON -DBUILD_ROCKETMQ_SHARED=OFF ..
   else
     if [ $codecov -eq 1 ]; then
-      cmake .. -DRUN_UNIT_TEST=ON -DCODE_COVERAGE=ON
+      cmake .. -DLibevent_USE_STATIC_LIBS=ON -DJSONCPP_USE_STATIC_LIBS=ON -DBUILD_ROCKETMQ_STATIC=ON -DBUILD_ROCKETMQ_SHARED=OFF -DRUN_UNIT_TEST=ON -DCODE_COVERAGE=ON
     else
-      cmake .. -DRUN_UNIT_TEST=ON
+      cmake .. -DLibevent_USE_STATIC_LIBS=ON -DJSONCPP_USE_STATIC_LIBS=ON -DBUILD_ROCKETMQ_STATIC=ON -DBUILD_ROCKETMQ_SHARED=OFF -DRUN_UNIT_TEST=ON
     fi
   fi
   if [ $verbose -eq 0 ]; then
@@ -309,7 +301,6 @@ BuildRocketMQClient() {
     exit 1
   fi
   #sudo make install
-  PackageRocketMQStatic
 }
 
 BuildGoogleTest() {
@@ -319,20 +310,20 @@ BuildGoogleTest() {
   fi
 
   if [ -f ./bin/lib/libgtest.a ]; then
-    echo "libgteest already exist no need build test"
+    echo "libgtest already exist no need build test"
     return 0
   fi
 
   cd ${down_dir}
-  if [ -e release-1.8.1.tar.gz ]; then
+  if [ -e release-1.10.0.tar.gz ]; then
     echo "${fname_boost} is exist"
   else
-    wget https://github.com/abseil/googletest/archive/release-1.8.1.tar.gz
+    wget https://github.com/abseil/googletest/archive/release-1.10.0.tar.gz
   fi
-  if [ ! -d "googletest-release-1.8.1" ]; then
-    tar -zxvf release-1.8.1.tar.gz >googletest.txt 2>&1
+  if [ ! -d "googletest-release-1.10.0" ]; then
+    tar -zxvf release-1.10.0.tar.gz >googletest.txt 2>&1
   fi
-  cd googletest-release-1.8.1
+  cd googletest-release-1.10.0
   mkdir build
   cd build
   echo "build googletest static #####################"
@@ -380,21 +371,11 @@ ExecutionTesting() {
   echo "############# unit test  finish  ###########"
 }
 
-PackageRocketMQStatic() {
-  if test "$(uname)" = "Linux"; then
-    echo "package static library."
-    #packet libevent,jsoncpp,boost,rocketmq,Signature to one librocketmq.a
-    cp -f ${basepath}/libs/signature/lib/libSignature.a ${install_lib_dir}/lib
-    ar -M <${basepath}/package_rocketmq.mri
-    cp -f librocketmq.a ${install_lib_dir}
-  fi
-}
-
 PrintParams
 Prepare
+BuildSpdlog
 BuildLibevent
 BuildJsonCPP
-BuildBoost
 BuildGoogleTest
 BuildRocketMQClient
 ExecutionTesting
diff --git a/cmake/BundleStaticLibrary.cmake b/cmake/BundleStaticLibrary.cmake
index 4ab9a24..782eec4 100644
--- a/cmake/BundleStaticLibrary.cmake
+++ b/cmake/BundleStaticLibrary.cmake
@@ -16,7 +16,7 @@
 # ref: https://cristianadam.eu/20190501/bundling-together-static-libraries-with-cmake/
 
 set(STATIC_LIBRARY_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
-string(REPLACE ".", "\\.", STATIC_LIBRARY_REGEX ${STATIC_LIBRARY_REGEX})
+string(REPLACE "." "\\." STATIC_LIBRARY_REGEX "${STATIC_LIBRARY_REGEX}")
 set(STATIC_LIBRARY_REGEX "^.+${STATIC_LIBRARY_REGEX}$")
 
 function(bundle_static_library tgt_name bundled_tgt_name)
diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake
index cdef2b1..4625ccf 100755
--- a/cmake/FindJsoncpp.cmake
+++ b/cmake/FindJsoncpp.cmake
@@ -17,17 +17,17 @@
 #
 # Find the jsoncpp includes and library
 #
-# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
+# if you nee to add a custom library search path, do it via CMAKE_PREFIX_PATH
 #
 # -*- cmake -*-
 # - Find JSONCpp
 # Find the JSONCpp includes and library
-# This module defines
+#
+# This module define the following variables:
+#
+#  JSONCPP_FOUND, If false, do not try to use jsoncpp.
 #  JSONCPP_INCLUDE_DIRS, where to find json.h, etc.
 #  JSONCPP_LIBRARIES, the libraries needed to use jsoncpp.
-#  JSONCPP_FOUND, If false, do not try to use jsoncpp.
-#  also defined, but not for general use are
-#  JSONCPP_LIBRARIES, where to find the jsoncpp library.
 
 # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
 if (JSONCPP_USE_STATIC_LIBS)
@@ -48,13 +48,11 @@ else ()
     endif ()
 endif ()
 
-set(JSONCPP_INCLUDE_SEARCH_PATH ${CMAKE_SOURCE_DIR}/bin/include /usr/local/include C:/jsoncpp/include
-        ${CMAKE_SOURCE_DIR}/win32-deps/include C:/jsoncpp-0.10.6/include)
-set(JSONCPP_LIBRARIE_SEARCH_PATH ${CMAKE_SOURCE_DIR}/bin/lib /usr/local/lib C:/jsoncpp/lib
-        ${CMAKE_SOURCE_DIR}/win32-deps/lib C:/jsoncpp-0.10.6/)
+set(JSONCPP_INCLUDE_SEARCH_PATH /usr/local/include /usr/include)
+set(JSONCPP_LIBRARIES_SEARCH_PATH /usr/local/lib /usr/lib)
 if (JSONCPP_ROOT)
     list(INSERT JSONCPP_INCLUDE_SEARCH_PATH 0 ${JSONCPP_ROOT}/include)
-    list(INSERT JSONCPP_LIBRARIE_SEARCH_PATH 0 ${JSONCPP_ROOT}/lib)
+    list(INSERT JSONCPP_LIBRARIES_SEARCH_PATH 0 ${JSONCPP_ROOT}/lib)
 endif ()
 
 find_path(JSONCPP_INCLUDE_DIRS
@@ -64,34 +62,25 @@ find_path(JSONCPP_INCLUDE_DIRS
 
 find_library(JSONCPP_LIBRARIES
         NAMES jsoncpp
-        PATHS ${JSONCPP_LIBRARIE_SEARCH_PATH})
-
-IF (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
-    SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARIES})
-    SET(JSONCPP_FOUND "YES")
-ELSE (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
-    SET(JSONCPP_FOUND "NO")
-ENDIF (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
-
+        PATHS ${JSONCPP_LIBRARIES_SEARCH_PATH})
 
-IF (JSONCPP_FOUND)
-    IF (NOT JSONCPP_FIND_QUIETLY)
-        MESSAGE(STATUS "Found JSONCpp: ${JSONCPP_LIBRARIES}")
-    ENDIF (NOT JSONCPP_FIND_QUIETLY)
-ELSE (JSONCPP_FOUND)
-    IF (JSONCPP_FIND_REQUIRED)
-        MESSAGE(FATAL_ERROR "Could not find JSONCPP library include: ${JSONCPP_INCLUDE_DIRS}, lib: ${JSONCPP_LIBRARIES}")
-    ENDIF (JSONCPP_FIND_REQUIRED)
-ENDIF (JSONCPP_FOUND)
+if (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
+    set(JSONCPP_FOUND "YES")
+else (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
+    set(JSONCPP_FOUND "NO")
+endif (JSONCPP_LIBRARIES AND JSONCPP_INCLUDE_DIRS)
 
-# Deprecated declarations.
-SET(NATIVE_JSONCPP_INCLUDE_PATH ${JSONCPP_INCLUDE_DIRS})
-GET_FILENAME_COMPONENT(NATIVE_JSONCPP_LIB_PATH ${JSONCPP_LIBRARIES} PATH)
+if (JSONCPP_FOUND)
+    if (NOT JSONCPP_FIND_QUIETLY)
+        message(STATUS "Found JSONCpp: ${JSONCPP_LIBRARIES}")
+    endif (NOT JSONCPP_FIND_QUIETLY)
+else (JSONCPP_FOUND)
+    if (JSONCPP_FIND_REQUIRED)
+        message(FATAL_ERROR "Could not find JSONCPP library, include: ${JSONCPP_INCLUDE_DIRS}, lib: ${JSONCPP_LIBRARIES}")
+    endif (JSONCPP_FIND_REQUIRED)
+endif (JSONCPP_FOUND)
 
-MARK_AS_ADVANCED(
-        JSONCPP_LIBRARIES
-        JSONCPP_INCLUDE_DIRS
-)
+mark_as_advanced(JSONCPP_LIBRARIES JSONCPP_INCLUDE_DIRS)
 
 # Restore the original find library ordering
 if (JSONCPP_USE_STATIC_LIBS)
diff --git a/cmake/FindLibevent.cmake b/cmake/FindLibevent.cmake
index 0165e70..1b4ab65 100755
--- a/cmake/FindLibevent.cmake
+++ b/cmake/FindLibevent.cmake
@@ -29,7 +29,7 @@
 # Note that 'libevent' contains both core and extra. You must specify one of
 # them for the other components.
 #
-# This module will define the following variables::
+# This module will define the following variables:
 #
 #  LIBEVENT_FOUND        - True if headers and requested libraries were found
 #  LIBEVENT_INCLUDE_DIRS - Libevent include directories
@@ -59,18 +59,16 @@ else ()
     endif ()
 endif ()
 
-set(LIBEVENT_INCLUDE_SEARCH_PATH ${CMAKE_SOURCE_DIR}/bin/include /usr/local/include C:/libevent/include
-        ${CMAKE_SOURCE_DIR}/win32-deps/include)
-set(LIBEVENT_LIBRARIE_SEARCH_PATH ${CMAKE_SOURCE_DIR}/bin/lib /usr/local/lib C:/libevent-2.0.22-stable
-        C:/libevent-2.0.22-stable/lib C:/libevent/lib ${CMAKE_SOURCE_DIR}/win32-deps/lib)
+set(LIBEVENT_INCLUDE_SEARCH_PATH /usr/local/include /usr/include)
+set(LIBEVENT_LIBRARIES_SEARCH_PATH /usr/local/lib /usr/lib)
 if (LIBEVENT_ROOT)
-    list(INSERT LIBEVENT_INCLUDE_SEARCH_PATH 0 ${JSONCPP_ROOT}/include)
-    list(INSERT LIBEVENT_LIBRARIE_SEARCH_PATH 0 ${JSONCPP_ROOT}/lib)
+    list(INSERT LIBEVENT_INCLUDE_SEARCH_PATH 0 ${LIBEVENT_ROOT}/include)
+    list(INSERT LIBEVENT_LIBRARIES_SEARCH_PATH 0 ${LIBEVENT_ROOT}/lib)
 endif ()
 
 # Look for the Libevent 2.0 or 1.4 headers
 find_path(LIBEVENT_INCLUDE_DIR
-        NAMES WIN32-Code/event2/event-config.h event2/event-config.h event-config.h
+        NAMES event2/event-config.h event-config.h
         PATHS ${LIBEVENT_INCLUDE_SEARCH_PATH}
         HINTS ${PC_LIBEVENT_INCLUDE_DIRS})
 
@@ -81,7 +79,6 @@ set(Libevent_LIB_PREFIX "")
 set(LIBEVENT_EVENT_CONFIG_DIR ${LIBEVENT_INCLUDE_DIR})
 if (WIN32)
     set(Libevent_LIB_PREFIX "lib")
-    set(LIBEVENT_EVENT_CONFIG_DIR "${LIBEVENT_INCLUDE_DIR}/../WIN32-Code/")
 endif ()
 
 if (LIBEVENT_INCLUDE_DIR)
@@ -110,7 +107,7 @@ endif ()
 
 set(_LIBEVENT_REQUIRED_VARS)
 if (WIN32)
-    set(Libevent_FIND_COMPONENTS ${Libevent_LIB_PREFIX}event core extras)
+    set(Libevent_FIND_COMPONENTS ${Libevent_LIB_PREFIX}event core extra)
 else ()
     set(Libevent_FIND_COMPONENTS ${Libevent_LIB_PREFIX}event core extra pthreads)
 endif ()
@@ -124,10 +121,10 @@ foreach (COMPONENT ${Libevent_FIND_COMPONENTS})
         set(_LIBEVENT_LIBNAME "${Libevent_LIB_PREFIX}event_${COMPONENT}")
     endif ()
     string(TOUPPER "${COMPONENT}" COMPONENT_UPPER)
-    message(STATUS "** ${_LIBEVENT_LIBNAME}")
+    message(STATUS "** fine ${_LIBEVENT_LIBNAME} in ${LIBEVENT_LIBRARIES_SEARCH_PATH}")
     find_library(LIBEVENT_${COMPONENT_UPPER}_LIBRARY
             NAMES ${_LIBEVENT_LIBNAME}
-            PATHS ${LIBEVENT_LIBRARIE_SEARCH_PATH}
+            PATHS ${LIBEVENT_LIBRARIES_SEARCH_PATH}
             HINTS ${PC_LIBEVENT_LIBRARY_DIRS}
             )
     if (LIBEVENT_${COMPONENT_UPPER}_LIBRARY)
@@ -140,9 +137,8 @@ unset(_LIBEVENT_LIBNAME)
 include(FindPackageHandleStandardArgs)
 # handle the QUIETLY and REQUIRED arguments and set LIBEVENT_FOUND to TRUE
 # if all listed variables are TRUE and the requested version matches.
-find_package_handle_standard_args(Libevent REQUIRED_VARS
-        ${_LIBEVENT_REQUIRED_VARS}
-        LIBEVENT_INCLUDE_DIR
+find_package_handle_standard_args(Libevent
+        REQUIRED_VARS ${_LIBEVENT_REQUIRED_VARS} LIBEVENT_INCLUDE_DIR
         VERSION_VAR LIBEVENT_VERSION
         HANDLE_COMPONENTS)
 
diff --git a/example/AsyncProducer.cpp b/example/AsyncProducer.cpp
index a8acd5d..8f6c05f 100644
--- a/example/AsyncProducer.cpp
+++ b/example/AsyncProducer.cpp
@@ -90,7 +90,7 @@ int main(int argc, char* argv[]) {
 
   int threadCount = info.thread_count;
   for (int j = 0; j < threadCount; j++) {
-    std::shared_ptr<std::thread> th = std::make_shared<std::thread>(AsyncProducerWorker, &info, producer);
+    auto th = std::make_shared<std::thread>(AsyncProducerWorker, &info, producer);
     work_pool.push_back(th);
   }
 
diff --git a/example/BatchProducer.cpp b/example/BatchProducer.cpp
index 12e95f7..4055d8a 100644
--- a/example/BatchProducer.cpp
+++ b/example/BatchProducer.cpp
@@ -80,7 +80,7 @@ int main(int argc, char* argv[]) {
 
   int threadCount = info.thread_count;
   for (int j = 0; j < threadCount; j++) {
-    std::shared_ptr<std::thread> th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
+    auto th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
     work_pool.push_back(th);
   }
 
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index 6ef72a8..8e445b1 100755
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -17,37 +17,23 @@ project(example)
 
 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
 
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/src)
-
-link_directories(${LIBEVENT_LIBRARY})
-link_directories(${JSONCPP_LIBRARY})
-
 file(GLOB files RELATIVE "${PROJECT_SOURCE_DIR}" "*.c*")
 list(REMOVE_ITEM files "ArgHelper.cpp")
 foreach(file ${files})
     get_filename_component(basename ${file} NAME_WE)
     add_executable(${basename} ${file})
+
     if(MSVC)
         if(CMAKE_CONFIGURATION_TYPES STREQUAL "Release")
-            set_target_properties( ${basename} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT" )
+            set_target_properties(${basename} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT")
         else()
-            set_target_properties( ${basename} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMTD" )
+            set_target_properties(${basename} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMTD")
         endif()
     endif()
 
-    if (MSVC)
-        if (BUILD_ROCKETMQ_SHARED)
-            target_link_libraries (${basename}  rocketmq_shared ${deplibs} ${LIBEVENT_LIBRARIES} ${JSONCPP_LIBRARIES})
-        else()
-            target_link_libraries (${basename}  rocketmq_static ${deplibs} ${LIBEVENT_LIBRARIES} ${JSONCPP_LIBRARIES})
-        endif()
+    if (BUILD_ROCKETMQ_SHARED)
+        target_link_libraries (${basename} rocketmq_shared)
     else()
-        if (BUILD_ROCKETMQ_SHARED)
-            target_link_libraries (${basename} rocketmq_shared)
-        else()
-            target_link_libraries (${basename} rocketmq_static)
-        endif()
+        target_link_libraries (${basename} rocketmq_static)
     endif()
-
 endforeach()
diff --git a/example/OrderlyProducer.cpp b/example/OrderlyProducer.cpp
index 237532b..d50542e 100644
--- a/example/OrderlyProducer.cpp
+++ b/example/OrderlyProducer.cpp
@@ -81,7 +81,7 @@ int main(int argc, char* argv[]) {
 
   int threadCount = info.thread_count;
   for (int j = 0; j < threadCount; j++) {
-    std::shared_ptr<std::thread> th = std::make_shared<std::thread>(ProducerWorker, &info, producer);
+    auto th = std::make_shared<std::thread>(ProducerWorker, &info, producer);
     work_pool.push_back(th);
   }
 
diff --git a/example/PullConsumer.cpp b/example/PullConsumer.cpp
index 6046d6c..7bd7ffd 100644
--- a/example/PullConsumer.cpp
+++ b/example/PullConsumer.cpp
@@ -34,7 +34,7 @@ void putMessageQueueOffset(MQMessageQueue mq, uint64_t offset) {
 }
 
 uint64_t getMessageQueueOffset(MQMessageQueue mq) {
-  auto it = g_offseTable.find(mq);
+  const auto& it = g_offseTable.find(mq);
   if (it != g_offseTable.end()) {
     return it->second;
   }
diff --git a/example/PushConsumer.cpp b/example/PushConsumer.cpp
index 9aba07c..9f17979 100644
--- a/example/PushConsumer.cpp
+++ b/example/PushConsumer.cpp
@@ -61,7 +61,7 @@ int main(int argc, char* argv[]) {
   consumer->setConsumeFromWhere(CONSUME_FROM_LAST_OFFSET);
 
   if (info.broadcasting) {
-    consumer->setMessageModel(rocketmq::BROADCASTING);
+    consumer->setMessageModel(BROADCASTING);
   }
 
   consumer->subscribe(info.topic, "*");
diff --git a/example/RequestReply.cpp b/example/RequestReply.cpp
new file mode 100644
index 0000000..1ba3af8
--- /dev/null
+++ b/example/RequestReply.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+#include <iostream>
+
+#include "../src/common/UtilAll.h"
+#include "../src/log/Logging.h"
+#include "MessageUtil.h"
+#include "common.h"
+
+using namespace rocketmq;
+
+class MyResponseMessageListener : public MessageListenerConcurrently {
+ public:
+  MyResponseMessageListener(DefaultMQProducer* replyProducer) : m_replyProducer(replyProducer) {}
+  virtual ~MyResponseMessageListener() = default;
+
+  ConsumeStatus consumeMessage(const std::vector<MQMessageExt*>& msgs) override {
+    for (const auto& msg : msgs) {
+      try {
+        std::cout << "handle message: " << msg->toString() << std::endl;
+        const auto& replyTo = MessageUtil::getReplyToClient(msg);
+
+        // create reply message with given util, do not create reply message by yourself
+        std::unique_ptr<MQMessage> replyMessage(MessageUtil::createReplyMessage(msg, "reply message contents."));
+
+        // send reply message with producer
+        SendResult replyResult = m_replyProducer->send(replyMessage.get(), 10000);
+        std::cout << "reply to " << replyTo << ", " << replyResult.toString() << std::endl;
+      } catch (const std::exception& e) {
+        std::cout << e.what() << std::endl;
+      }
+    }
+    return CONSUME_SUCCESS;
+  }
+
+ private:
+  DefaultMQProducer* m_replyProducer;
+};
+
+int main(int argc, char* argv[]) {
+  RocketmqSendAndConsumerArgs info;
+  if (!ParseArgs(argc, argv, &info)) {
+    exit(-1);
+  }
+  PrintRocketmqSendAndConsumerArgs(info);
+
+  DefaultMQProducer producer("");
+  producer.setNamesrvAddr(info.namesrv);
+  producer.setSendMsgTimeout(3000);
+  producer.setRetryTimes(info.retrytimes);
+  producer.setRetryTimes4Async(info.retrytimes);
+  producer.setSendLatencyFaultEnable(!info.selectUnactiveBroker);
+  producer.setTcpTransportTryLockTimeout(1000);
+  producer.setTcpTransportConnectTimeout(400);
+  producer.start();
+
+  DefaultMQPushConsumer consumer(info.groupname);
+  consumer.setNamesrvAddr(info.namesrv);
+  consumer.setTcpTransportTryLockTimeout(1000);
+  consumer.setTcpTransportConnectTimeout(400);
+  consumer.setConsumeThreadNum(info.thread_count);
+  consumer.setConsumeFromWhere(CONSUME_FROM_LAST_OFFSET);
+
+  // recommend client configs
+  consumer.setPullTimeDelayMillsWhenException(0L);
+
+  consumer.subscribe(info.topic, "*");
+
+  MyResponseMessageListener msglistener(&producer);
+  consumer.registerMessageListener(&msglistener);
+
+  try {
+    consumer.start();
+  } catch (MQClientException& e) {
+    std::cout << e << std::endl;
+    return -1;
+  }
+
+  // std::this_thread::sleep_for(std::chrono::seconds(10));
+
+  int msg_count = g_msgCount.load();
+  for (int count = 0; count < msg_count; count++) {
+    try {
+      MQMessage msg(info.topic, "Hello world");
+
+      auto begin = UtilAll::currentTimeMillis();
+      std::unique_ptr<MQMessage> retMsg(producer.request(&msg, 10000));
+      auto cost = UtilAll::currentTimeMillis() - begin;
+      std::cout << count << " >>> request to <" << info.topic << "> cost: " << cost
+                << " replyMessage: " << retMsg->toString() << std::endl;
+    } catch (const std::exception& e) {
+      std::cout << count << " >>> " << e.what() << std::endl;
+    }
+  }
+
+  consumer.shutdown();
+  producer.shutdown();
+
+  return 0;
+}
diff --git a/example/SyncProducer.cpp b/example/SyncProducer.cpp
index d840fdd..994a519 100644
--- a/example/SyncProducer.cpp
+++ b/example/SyncProducer.cpp
@@ -69,7 +69,7 @@ int main(int argc, char* argv[]) {
 
   int threadCount = info.thread_count;
   for (int j = 0; j < threadCount; j++) {
-    std::shared_ptr<std::thread> th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
+    auto th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
     work_pool.push_back(th);
   }
 
diff --git a/example/TransactionProducer.cpp b/example/TransactionProducer.cpp
index f6985f9..547a279 100644
--- a/example/TransactionProducer.cpp
+++ b/example/TransactionProducer.cpp
@@ -90,7 +90,7 @@ int main(int argc, char* argv[]) {
 
   int threadCount = info.thread_count;
   for (int j = 0; j < threadCount; j++) {
-    std::shared_ptr<std::thread> th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
+    auto th = std::make_shared<std::thread>(SyncProducerWorker, &info, producer);
     work_pool.push_back(th);
   }
 
diff --git a/example/common.h b/example/common.h
index db242f7..84683bc 100644
--- a/example/common.h
+++ b/example/common.h
@@ -31,9 +31,9 @@
 #endif
 
 #include "DefaultMQProducer.h"
-#include "TransactionMQProducer.h"
 #include "DefaultMQPullConsumer.h"
 #include "DefaultMQPushConsumer.h"
+#include "TransactionMQProducer.h"
 
 std::atomic<int> g_msgCount(1);
 
diff --git a/format.sh b/format.sh
index f46c5f2..9fcf5af 100755
--- a/format.sh
+++ b/format.sh
@@ -15,58 +15,53 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+set -e
 
 TMPFILE=".clang_format_file.tmp"
 FORMAT="{BasedOnStyle: Chromium, ColumnLimit: 120, TabWidth: 2}"
 
-function Usage
-{
+function Usage() {
     echo "Usage: $0 want-format-file|want-format-dir ..."
     #echo "Currently only format a file or dir at a time"
 }
 
-#Setp1 check clang-format support
+# Setp 1: check clang-format support
 if ! which clang-format &>/dev/null; then
     echo -e "\033[32m !!!!!!please install clang-format  \033[0m"
     exit 1
 fi
 
-
-#Setp2 check weather incoming format file
-if [ ! $# -ge 1 ];then
+# Setp 2: check weather incoming format file
+if [ ! $# -ge 1 ]; then
     Usage
     exit 1
 fi
 
-for dest in "$@"
-do
-  if [ ! -e $dest ]; then
-    echo -e "\033[32m $dest not exists,please check this file weather exists \033[0m"
-  fi
+for dest in "$@"; do
+    if [ ! -e $dest ]; then
+        echo -e "\033[32m $dest not exists,please check this file weather exists \033[0m"
+    fi
 done
 
-
-#Setp3 get filelist
-for dest in $*
-do
-  if [ -f $dest ];then
-      files="$files $dest"
-  elif [ -d $dest ];then
-      files="$files `ls $dest/*.cpp $dest/*.h $dest/*.cc 2>/dev/null`"
-  else
-      echo -e "\033[32m $dest sorry current $0 only support regular file or dir \033[0m"
-  fi
+# Setp 3: get filelist
+for dest in $*; do
+    if [ -f $dest ]; then
+        files="$files $dest"
+    elif [ -d $dest ]; then
+        files="$files $(ls $dest/*.cpp $dest/*.h $dest/*.cc 2>/dev/null)"
+    else
+        echo -e "\033[32m $dest sorry current $0 only support regular file or dir \033[0m"
+    fi
 done
 
-#Setp4 use clang-format format dest file
-for file in $files
-do
+# Setp 4: use clang-format format dest file
+for file in $files; do
     echo $file
-    clang-format $file > $TMPFILE
+    clang-format -style=file $file >$TMPFILE
 
-    if [ -e $TMPFILE ];then
-        filesize=`wc -c $TMPFILE |cut -d " " -f1`
-        if [ $filesize -eq 0 ];then
+    if [ -e $TMPFILE ]; then
+        filesize=$(wc -c $TMPFILE | awk -F' ' '{ print $1; }')
+        if [ $filesize -eq 0 ]; then
             echo -e "\033[32m formt file error,May be because of the size of the source file is 0, or format program error \033[0m"
             exit 1
         fi
diff --git a/src/common/DataBlock.h b/include/DataBlock.h
similarity index 94%
rename from src/common/DataBlock.h
rename to include/DataBlock.h
index 08a6404..7976cd0 100644
--- a/src/common/DataBlock.h
+++ b/include/DataBlock.h
@@ -18,20 +18,20 @@
 #define __DATA_BLOCK_H__
 
 #include <memory>
+#include <string>
 
 #include "RocketMQClient.h"
 
 namespace rocketmq {
 
 class MemoryBlock;
-typedef MemoryBlock* MemoryBlockPtr;
+typedef std::unique_ptr<MemoryBlock> MemoryBlockPtr;
 typedef std::shared_ptr<MemoryBlock> MemoryBlockPtr2;
-typedef std::unique_ptr<MemoryBlock> MemoryBlockPtr3;
 
 class ROCKETMQCLIENT_API MemoryBlock {
  public:
   MemoryBlock() : MemoryBlock(nullptr, 0) {}
-  MemoryBlock(char* data, size_t size) : data_(data), size_(size) {}
+  explicit MemoryBlock(char* data, size_t size) : data_(data), size_(size) {}
   virtual ~MemoryBlock() = default;
 
   /** Returns a void pointer to the data.
@@ -58,6 +58,14 @@ class ROCKETMQCLIENT_API MemoryBlock {
     return data_[offset];
   }
 
+  operator std::string() {
+    if (size_ > 0) {
+      return std::string(data_, size_);
+    } else {
+      return "";
+    }
+  }
+
   /** Frees all the blocks data, setting its size to 0. */
   virtual void reset() { reset(nullptr, 0); }
 
@@ -90,14 +98,14 @@ class ROCKETMQCLIENT_API MemoryPool : public MemoryBlock {
    *  @param initialSize          the size of block to create
    *  @param initialiseToZero     whether to clear the memory or just leave it uninitialised
    */
-  MemoryPool(size_t initialSize, bool initialiseToZero = false);
+  explicit MemoryPool(size_t initialSize, bool initialiseToZero = false);
 
   /** Creates a memory block using a copy of a block of data.
    *
    *  @param dataToInitialiseFrom     some data to copy into this block
    *  @param sizeInBytes              how much space to use
    */
-  MemoryPool(const void* dataToInitialiseFrom, size_t sizeInBytes);
+  explicit MemoryPool(const void* dataToInitialiseFrom, size_t sizeInBytes);
 
   /** Creates a copy of another memory block. */
   MemoryPool(const MemoryPool&);
diff --git a/include/DefaultMQProducer.h b/include/DefaultMQProducer.h
index 71a1da9..91e0e2b 100644
--- a/include/DefaultMQProducer.h
+++ b/include/DefaultMQProducer.h
@@ -17,72 +17,22 @@
 #ifndef __DEFAULT_MQ_PRODUCER_H__
 #define __DEFAULT_MQ_PRODUCER_H__
 
-#include "MQClientConfig.h"
+#include "DefaultMQProducerConfigProxy.h"
 #include "MQProducer.h"
 #include "RPCHook.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQProducerConfig : public MQClientConfig {
- public:
-  DefaultMQProducerConfig();
-  virtual ~DefaultMQProducerConfig() = default;
-
-  // if msgbody size larger than maxMsgBodySize, exception will be throwed
-  int getMaxMessageSize() const { return m_maxMessageSize; }
-  void setMaxMessageSize(int maxMessageSize) { m_maxMessageSize = maxMessageSize; }
-
-  /*
-   * if msgBody size is large than m_compressMsgBodyOverHowmuch
-   *  rocketmq cpp will compress msgBody according to compressLevel
-   */
-  int getCompressMsgBodyOverHowmuch() const { return m_compressMsgBodyOverHowmuch; }
-  void setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) {
-    m_compressMsgBodyOverHowmuch = compressMsgBodyOverHowmuch;
-  }
-
-  int getCompressLevel() const { return m_compressLevel; }
-  void setCompressLevel(int compressLevel) {
-    if ((compressLevel >= 0 && compressLevel <= 9) || compressLevel == -1) {
-      m_compressLevel = compressLevel;
-    }
-  }
-
-  // set and get timeout of per msg
-  int getSendMsgTimeout() const { return m_sendMsgTimeout; }
-  void setSendMsgTimeout(int sendMsgTimeout) { m_sendMsgTimeout = sendMsgTimeout; }
-
-  // set msg max retry times, default retry times is 5
-  int getRetryTimes() const { return m_retryTimes; }
-  void setRetryTimes(int times) { m_retryTimes = std::min(std::max(0, times), 15); }
-
-  int getRetryTimes4Async() const { return m_retryTimes4Async; }
-  void setRetryTimes4Async(int times) { m_retryTimes4Async = std::min(std::max(0, times), 15); }
-
-  bool isRetryAnotherBrokerWhenNotStoreOK() const { return m_retryAnotherBrokerWhenNotStoreOK; }
-  void setRetryAnotherBrokerWhenNotStoreOK(bool retryAnotherBrokerWhenNotStoreOK) {
-    m_retryAnotherBrokerWhenNotStoreOK = retryAnotherBrokerWhenNotStoreOK;
-  }
-
-  virtual bool isSendLatencyFaultEnable() const = 0;
-  virtual void setSendLatencyFaultEnable(bool sendLatencyFaultEnable) = 0;
-
- protected:
-  int m_maxMessageSize;              // default: 4 MB
-  int m_compressMsgBodyOverHowmuch;  // default: 4 KB
-  int m_compressLevel;
-  int m_sendMsgTimeout;
-  int m_retryTimes;
-  int m_retryTimes4Async;
-  bool m_retryAnotherBrokerWhenNotStoreOK;
-};
-
-class ROCKETMQCLIENT_API DefaultMQProducer : public MQProducer, public DefaultMQProducerConfig {
+class ROCKETMQCLIENT_API DefaultMQProducer : public MQProducer, public DefaultMQProducerConfigProxy {
  public:
   DefaultMQProducer(const std::string& groupname);
   DefaultMQProducer(const std::string& groupname, RPCHookPtr rpcHook);
   virtual ~DefaultMQProducer();
 
+ private:
+  DefaultMQProducer(const std::string& groupname, RPCHookPtr rpcHook, DefaultMQProducerConfigPtr producerConfig);
+  friend class TransactionMQProducer;
+
  public:  // MQProducer
   void start() override;
   void shutdown() override;
@@ -123,12 +73,15 @@ class ROCKETMQCLIENT_API DefaultMQProducer : public MQProducer, public DefaultMQ
   SendResult send(std::vector<MQMessagePtr>& msgs, const MQMessageQueue& mq) override;
   SendResult send(std::vector<MQMessagePtr>& msgs, const MQMessageQueue& mq, long timeout) override;
 
+  // RPC
+  MQMessagePtr request(MQMessagePtr msg, long timeout) override;
+
  public:  // DefaultMQProducerConfig
   bool isSendLatencyFaultEnable() const override;
   void setSendLatencyFaultEnable(bool sendLatencyFaultEnable) override;
 
  public:
-  void setRPCHook(std::shared_ptr<RPCHook> rpcHook);
+  void setRPCHook(RPCHookPtr rpcHook);
 
  protected:
   std::shared_ptr<MQProducer> m_producerDelegate;
diff --git a/include/DefaultMQProducerConfig.h b/include/DefaultMQProducerConfig.h
new file mode 100644
index 0000000..fe396ee
--- /dev/null
+++ b/include/DefaultMQProducerConfig.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PRODUCER_CONFIG_H__
+#define __DEFAULT_MQ_PRODUCER_CONFIG_H__
+
+#include "MQClientConfig.h"
+
+namespace rocketmq {
+
+class DefaultMQProducerConfig;
+typedef std::shared_ptr<DefaultMQProducerConfig> DefaultMQProducerConfigPtr;
+
+class ROCKETMQCLIENT_API DefaultMQProducerConfig : virtual public MQClientConfig {
+ public:
+  virtual ~DefaultMQProducerConfig() = default;
+
+  // if msgbody size larger than maxMsgBodySize, exception will be throwed
+  virtual int getMaxMessageSize() const = 0;
+  virtual void setMaxMessageSize(int maxMessageSize) = 0;
+
+  /*
+   * if msgBody size is large than m_compressMsgBodyOverHowmuch
+   *  rocketmq cpp will compress msgBody according to compressLevel
+   */
+  virtual int getCompressMsgBodyOverHowmuch() const = 0;
+  virtual void setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) = 0;
+
+  virtual int getCompressLevel() const = 0;
+  virtual void setCompressLevel(int compressLevel) = 0;
+
+  // set and get timeout of per msg
+  virtual int getSendMsgTimeout() const = 0;
+  virtual void setSendMsgTimeout(int sendMsgTimeout) = 0;
+
+  // set msg max retry times, default retry times is 5
+  virtual int getRetryTimes() const = 0;
+  virtual void setRetryTimes(int times) = 0;
+
+  virtual int getRetryTimes4Async() const = 0;
+  virtual void setRetryTimes4Async(int times) = 0;
+
+  virtual bool isRetryAnotherBrokerWhenNotStoreOK() const = 0;
+  virtual void setRetryAnotherBrokerWhenNotStoreOK(bool retryAnotherBrokerWhenNotStoreOK) = 0;
+
+  virtual bool isSendLatencyFaultEnable() const { return false; };
+  virtual void setSendLatencyFaultEnable(bool sendLatencyFaultEnable){};
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PRODUCER_CONFIG_H__
diff --git a/include/DefaultMQProducerConfigProxy.h b/include/DefaultMQProducerConfigProxy.h
new file mode 100644
index 0000000..522decf
--- /dev/null
+++ b/include/DefaultMQProducerConfigProxy.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PRODUCER_CONFI_PROXY_H__
+#define __DEFAULT_MQ_PRODUCER_CONFI_PROXY_H__
+
+#include "DefaultMQProducerConfig.h"
+#include "MQClientConfigProxy.h"
+
+namespace rocketmq {
+
+class ROCKETMQCLIENT_API DefaultMQProducerConfigProxy : virtual public DefaultMQProducerConfig,
+                                                        public MQClientConfigProxy {
+ public:
+  DefaultMQProducerConfigProxy(DefaultMQProducerConfigPtr producerConfig)
+      : MQClientConfigProxy(producerConfig), m_producerConfig(producerConfig) {}
+  virtual ~DefaultMQProducerConfigProxy() = default;
+
+  DefaultMQProducerConfigPtr getRealConfig() const { return m_producerConfig; }
+
+  int getMaxMessageSize() const override { return m_producerConfig->getMaxMessageSize(); }
+
+  void setMaxMessageSize(int maxMessageSize) override { m_producerConfig->setMaxMessageSize(maxMessageSize); }
+
+  int getCompressMsgBodyOverHowmuch() const override { return m_producerConfig->getCompressMsgBodyOverHowmuch(); }
+
+  void setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) override {
+    m_producerConfig->setCompressMsgBodyOverHowmuch(compressMsgBodyOverHowmuch);
+  }
+
+  int getCompressLevel() const override { return m_producerConfig->getCompressLevel(); }
+
+  void setCompressLevel(int compressLevel) override { m_producerConfig->setCompressLevel(compressLevel); }
+
+  int getSendMsgTimeout() const override { return m_producerConfig->getSendMsgTimeout(); }
+
+  void setSendMsgTimeout(int sendMsgTimeout) override { m_producerConfig->setSendMsgTimeout(sendMsgTimeout); }
+
+  int getRetryTimes() const override { return m_producerConfig->getRetryTimes(); }
+
+  void setRetryTimes(int times) override { m_producerConfig->setRetryTimes(times); }
+
+  int getRetryTimes4Async() const override { return m_producerConfig->getRetryTimes4Async(); }
+
+  void setRetryTimes4Async(int times) override { m_producerConfig->setRetryTimes4Async(times); }
+
+  bool isRetryAnotherBrokerWhenNotStoreOK() const override {
+    return m_producerConfig->isRetryAnotherBrokerWhenNotStoreOK();
+  }
+
+  void setRetryAnotherBrokerWhenNotStoreOK(bool retryAnotherBrokerWhenNotStoreOK) override {
+    m_producerConfig->setRetryAnotherBrokerWhenNotStoreOK(retryAnotherBrokerWhenNotStoreOK);
+  }
+
+  bool isSendLatencyFaultEnable() const override { return m_producerConfig->isSendLatencyFaultEnable(); }
+
+  void setSendLatencyFaultEnable(bool sendLatencyFaultEnable) override {
+    m_producerConfig->setSendLatencyFaultEnable(sendLatencyFaultEnable);
+  }
+
+ private:
+  DefaultMQProducerConfigPtr m_producerConfig;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PRODUCER_CONFI_PROXY_H__
diff --git a/include/DefaultMQPullConsumer.h b/include/DefaultMQPullConsumer.h
index 1bd7aff..8461969 100755
--- a/include/DefaultMQPullConsumer.h
+++ b/include/DefaultMQPullConsumer.h
@@ -21,25 +21,13 @@
 #include <string>
 
 #include "AllocateMQStrategy.h"
-#include "DefaultMQConsumer.h"
+#include "DefaultMQPullConsumerConfigProxy.h"
 #include "MQPullConsumer.h"
 #include "RPCHook.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQPullConsumerConfig : public DefaultMQConsumerConfig {
- public:
-  DefaultMQPullConsumerConfig();
-  virtual ~DefaultMQPullConsumerConfig() = default;
-
-  AllocateMQStrategy* getAllocateMQStrategy() { return m_allocateMQStrategy.get(); }
-  void setAllocateMQStrategy(AllocateMQStrategy* strategy) { m_allocateMQStrategy.reset(strategy); }
-
- protected:
-  std::unique_ptr<AllocateMQStrategy> m_allocateMQStrategy;
-};
-
-class ROCKETMQCLIENT_API DefaultMQPullConsumer : public MQPullConsumer, public DefaultMQPullConsumerConfig {
+class ROCKETMQCLIENT_API DefaultMQPullConsumer : public MQPullConsumer, public DefaultMQPullConsumerConfigProxy {
  public:
   DefaultMQPullConsumer(const std::string& groupname);
   DefaultMQPullConsumer(const std::string& groupname, RPCHookPtr rpcHook);
@@ -82,7 +70,7 @@ class ROCKETMQCLIENT_API DefaultMQPullConsumer : public MQPullConsumer, public D
   void fetchMessageQueuesInBalance(const std::string& topic, std::vector<MQMessageQueue>& mqs) override;
 
  public:
-  void setRPCHook(std::shared_ptr<RPCHook> rpcHook);
+  void setRPCHook(RPCHookPtr rpcHook);
 
  protected:
   std::shared_ptr<MQPullConsumer> m_pullConsumerDelegate;
diff --git a/include/DefaultMQConsumer.h b/include/DefaultMQPullConsumerConfig.h
similarity index 57%
copy from include/DefaultMQConsumer.h
copy to include/DefaultMQPullConsumerConfig.h
index 1f103ac..835c076 100644
--- a/include/DefaultMQConsumer.h
+++ b/include/DefaultMQPullConsumerConfig.h
@@ -14,25 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __DEFAULT_MQ_CONSUMER_H__
-#define __DEFAULT_MQ_CONSUMER_H__
+#ifndef __DEFAULT_MQ_PULL_CONSUMER_CONFIG_H__
+#define __DEFAULT_MQ_PULL_CONSUMER_CONFIG_H__
 
+#include "AllocateMQStrategy.h"
 #include "ConsumeType.h"
 #include "MQClientConfig.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQConsumerConfig : public MQClientConfig {
+class DefaultMQPullConsumerConfig;
+typedef std::shared_ptr<DefaultMQPullConsumerConfig> DefaultMQPullConsumerConfigPtr;
+
+class ROCKETMQCLIENT_API DefaultMQPullConsumerConfig : virtual public MQClientConfig {
  public:
-  DefaultMQConsumerConfig() : m_messageModel(CLUSTERING) {}
+  virtual ~DefaultMQPullConsumerConfig() = default;
 
-  MessageModel getMessageModel() const { return m_messageModel; }
-  void setMessageModel(MessageModel messageModel) { m_messageModel = messageModel; }
+  virtual MessageModel getMessageModel() const = 0;
+  virtual void setMessageModel(MessageModel messageModel) = 0;
 
- protected:
-  MessageModel m_messageModel;
+  virtual AllocateMQStrategy* getAllocateMQStrategy() const = 0;
+  virtual void setAllocateMQStrategy(AllocateMQStrategy* strategy) = 0;
 };
 
 }  // namespace rocketmq
 
-#endif  // __DEFAULT_MQ_CONSUMER_H__
+#endif  // __DEFAULT_MQ_PULL_CONSUMER_CONFIG_H__
diff --git a/include/DefaultMQPullConsumerConfigProxy.h b/include/DefaultMQPullConsumerConfigProxy.h
new file mode 100644
index 0000000..101acf4
--- /dev/null
+++ b/include/DefaultMQPullConsumerConfigProxy.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PULL_CONSUMER_CONFIG_PROXY_H__
+#define __DEFAULT_MQ_PULL_CONSUMER_CONFIG_PROXY_H__
+
+#include "DefaultMQPullConsumerConfig.h"
+#include "MQClientConfigProxy.h"
+
+namespace rocketmq {
+
+class ROCKETMQCLIENT_API DefaultMQPullConsumerConfigProxy : virtual public DefaultMQPullConsumerConfig,
+                                                            public MQClientConfigProxy {
+ public:
+  DefaultMQPullConsumerConfigProxy(DefaultMQPullConsumerConfigPtr consumerConfig)
+      : MQClientConfigProxy(consumerConfig), m_consumerConfig(consumerConfig) {}
+  virtual ~DefaultMQPullConsumerConfigProxy() = default;
+
+  MessageModel getMessageModel() const override { return m_consumerConfig->getMessageModel(); }
+
+  void setMessageModel(MessageModel messageModel) override { m_consumerConfig->setMessageModel(messageModel); }
+
+  AllocateMQStrategy* getAllocateMQStrategy() const override { return m_consumerConfig->getAllocateMQStrategy(); }
+
+  void setAllocateMQStrategy(AllocateMQStrategy* strategy) override {
+    m_consumerConfig->setAllocateMQStrategy(strategy);
+  }
+
+ private:
+  DefaultMQPullConsumerConfigPtr m_consumerConfig;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PULL_CONSUMER_CONFIG_PROXY_H__
diff --git a/include/DefaultMQPushConsumer.h b/include/DefaultMQPushConsumer.h
index 1caf98f..e90eb95 100755
--- a/include/DefaultMQPushConsumer.h
+++ b/include/DefaultMQPushConsumer.h
@@ -17,79 +17,13 @@
 #ifndef __DEFAULT_MQ_PUSH_CONSUMER_H__
 #define __DEFAULT_MQ_PUSH_CONSUMER_H__
 
-#include "AllocateMQStrategy.h"
-#include "DefaultMQConsumer.h"
+#include "DefaultMQPushConsumerConfigProxy.h"
 #include "MQPushConsumer.h"
 #include "RPCHook.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQPushConsumerConfig : public DefaultMQConsumerConfig {
- public:
-  DefaultMQPushConsumerConfig();
-  virtual ~DefaultMQPushConsumerConfig() = default;
-
-  ConsumeFromWhere getConsumeFromWhere() const { return m_consumeFromWhere; }
-  void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) { m_consumeFromWhere = consumeFromWhere; }
-
-  std::string getConsumeTimestamp() { return m_consumeTimestamp; }
-  void setConsumeTimestamp(std::string consumeTimestamp) { m_consumeTimestamp = consumeTimestamp; }
-
-  /**
-   * consuming thread count, default value is cpu cores
-   */
-  int getConsumeThreadNum() const { return m_consumeThreadNum; }
-  void setConsumeThreadNum(int threadNum) {
-    if (threadNum > 0) {
-      m_consumeThreadNum = threadNum;
-    }
-  }
-
-  /**
-   * the pull number of message size by each pullMsg for orderly consume, default value is 1
-   */
-  int getConsumeMessageBatchMaxSize() const { return m_consumeMessageBatchMaxSize; }
-  void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) {
-    if (consumeMessageBatchMaxSize >= 1) {
-      m_consumeMessageBatchMaxSize = consumeMessageBatchMaxSize;
-    }
-  }
-
-  /**
-   * max cache msg size per Queue in memory if consumer could not consume msgs immediately,
-   * default maxCacheMsgSize per Queue is 1000, set range is:1~65535
-   */
-  int getMaxCacheMsgSizePerQueue() const { return m_maxMsgCacheSize; }
-  void setMaxCacheMsgSizePerQueue(int maxCacheSize) {
-    if (maxCacheSize > 0 && maxCacheSize < 65535) {
-      m_maxMsgCacheSize = maxCacheSize;
-    }
-  }
-
-  int getAsyncPullTimeout() const { return m_asyncPullTimeout; }
-  void setAsyncPullTimeout(int asyncPullTimeout) { m_asyncPullTimeout = asyncPullTimeout; }
-
-  int getMaxReconsumeTimes() { return m_maxReconsumeTimes; }
-  void setMaxReconsumeTimes(int maxReconsumeTimes) { m_maxReconsumeTimes = maxReconsumeTimes; }
-
-  AllocateMQStrategy* getAllocateMQStrategy() { return m_allocateMQStrategy.get(); }
-  void setAllocateMQStrategy(AllocateMQStrategy* strategy) { m_allocateMQStrategy.reset(strategy); }
-
- protected:
-  ConsumeFromWhere m_consumeFromWhere;
-  std::string m_consumeTimestamp;
-
-  int m_consumeThreadNum;
-  int m_consumeMessageBatchMaxSize;
-  int m_maxMsgCacheSize;
-
-  int m_asyncPullTimeout;  // 30s
-  int m_maxReconsumeTimes;
-
-  std::unique_ptr<AllocateMQStrategy> m_allocateMQStrategy;
-};
-
-class ROCKETMQCLIENT_API DefaultMQPushConsumer : public MQPushConsumer, public DefaultMQPushConsumerConfig {
+class ROCKETMQCLIENT_API DefaultMQPushConsumer : public MQPushConsumer, public DefaultMQPushConsumerConfigProxy {
  public:
   DefaultMQPushConsumer(const std::string& groupname);
   DefaultMQPushConsumer(const std::string& groupname, RPCHookPtr rpcHook);
@@ -108,13 +42,15 @@ class ROCKETMQCLIENT_API DefaultMQPushConsumer : public MQPushConsumer, public D
   void registerMessageListener(MessageListenerConcurrently* messageListener) override;
   void registerMessageListener(MessageListenerOrderly* messageListener) override;
 
+  MQMessageListener* getMessageListener() const override;
+
   void subscribe(const std::string& topic, const std::string& subExpression) override;
 
   void suspend() override;
   void resume() override;
 
  public:
-  void setRPCHook(std::shared_ptr<RPCHook> rpcHook);
+  void setRPCHook(RPCHookPtr rpcHook);
 
  protected:
   std::shared_ptr<MQPushConsumer> m_pushConsumerDelegate;
diff --git a/include/DefaultMQPushConsumerConfig.h b/include/DefaultMQPushConsumerConfig.h
new file mode 100644
index 0000000..0c571cc
--- /dev/null
+++ b/include/DefaultMQPushConsumerConfig.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_H__
+#define __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_H__
+
+#include "AllocateMQStrategy.h"
+#include "ConsumeType.h"
+#include "MQClientConfig.h"
+
+namespace rocketmq {
+
+class DefaultMQPushConsumerConfig;
+typedef std::shared_ptr<DefaultMQPushConsumerConfig> DefaultMQPushConsumerConfigPtr;
+
+class ROCKETMQCLIENT_API DefaultMQPushConsumerConfig : virtual public MQClientConfig {
+ public:
+  virtual ~DefaultMQPushConsumerConfig() = default;
+
+  virtual MessageModel getMessageModel() const = 0;
+  virtual void setMessageModel(MessageModel messageModel) = 0;
+
+  virtual ConsumeFromWhere getConsumeFromWhere() const = 0;
+  virtual void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) = 0;
+
+  virtual std::string getConsumeTimestamp() = 0;
+  virtual void setConsumeTimestamp(std::string consumeTimestamp) = 0;
+
+  /**
+   * consuming thread count, default value is cpu cores
+   */
+  virtual int getConsumeThreadNum() const = 0;
+  virtual void setConsumeThreadNum(int threadNum) = 0;
+
+  /**
+   * the pull number of message size by each pullMsg for orderly consume, default value is 1
+   */
+  virtual int getConsumeMessageBatchMaxSize() const = 0;
+  virtual void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) = 0;
+
+  /**
+   * max cache msg size per Queue in memory if consumer could not consume msgs immediately,
+   * default maxCacheMsgSize per Queue is 1000, set range is:1~65535
+   */
+  virtual int getMaxCacheMsgSizePerQueue() const = 0;
+  virtual void setMaxCacheMsgSizePerQueue(int maxCacheSize) = 0;
+
+  virtual int getAsyncPullTimeout() const = 0;
+  virtual void setAsyncPullTimeout(int asyncPullTimeout) = 0;
+
+  virtual int getMaxReconsumeTimes() const = 0;
+  virtual void setMaxReconsumeTimes(int maxReconsumeTimes) = 0;
+
+  virtual long getPullTimeDelayMillsWhenException() const = 0;
+  virtual void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) = 0;
+
+  virtual AllocateMQStrategy* getAllocateMQStrategy() const = 0;
+  virtual void setAllocateMQStrategy(AllocateMQStrategy* strategy) = 0;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_H__
diff --git a/include/DefaultMQPushConsumerConfigProxy.h b/include/DefaultMQPushConsumerConfigProxy.h
new file mode 100644
index 0000000..ef0c4de
--- /dev/null
+++ b/include/DefaultMQPushConsumerConfigProxy.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_PROXY_H__
+#define __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_PROXY_H__
+
+#include "DefaultMQPushConsumerConfig.h"
+#include "MQClientConfigProxy.h"
+
+namespace rocketmq {
+
+class ROCKETMQCLIENT_API DefaultMQPushConsumerConfigProxy : virtual public DefaultMQPushConsumerConfig,
+                                                            public MQClientConfigProxy {
+ public:
+  DefaultMQPushConsumerConfigProxy(DefaultMQPushConsumerConfigPtr consumerConfig)
+      : MQClientConfigProxy(consumerConfig), m_consumerConfig(consumerConfig) {}
+  virtual ~DefaultMQPushConsumerConfigProxy() = default;
+
+  DefaultMQPushConsumerConfigPtr getRealConfig() const { return m_consumerConfig; }
+
+  MessageModel getMessageModel() const override { return m_consumerConfig->getMessageModel(); }
+
+  void setMessageModel(MessageModel messageModel) override { m_consumerConfig->setMessageModel(messageModel); }
+
+  ConsumeFromWhere getConsumeFromWhere() const override { return m_consumerConfig->getConsumeFromWhere(); }
+
+  void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) override {
+    m_consumerConfig->setConsumeFromWhere(consumeFromWhere);
+  }
+
+  std::string getConsumeTimestamp() override { return m_consumerConfig->getConsumeTimestamp(); }
+
+  void setConsumeTimestamp(std::string consumeTimestamp) override {
+    m_consumerConfig->setConsumeTimestamp(consumeTimestamp);
+  }
+
+  int getConsumeThreadNum() const override { return m_consumerConfig->getConsumeThreadNum(); }
+
+  void setConsumeThreadNum(int threadNum) override { return m_consumerConfig->setConsumeThreadNum(threadNum); }
+
+  int getConsumeMessageBatchMaxSize() const override { return m_consumerConfig->getConsumeMessageBatchMaxSize(); }
+
+  void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) override {
+    m_consumerConfig->setConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize);
+  }
+
+  int getMaxCacheMsgSizePerQueue() const override { return m_consumerConfig->getMaxCacheMsgSizePerQueue(); }
+
+  void setMaxCacheMsgSizePerQueue(int maxCacheSize) override {
+    m_consumerConfig->setMaxCacheMsgSizePerQueue(maxCacheSize);
+  }
+
+  int getAsyncPullTimeout() const override { return m_consumerConfig->getAsyncPullTimeout(); }
+
+  void setAsyncPullTimeout(int asyncPullTimeout) override { m_consumerConfig->setAsyncPullTimeout(asyncPullTimeout); }
+
+  int getMaxReconsumeTimes() const override { return m_consumerConfig->getMaxReconsumeTimes(); }
+
+  void setMaxReconsumeTimes(int maxReconsumeTimes) override {
+    m_consumerConfig->setMaxReconsumeTimes(maxReconsumeTimes);
+  }
+
+  long getPullTimeDelayMillsWhenException() const override {
+    return m_consumerConfig->getPullTimeDelayMillsWhenException();
+  }
+
+  void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) override {
+    m_consumerConfig->setPullTimeDelayMillsWhenException(pullTimeDelayMillsWhenException);
+  }
+
+  AllocateMQStrategy* getAllocateMQStrategy() const override { return m_consumerConfig->getAllocateMQStrategy(); }
+
+  void setAllocateMQStrategy(AllocateMQStrategy* strategy) override {
+    m_consumerConfig->setAllocateMQStrategy(strategy);
+  }
+
+ private:
+  DefaultMQPushConsumerConfigPtr m_consumerConfig;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_PROXY_H__
diff --git a/include/MQClientConfig.h b/include/MQClientConfig.h
index cb4de54..9cc5bc6 100644
--- a/include/MQClientConfig.h
+++ b/include/MQClientConfig.h
@@ -17,78 +17,57 @@
 #ifndef __MQ_CLIENT_CONFIG_H__
 #define __MQ_CLIENT_CONFIG_H__
 
+#include <memory>
 #include <string>
 
 #include "RocketMQClient.h"
 
 namespace rocketmq {
 
+class MQClientConfig;
+typedef std::shared_ptr<MQClientConfig> MQClientConfigPtr;
+
 /**
  * MQ Client Config
  */
 class ROCKETMQCLIENT_API MQClientConfig {
  public:
-  MQClientConfig();
   virtual ~MQClientConfig() = default;
 
-  // clientId=processId-ipAddr@instanceName
-  std::string buildMQClientId() const;
+  // clientId = clientIP @ processId [ @ unitName ]
+  virtual std::string buildMQClientId() const = 0;
+
+  virtual const std::string& getGroupName() const = 0;
+  virtual void setGroupName(const std::string& groupname) = 0;
 
-  // groupName
-  const std::string& getGroupName() const;
-  void setGroupName(const std::string& groupname);
+  virtual const std::string& getNamesrvAddr() const = 0;
+  virtual void setNamesrvAddr(const std::string& namesrvAddr) = 0;
 
-  const std::string& getNamesrvAddr() const;
-  void setNamesrvAddr(const std::string& namesrvAddr);
+  virtual const std::string& getInstanceName() const = 0;
+  virtual void setInstanceName(const std::string& instanceName) = 0;
 
-  const std::string& getInstanceName() const;
-  void setInstanceName(const std::string& instanceName);
+  virtual void changeInstanceNameToPID() = 0;
 
-  void changeInstanceNameToPID();
+  virtual const std::string& getUnitName() const = 0;
+  virtual void setUnitName(std::string unitName) = 0;
 
   /**
-   * set TcpTransport pull thread num, which dermine the num of threads to distribute network data,
-   *
-   *  1. its default value is CPU num, it must be setted before producer/consumer start, minimum value is CPU num;
-   *  2. this pullThread num must be tested on your environment to find the best value for RT of sendMsg or delay time
-   *     of consume msg before you change it;
-   *  3. producer and consumer need different pullThread num, if set this num, producer and consumer must set different
-   *     instanceName.
-   *  4. configuration suggestion:
-   *      1>. minimum RT of sendMsg:
-   *              pullThreadNum = brokerNum*2
+   * the num of threads to distribute network data
    **/
-  int getTcpTransportWorkerThreadNum() const;
-  void setTcpTransportWorkerThreadNum(int num);
+  virtual int getTcpTransportWorkerThreadNum() const = 0;
+  virtual void setTcpTransportWorkerThreadNum(int num) = 0;
 
   /**
-   * timeout of tcp connect, it is same meaning for both producer and consumer;
-   *  1. default value is 3000ms
-   *  2. input parameter could only be milliSecond, suggestion value is 1000-3000ms;
+   * timeout of tcp connect
    **/
-  uint64_t getTcpTransportConnectTimeout() const;
-  void setTcpTransportConnectTimeout(uint64_t timeout);  // ms
+  virtual uint64_t getTcpTransportConnectTimeout() const = 0;
+  virtual void setTcpTransportConnectTimeout(uint64_t timeout) = 0;  // ms
 
   /**
-   * timeout of tryLock tcpTransport before sendMsg/pullMsg, if timeout, returns NULL
-   *  1. paremeter unit is ms, default value is 3000ms, the minimun value is 1000ms, suggestion value is 3000ms;
-   *  2. if configured with value smaller than 1000ms, the tryLockTimeout value will be setted to 1000ms
+   * timeout of tryLock tcpTransport, the minimun value is 1000ms
    **/
-  uint64_t getTcpTransportTryLockTimeout() const;
-  void setTcpTransportTryLockTimeout(uint64_t timeout);  // ms
-
-  const std::string& getUnitName() const;
-  void setUnitName(std::string unitName);
-
- protected:
-  std::string m_namesrvAddr;
-  std::string m_instanceName;
-  std::string m_groupName;
-  std::string m_unitName;
-
-  int m_tcpWorkerThreadNum;
-  uint64_t m_tcpConnectTimeout;           // ms
-  uint64_t m_tcpTransportTryLockTimeout;  // s
+  virtual uint64_t getTcpTransportTryLockTimeout() const = 0;
+  virtual void setTcpTransportTryLockTimeout(uint64_t timeout) = 0;  // ms
 };
 
 }  // namespace rocketmq
diff --git a/include/MQClientConfigProxy.h b/include/MQClientConfigProxy.h
new file mode 100644
index 0000000..5714aad
--- /dev/null
+++ b/include/MQClientConfigProxy.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+#ifndef __MQ_CLIENT_CONFIG_PROXY_H__
+#define __MQ_CLIENT_CONFIG_PROXY_H__
+
+#include "MQClientConfig.h"
+
+namespace rocketmq {
+
+class ROCKETMQCLIENT_API MQClientConfigProxy : virtual public MQClientConfig {
+ public:
+  MQClientConfigProxy(MQClientConfigPtr clientConfig) : m_clientConfig(clientConfig) {}
+  virtual ~MQClientConfigProxy() = default;
+
+  MQClientConfigPtr getRealConfig() const { return m_clientConfig; }
+
+  std::string buildMQClientId() const override { return m_clientConfig->buildMQClientId(); }
+
+  const std::string& getGroupName() const override { return m_clientConfig->getGroupName(); }
+
+  void setGroupName(const std::string& groupname) override { m_clientConfig->setGroupName(groupname); }
+
+  const std::string& getNamesrvAddr() const override { return m_clientConfig->getNamesrvAddr(); }
+
+  void setNamesrvAddr(const std::string& namesrvAddr) override { m_clientConfig->setNamesrvAddr(namesrvAddr); }
+
+  const std::string& getInstanceName() const override { return m_clientConfig->getInstanceName(); }
+
+  void setInstanceName(const std::string& instanceName) override { m_clientConfig->setInstanceName(instanceName); }
+
+  void changeInstanceNameToPID() override { m_clientConfig->changeInstanceNameToPID(); }
+
+  const std::string& getUnitName() const override { return m_clientConfig->getUnitName(); }
+
+  void setUnitName(std::string unitName) override { m_clientConfig->setUnitName(unitName); }
+
+  int getTcpTransportWorkerThreadNum() const override { return m_clientConfig->getTcpTransportWorkerThreadNum(); }
+
+  void setTcpTransportWorkerThreadNum(int num) override { m_clientConfig->setTcpTransportWorkerThreadNum(num); }
+
+  uint64_t getTcpTransportConnectTimeout() const override { return m_clientConfig->getTcpTransportConnectTimeout(); }
+
+  void setTcpTransportConnectTimeout(uint64_t timeout) override {
+    m_clientConfig->setTcpTransportConnectTimeout(timeout);
+  }
+
+  uint64_t getTcpTransportTryLockTimeout() const override { return m_clientConfig->getTcpTransportTryLockTimeout(); }
+
+  void setTcpTransportTryLockTimeout(uint64_t timeout) override {
+    m_clientConfig->setTcpTransportTryLockTimeout(timeout);
+  }
+
+ private:
+  MQClientConfigPtr m_clientConfig;
+};
+
+}  // namespace rocketmq
+
+#endif  // __MQ_CLIENT_CONFIG_PROXY_H__
diff --git a/include/MQClientException.h b/include/MQClientException.h
index 56deb7a..4e2498d 100644
--- a/include/MQClientException.h
+++ b/include/MQClientException.h
@@ -29,10 +29,22 @@ namespace rocketmq {
 class ROCKETMQCLIENT_API MQException : public std::exception {
  public:
   MQException(const std::string& msg, int error, const char* file, int line) noexcept
-      : m_error(error), m_line(line), m_msg(msg), m_file(file), m_type("MQException") {}
-
-  MQException(const std::string& msg, int error, const char* file, const char* type, int line) noexcept
-      : m_error(error), m_line(line), m_msg(msg), m_file(file), m_type(type) {}
+      : MQException(msg, error, nullptr, file, line) {}
+
+  MQException(const std::string& msg, int error, std::exception_ptr cause, const char* file, int line) noexcept
+      : MQException("MQException", msg, error, cause, file, line) {}
+
+  MQException(const std::string& type,
+              const std::string& msg,
+              int error,
+              std::exception_ptr cause,
+              const char* file,
+              int line) noexcept : m_type(type),
+                                   m_msg(msg),
+                                   m_error(error),
+                                   m_cause(cause),
+                                   m_file(file),
+                                   m_line(line) {}
 
   virtual ~MQException() noexcept = default;
 
@@ -45,18 +57,27 @@ class ROCKETMQCLIENT_API MQException : public std::exception {
     return m_what_.c_str();
   }
 
-  int GetError() const noexcept { return m_error; }
-  int GetLine() { return m_line; }
-  const char* GetMsg() { return m_msg.c_str(); }
-  const char* GetFile() { return m_file.c_str(); }
   const char* GetType() const noexcept { return m_type.c_str(); }
 
+  const std::string& GetErrorMessage() const noexcept { return m_msg; }
+  const char* GetMsg() const noexcept { return m_msg.c_str(); }
+
+  int GetError() const noexcept { return m_error; }
+
+  std::exception_ptr GetCause() const { return m_cause; }
+
+  const char* GetFile() const noexcept { return m_file.c_str(); }
+  int GetLine() const noexcept { return m_line; }
+
  protected:
-  int m_error;
-  int m_line;
+  std::string m_type;
   std::string m_msg;
+  int m_error;
+
+  std::exception_ptr m_cause;
+
   std::string m_file;
-  std::string m_type;
+  int m_line;
 
   mutable std::string m_what_;
 };
@@ -66,32 +87,42 @@ inline std::ostream& operator<<(std::ostream& os, const MQException& e) {
   return os;
 }
 
-#define DEFINE_MQCLIENTEXCEPTION2(name, super)                                                     \
-  class ROCKETMQCLIENT_API name : public super {                                                   \
-   public:                                                                                         \
-    name(const std::string& msg, int error, const char* file, int line) noexcept                   \
-        : super(msg, error, file, #name, line) {}                                                  \
-                                                                                                   \
-   protected:                                                                                      \
-    name(const std::string& msg, int error, const char* file, const char* type, int line) noexcept \
-        : super(msg, error, file, type, line) {}                                                   \
+#define DEFINE_MQEXCEPTION2(name, super)                                                                   \
+  class ROCKETMQCLIENT_API name : public super {                                                           \
+   public:                                                                                                 \
+    name(const std::string& msg, int error, const char* file, int line) noexcept                           \
+        : name(msg, error, nullptr, file, line) {}                                                         \
+    name(const std::string& msg, int error, std::exception_ptr cause, const char* file, int line) noexcept \
+        : name(#name, msg, error, cause, file, line) {}                                                    \
+                                                                                                           \
+   protected:                                                                                              \
+    name(const std::string& type,                                                                          \
+         const std::string& msg,                                                                           \
+         int error,                                                                                        \
+         std::exception_ptr cause,                                                                         \
+         const char* file,                                                                                 \
+         int line) noexcept : super(type, msg, error, cause, file, line) {}                                \
   };
 
-#define DEFINE_MQCLIENTEXCEPTION(name) DEFINE_MQCLIENTEXCEPTION2(name, MQException)
-
-DEFINE_MQCLIENTEXCEPTION(MQClientException)
-DEFINE_MQCLIENTEXCEPTION(MQBrokerException)
-DEFINE_MQCLIENTEXCEPTION(InterruptedException)
-DEFINE_MQCLIENTEXCEPTION(RemotingException)
-DEFINE_MQCLIENTEXCEPTION2(RemotingCommandException, RemotingException)
-DEFINE_MQCLIENTEXCEPTION2(RemotingConnectException, RemotingException)
-DEFINE_MQCLIENTEXCEPTION2(RemotingSendRequestException, RemotingException)
-DEFINE_MQCLIENTEXCEPTION2(RemotingTimeoutException, RemotingException)
-DEFINE_MQCLIENTEXCEPTION2(RemotingTooMuchRequestException, RemotingException)
-DEFINE_MQCLIENTEXCEPTION(UnknownHostException)
-
-#define THROW_MQEXCEPTION(e, msg, err) throw e(msg, err, __FILE__, __LINE__)
-#define NEW_MQEXCEPTION(e, msg, err) e(msg, err, __FILE__, __LINE__)
+#define DEFINE_MQEXCEPTION(name) DEFINE_MQEXCEPTION2(name, MQException)
+
+DEFINE_MQEXCEPTION(MQClientException)
+DEFINE_MQEXCEPTION(MQBrokerException)
+DEFINE_MQEXCEPTION(InterruptedException)
+DEFINE_MQEXCEPTION(RemotingException)
+DEFINE_MQEXCEPTION2(RemotingCommandException, RemotingException)
+DEFINE_MQEXCEPTION2(RemotingConnectException, RemotingException)
+DEFINE_MQEXCEPTION2(RemotingSendRequestException, RemotingException)
+DEFINE_MQEXCEPTION2(RemotingTimeoutException, RemotingException)
+DEFINE_MQEXCEPTION2(RemotingTooMuchRequestException, RemotingException)
+DEFINE_MQEXCEPTION(UnknownHostException)
+DEFINE_MQEXCEPTION(RequestTimeoutException)
+
+#define THROW_MQEXCEPTION(e, msg, err) throw e((msg), (err), __FILE__, __LINE__)
+#define THROW_MQEXCEPTION2(e, msg, err, cause) throw e((msg), (err), (cause), __FILE__, __LINE__)
+
+#define NEW_MQEXCEPTION(e, msg, err) e((msg), (err), __FILE__, __LINE__)
+#define NEW_MQEXCEPTION2(e, msg, err, cause) e((msg), (err), (cause), __FILE__, __LINE__)
 
 }  // namespace rocketmq
 
diff --git a/include/MQMessage.h b/include/MQMessage.h
index a2a819e..19f581d 100644
--- a/include/MQMessage.h
+++ b/include/MQMessage.h
@@ -30,6 +30,7 @@ namespace rocketmq {
 class MQMessage;
 typedef MQMessage* MQMessagePtr;
 typedef std::shared_ptr<MQMessage> MQMessagePtr2;
+typedef std::unique_ptr<MQMessage> MQMessagePtr3;
 
 class ROCKETMQCLIENT_API MQMessage {
  public:
diff --git a/include/MQMessageConst.h b/include/MQMessageConst.h
index 61c5c00..0657219 100644
--- a/include/MQMessageConst.h
+++ b/include/MQMessageConst.h
@@ -52,6 +52,13 @@ class ROCKETMQCLIENT_API MQMessageConst {
   static const std::string PROPERTY_TRANSACTION_CHECK_TIMES;
   static const std::string PROPERTY_CHECK_IMMUNITY_TIME_IN_SECONDS;
   static const std::string PROPERTY_INSTANCE_ID;
+  static const std::string PROPERTY_CORRELATION_ID;
+  static const std::string PROPERTY_MESSAGE_REPLY_TO_CLIENT;
+  static const std::string PROPERTY_MESSAGE_TTL;
+  static const std::string PROPERTY_REPLY_MESSAGE_ARRIVE_TIME;
+  static const std::string PROPERTY_PUSH_REPLY_TIME;
+  static const std::string PROPERTY_CLUSTER;
+  static const std::string PROPERTY_MESSAGE_TYPE;
 
   // sdk internal use only
   static const std::string PROPERTY_ALREADY_COMPRESSED_FLAG;
diff --git a/include/MQMessageExt.h b/include/MQMessageExt.h
index f142045..42e5078 100644
--- a/include/MQMessageExt.h
+++ b/include/MQMessageExt.h
@@ -42,9 +42,9 @@ class ROCKETMQCLIENT_API MQMessageExt : public MQMessage {
   MQMessageExt();
   MQMessageExt(int queueId,
                int64_t bornTimestamp,
-               sockaddr bornHost,
+               const struct sockaddr* bornHost,
                int64_t storeTimestamp,
-               sockaddr storeHost,
+               const struct sockaddr* storeHost,
                std::string msgId);
 
   virtual ~MQMessageExt();
@@ -72,16 +72,16 @@ class ROCKETMQCLIENT_API MQMessageExt : public MQMessage {
   int64_t getBornTimestamp() const;
   void setBornTimestamp(int64_t bornTimestamp);
 
-  const sockaddr& getBornHost() const;
+  const struct sockaddr* getBornHost() const;
   std::string getBornHostString() const;
-  void setBornHost(const sockaddr& bornHost);
+  void setBornHost(const struct sockaddr* bornHost);
 
   int64_t getStoreTimestamp() const;
   void setStoreTimestamp(int64_t storeTimestamp);
 
-  const sockaddr& getStoreHost() const;
+  const struct sockaddr* getStoreHost() const;
   std::string getStoreHostString() const;
-  void setStoreHost(const sockaddr& storeHost);
+  void setStoreHost(const struct sockaddr* storeHost);
 
   int32_t getReconsumeTimes() const;
   void setReconsumeTimes(int32_t reconsumeTimes);
@@ -111,15 +111,16 @@ class ROCKETMQCLIENT_API MQMessageExt : public MQMessage {
   int64_t m_commitLogOffset;
   int32_t m_sysFlag;
   int64_t m_bornTimestamp;
-  sockaddr m_bornHost;
+  struct sockaddr* m_bornHost;
   int64_t m_storeTimestamp;
-  sockaddr m_storeHost;
+  struct sockaddr* m_storeHost;
   int32_t m_reconsumeTimes;
   int64_t m_preparedTransactionOffset;
   std::string m_msgId;
 };
 
 class ROCKETMQCLIENT_API MQMessageClientExt : public MQMessageExt {
+ public:
   const std::string& getOffsetMsgId() const;
   void setOffsetMsgId(const std::string& offsetMsgId);
 
diff --git a/include/MQMessageListener.h b/include/MQMessageListener.h
index d7b700a..61bb243 100644
--- a/include/MQMessageListener.h
+++ b/include/MQMessageListener.h
@@ -30,33 +30,15 @@ enum ConsumeStatus {
   RECONSUME_LATER
 };
 
-/*enum ConsumeOrderlyStatus
-{*/
-/**
- * Success consumption
- */
-// SUCCESS,
-/**
- * Rollback consumption(only for binlog consumption)
- */
-// ROLLBACK,
-/**
- * Commit offset(only for binlog consumption)
- */
-// COMMIT,
-/**
- * Suspend current queue a moment
- */
-// SUSPEND_CURRENT_QUEUE_A_MOMENT
-/*};*/
-
 enum MessageListenerType { messageListenerDefaultly = 0, messageListenerOrderly = 1, messageListenerConcurrently = 2 };
 
 class ROCKETMQCLIENT_API MQMessageListener {
  public:
   virtual ~MQMessageListener() = default;
+
   virtual MessageListenerType getMessageListenerType() { return messageListenerDefaultly; }
 
+  // Recommended
   virtual ConsumeStatus consumeMessage(const std::vector<MQMessageExtPtr2>& msgs) {
     std::vector<MQMessageExtPtr> msgs2;
     msgs2.reserve(msgs.size());
@@ -67,7 +49,7 @@ class ROCKETMQCLIENT_API MQMessageListener {
   }
 
   // SDK will be responsible for the lifecycle of messages.
-  virtual ConsumeStatus consumeMessage(const std::vector<MQMessageExtPtr>& msgs) = 0;
+  virtual ConsumeStatus consumeMessage(const std::vector<MQMessageExtPtr>& msgs) { return RECONSUME_LATER; };
 };
 
 class ROCKETMQCLIENT_API MessageListenerConcurrently : virtual public MQMessageListener {
diff --git a/include/MQMessageQueue.h b/include/MQMessageQueue.h
index a37cdf5..8fe5940 100644
--- a/include/MQMessageQueue.h
+++ b/include/MQMessageQueue.h
@@ -44,6 +44,8 @@ class ROCKETMQCLIENT_API MQMessageQueue {
   void setQueueId(int queueId);
 
   bool operator==(const MQMessageQueue& mq) const;
+  bool operator!=(const MQMessageQueue& mq) const { return !operator==(mq); }
+
   bool operator<(const MQMessageQueue& mq) const;
   int compareTo(const MQMessageQueue& mq) const;
 
diff --git a/include/MQProducer.h b/include/MQProducer.h
index 36878d9..81a1c31 100644
--- a/include/MQProducer.h
+++ b/include/MQProducer.h
@@ -74,6 +74,9 @@ class ROCKETMQCLIENT_API MQProducer {
   virtual SendResult send(std::vector<MQMessagePtr>& msgs, long timeout) = 0;
   virtual SendResult send(std::vector<MQMessagePtr>& msgs, const MQMessageQueue& mq) = 0;
   virtual SendResult send(std::vector<MQMessagePtr>& msgs, const MQMessageQueue& mq, long timeout) = 0;
+
+  // RPC
+  virtual MQMessagePtr request(MQMessagePtr msg, long timeout) = 0;
 };
 
 }  // namespace rocketmq
diff --git a/include/MQPushConsumer.h b/include/MQPushConsumer.h
index 76d5f93..8d59f09 100644
--- a/include/MQPushConsumer.h
+++ b/include/MQPushConsumer.h
@@ -29,6 +29,8 @@ class ROCKETMQCLIENT_API MQPushConsumer : public MQConsumer {
   virtual void registerMessageListener(MessageListenerConcurrently* messageListener) = 0;
   virtual void registerMessageListener(MessageListenerOrderly* messageListener) = 0;
 
+  virtual MQMessageListener* getMessageListener() const = 0;
+
   virtual void subscribe(const std::string& topic, const std::string& subExpression) = 0;
   // virtual void subscribe(const std::string& topic, MessageSelector* selector) = 0;
 
diff --git a/include/DefaultMQConsumer.h b/include/MessageUtil.h
similarity index 64%
copy from include/DefaultMQConsumer.h
copy to include/MessageUtil.h
index 1f103ac..ad6808a 100644
--- a/include/DefaultMQConsumer.h
+++ b/include/MessageUtil.h
@@ -14,25 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __DEFAULT_MQ_CONSUMER_H__
-#define __DEFAULT_MQ_CONSUMER_H__
+#ifndef __MESSAGE_UTIL_H__
+#define __MESSAGE_UTIL_H__
 
-#include "ConsumeType.h"
-#include "MQClientConfig.h"
+#include <string>
+
+#include "MQClientException.h"
+#include "MQMessage.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQConsumerConfig : public MQClientConfig {
+class ROCKETMQCLIENT_API MessageUtil {
  public:
-  DefaultMQConsumerConfig() : m_messageModel(CLUSTERING) {}
-
-  MessageModel getMessageModel() const { return m_messageModel; }
-  void setMessageModel(MessageModel messageModel) { m_messageModel = messageModel; }
+  static MQMessagePtr createReplyMessage(const MQMessagePtr requestMessage,
+                                         const std::string& body) throw(MQClientException);
 
- protected:
-  MessageModel m_messageModel;
+  static const std::string& getReplyToClient(const MQMessagePtr msg);
 };
 
 }  // namespace rocketmq
 
-#endif  // __DEFAULT_MQ_CONSUMER_H__
+#endif  // __MESSAGE_UTIL_H__
diff --git a/include/PullResult.h b/include/PullResult.h
index d43fda2..eccf19e 100644
--- a/include/PullResult.h
+++ b/include/PullResult.h
@@ -28,12 +28,11 @@ enum PullStatus {
   FOUND,
   NO_NEW_MSG,
   NO_MATCHED_MSG,
+  NO_LATEST_MSG,
   OFFSET_ILLEGAL,
   BROKER_TIMEOUT  // indicate pull request timeout or received NULL response
 };
 
-static const char* EnumStrings[] = {"FOUND", "NO_NEW_MSG", "NO_MATCHED_MSG", "OFFSET_ILLEGAL", "BROKER_TIMEOUT"};
-
 class ROCKETMQCLIENT_API PullResult {
  public:
   PullResult();
@@ -53,13 +52,7 @@ class ROCKETMQCLIENT_API PullResult {
 
   virtual ~PullResult();
 
-  std::string toString() const {
-    std::stringstream ss;
-    ss << "PullResult [ pullStatus=" << EnumStrings[pullStatus] << ", nextBeginOffset=" << nextBeginOffset
-       << ", minOffset=" << minOffset << ", maxOffset=" << maxOffset << ", msgFoundList=" << msgFoundList.size()
-       << " ]";
-    return ss.str();
-  }
+  std::string toString() const;
 
  public:
   PullStatus pullStatus;
diff --git a/include/RemotingCommand.h b/include/RemotingCommand.h
index e204445..2fa8a27 100644
--- a/include/RemotingCommand.h
+++ b/include/RemotingCommand.h
@@ -22,14 +22,11 @@
 #include <typeindex>
 
 #include "CommandCustomHeader.h"
+#include "DataBlock.h"
 #include "MQClientException.h"
 
 namespace rocketmq {
 
-class MemoryBlock;
-typedef MemoryBlock* MemoryBlockPtr;
-typedef std::shared_ptr<MemoryBlock> MemoryBlockPtr2;
-
 class ROCKETMQCLIENT_API RemotingCommand {
  public:
   static int32_t createNewRequestId();
@@ -37,6 +34,7 @@ class ROCKETMQCLIENT_API RemotingCommand {
  public:
   RemotingCommand() : m_code(0) {}
   RemotingCommand(int32_t code, CommandCustomHeader* customHeader = nullptr);
+  RemotingCommand(int32_t code, const std::string& remark, CommandCustomHeader* customHeader = nullptr);
   RemotingCommand(int32_t code,
                   const std::string& language,
                   int32_t version,
@@ -71,13 +69,13 @@ class ROCKETMQCLIENT_API RemotingCommand {
 
   CommandCustomHeader* readCustomHeader() const;
 
-  MemoryBlockPtr2 getBody();
+  MemoryBlockPtr2 getBody() const;
   void setBody(MemoryBlock* body);
   void setBody(MemoryBlockPtr2 body);
   void setBody(const std::string& body);
 
  public:
-  MemoryBlockPtr encode();
+  MemoryBlockPtr encode() const;
 
   template <class H>
   H* decodeCommandCustomHeader(bool useCache);
@@ -85,7 +83,7 @@ class ROCKETMQCLIENT_API RemotingCommand {
   template <class H>
   H* decodeCommandCustomHeader();
 
-  static RemotingCommand* Decode(MemoryBlockPtr2& package);
+  static RemotingCommand* Decode(MemoryBlockPtr2 package, bool havePackageLen = false);
 
   std::string toString() const;
 
diff --git a/include/SendCallback.h b/include/RequestCallback.h
old mode 100755
new mode 100644
similarity index 55%
copy from include/SendCallback.h
copy to include/RequestCallback.h
index 7370250..8b31098
--- a/include/SendCallback.h
+++ b/include/RequestCallback.h
@@ -14,32 +14,35 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __SEND_CALLBACK_H__
-#define __SEND_CALLBACK_H__
+#ifndef __REQUEST_CALLBACK_H__
+#define __REQUEST_CALLBACK_H__
 
 #include "MQClientException.h"
-#include "SendResult.h"
+#include "MQMessage.h"
 
 namespace rocketmq {
 
-enum SendCallbackType { SEND_CALLBACK_TYPE_SIMPLE = 0, SEND_CALLBACK_TYPE_ATUO_DELETE = 1 };
+enum RequestCallbackType { REQUEST_CALLBACK_TYPE_SIMPLE = 0, REQUEST_CALLBACK_TYPE_AUTO_DELETE = 1 };
 
-class ROCKETMQCLIENT_API SendCallback {
+class ROCKETMQCLIENT_API RequestCallback {
  public:
-  virtual ~SendCallback() = default;
+  virtual ~RequestCallback() = default;
+
+  virtual void onSuccess(MQMessagePtr3 message) { onSuccess(message.get()); }
+
+  // SDK will be responsible for the lifecycle of message.
+  virtual void onSuccess(MQMessagePtr message) = 0;
 
-  virtual void onSuccess(SendResult& sendResult) = 0;
   virtual void onException(MQException& e) noexcept = 0;
 
-  virtual SendCallbackType getSendCallbackType() const { return SEND_CALLBACK_TYPE_SIMPLE; }
+  virtual RequestCallbackType getRequestCallbackType() const { return REQUEST_CALLBACK_TYPE_SIMPLE; }
 };
 
-// async SendCallback will be deleted automatically by rocketmq cpp after invoke callback interface
-class ROCKETMQCLIENT_API AutoDeleteSendCallback : public SendCallback {
+class ROCKETMQCLIENT_API AutoDeleteRequestCallback : public RequestCallback {
  public:
-  SendCallbackType getSendCallbackType() const override final { return SEND_CALLBACK_TYPE_ATUO_DELETE; }
+  RequestCallbackType getRequestCallbackType() const override final { return REQUEST_CALLBACK_TYPE_AUTO_DELETE; }
 };
 
 }  // namespace rocketmq
 
-#endif  // __SEND_CALLBACK_H__
+#endif  // __REQUEST_CALLBACK_H__
diff --git a/include/RocketMQClient.h b/include/RocketMQClient.h
index 09be801..fc5bb6a 100644
--- a/include/RocketMQClient.h
+++ b/include/RocketMQClient.h
@@ -37,30 +37,6 @@
 #define ROCKETMQCLIENT_API
 #endif  // WIN32
 
-/** A platform-independent 8-bit signed integer type. */
-typedef int8_t int8;
-
-/** A platform-independent 8-bit unsigned integer type. */
-typedef uint8_t uint8;
-
-/** A platform-independent 16-bit signed integer type. */
-typedef int16_t int16;
-
-/** A platform-independent 16-bit unsigned integer type. */
-typedef uint16_t uint16;
-
-/** A platform-independent 32-bit signed integer type. */
-typedef int32_t int32;
-
-/** A platform-independent 32-bit unsigned integer type. */
-typedef uint32_t uint32;
-
-/** A platform-independent 64-bit integer type. */
-typedef int64_t int64;
-
-/** A platform-independent 64-bit unsigned integer type. */
-typedef uint64_t uint64;
-
 #ifdef WIN32
 #define SIZET_FMT "%lu"
 #else
diff --git a/include/SendCallback.h b/include/SendCallback.h
index 7370250..e01f513 100755
--- a/include/SendCallback.h
+++ b/include/SendCallback.h
@@ -22,7 +22,7 @@
 
 namespace rocketmq {
 
-enum SendCallbackType { SEND_CALLBACK_TYPE_SIMPLE = 0, SEND_CALLBACK_TYPE_ATUO_DELETE = 1 };
+enum SendCallbackType { SEND_CALLBACK_TYPE_SIMPLE = 0, SEND_CALLBACK_TYPE_AUTO_DELETE = 1 };
 
 class ROCKETMQCLIENT_API SendCallback {
  public:
@@ -37,7 +37,7 @@ class ROCKETMQCLIENT_API SendCallback {
 // async SendCallback will be deleted automatically by rocketmq cpp after invoke callback interface
 class ROCKETMQCLIENT_API AutoDeleteSendCallback : public SendCallback {
  public:
-  SendCallbackType getSendCallbackType() const override final { return SEND_CALLBACK_TYPE_ATUO_DELETE; }
+  SendCallbackType getSendCallbackType() const override final { return SEND_CALLBACK_TYPE_AUTO_DELETE; }
 };
 
 }  // namespace rocketmq
diff --git a/include/SessionCredentials.h b/include/SessionCredentials.h
index 5feea08..15dd25a 100644
--- a/include/SessionCredentials.h
+++ b/include/SessionCredentials.h
@@ -34,6 +34,12 @@ class ROCKETMQCLIENT_API SessionCredentials {
   SessionCredentials() : authChannel_("ALIYUN") {}
   SessionCredentials(const std::string& accessKey, const std::string& secretKey, const std::string& authChannel)
       : accessKey_(accessKey), secretKey_(secretKey), authChannel_(authChannel) {}
+  SessionCredentials(const SessionCredentials& other)
+      : accessKey_(other.accessKey_),
+        secretKey_(other.secretKey_),
+        signature_(other.signature_),
+        signatureMethod_(other.signatureMethod_),
+        authChannel_(other.authChannel_) {}
 
   ~SessionCredentials() = default;
 
diff --git a/include/TransactionMQProducer.h b/include/TransactionMQProducer.h
index 97ce077..0a1380f 100644
--- a/include/TransactionMQProducer.h
+++ b/include/TransactionMQProducer.h
@@ -18,34 +18,25 @@
 #define __TRANSACTION_MQ_PRODUCER_H__
 
 #include "DefaultMQProducer.h"
-#include "TransactionListener.h"
+#include "TransactionMQProducerConfig.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API TransactionMQProducerConfig {
- public:
-  TransactionMQProducerConfig();
-  virtual ~TransactionMQProducerConfig() = default;
-
- public:  // TransactionMQProducerConfig
-  TransactionListener* getTransactionListener() const { return m_transactionListener; }
-  void setTransactionListener(TransactionListener* transactionListener) { m_transactionListener = transactionListener; }
-
- protected:
-  TransactionListener* m_transactionListener;
-};
-
-class ROCKETMQCLIENT_API TransactionMQProducer : public DefaultMQProducer, public TransactionMQProducerConfig {
+class ROCKETMQCLIENT_API TransactionMQProducer : public DefaultMQProducer, virtual public TransactionMQProducerConfig {
  public:
   TransactionMQProducer(const std::string& groupname);
   TransactionMQProducer(const std::string& groupname, RPCHookPtr rpcHook);
   virtual ~TransactionMQProducer();
 
+ public:  // TransactionMQProducerConfig
+  TransactionListener* getTransactionListener() const override;
+  void setTransactionListener(TransactionListener* transactionListener) override;
+
  public:  // MQProducer
   void start() override;
   void shutdown() override;
 
-  // Transaction
+  // Transaction: don't delete msg object, until callback occur.
   TransactionSendResult sendMessageInTransaction(MQMessagePtr msg, void* arg) override;
 };
 
diff --git a/include/DefaultMQConsumer.h b/include/TransactionMQProducerConfig.h
similarity index 56%
copy from include/DefaultMQConsumer.h
copy to include/TransactionMQProducerConfig.h
index 1f103ac..e341aa2 100644
--- a/include/DefaultMQConsumer.h
+++ b/include/TransactionMQProducerConfig.h
@@ -14,25 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __DEFAULT_MQ_CONSUMER_H__
-#define __DEFAULT_MQ_CONSUMER_H__
+#ifndef __TRANSACTION_MQ_PRODUCER_CONFIG_H__
+#define __TRANSACTION_MQ_PRODUCER_CONFIG_H__
 
-#include "ConsumeType.h"
-#include "MQClientConfig.h"
+#include "DefaultMQProducerConfig.h"
+#include "TransactionListener.h"
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQConsumerConfig : public MQClientConfig {
- public:
-  DefaultMQConsumerConfig() : m_messageModel(CLUSTERING) {}
+class TransactionMQProducerConfig;
+typedef std::shared_ptr<TransactionMQProducerConfig> TransactionMQProducerConfigPtr;
 
-  MessageModel getMessageModel() const { return m_messageModel; }
-  void setMessageModel(MessageModel messageModel) { m_messageModel = messageModel; }
+class ROCKETMQCLIENT_API TransactionMQProducerConfig : virtual public DefaultMQProducerConfig {
+ public:
+  virtual ~TransactionMQProducerConfig() = default;
 
- protected:
-  MessageModel m_messageModel;
+ public:  // TransactionMQProducerConfig
+  virtual TransactionListener* getTransactionListener() const = 0;
+  virtual void setTransactionListener(TransactionListener* transactionListener) = 0;
 };
 
 }  // namespace rocketmq
 
-#endif  // __DEFAULT_MQ_CONSUMER_H__
+#endif  // __TRANSACTION_MQ_PRODUCER_CONFIG_H__
diff --git a/include/c/CMessage.h b/include/c/CMessage.h
index 37feda7..7c16f15 100644
--- a/include/c/CMessage.h
+++ b/include/c/CMessage.h
@@ -23,7 +23,6 @@
 extern "C" {
 #endif
 
-// typedef struct _CMessage_ CMessage;
 typedef struct CMessage CMessage;
 
 ROCKETMQCLIENT_API CMessage* CreateMessage(const char* topic);
diff --git a/include/c/CMessageExt.h b/include/c/CMessageExt.h
index 17c0cee..bfd4343 100644
--- a/include/c/CMessageExt.h
+++ b/include/c/CMessageExt.h
@@ -23,7 +23,6 @@
 extern "C" {
 #endif
 
-// typedef struct _CMessageExt_ _CMessageExt;
 typedef struct CMessageExt CMessageExt;
 
 ROCKETMQCLIENT_API const char* GetMessageTopic(CMessageExt* msgExt);
diff --git a/include/c/CProducer.h b/include/c/CProducer.h
index b70e28e..ed8800c 100644
--- a/include/c/CProducer.h
+++ b/include/c/CProducer.h
@@ -28,7 +28,6 @@
 extern "C" {
 #endif
 
-// typedef struct _CProducer_ _CProducer;
 typedef struct CProducer CProducer;
 typedef int (*QueueSelectorCallback)(int size, CMessage* msg, void* arg);
 typedef void (*CSendSuccessCallback)(CSendResult result);
@@ -67,12 +66,12 @@ ROCKETMQCLIENT_API int SendMessageSync(CProducer* producer, CMessage* msg, CSend
 ROCKETMQCLIENT_API int SendBatchMessage(CProducer* producer, CBatchMessage* msg, CSendResult* result);
 ROCKETMQCLIENT_API int SendMessageAsync(CProducer* producer,
                                         CMessage* msg,
-                                        CSendSuccessCallback cSendSuccessCallback,
-                                        CSendExceptionCallback cSendExceptionCallback);
+                                        CSendSuccessCallback sendSuccessCallback,
+                                        CSendExceptionCallback sendExceptionCallback);
 ROCKETMQCLIENT_API int SendAsync(CProducer* producer,
                                  CMessage* msg,
-                                 COnSendSuccessCallback cSendSuccessCallback,
-                                 COnSendExceptionCallback cSendExceptionCallback,
+                                 COnSendSuccessCallback sendSuccessCallback,
+                                 COnSendExceptionCallback sendExceptionCallback,
                                  void* userData);
 ROCKETMQCLIENT_API int SendMessageOneway(CProducer* producer, CMessage* msg);
 ROCKETMQCLIENT_API int SendMessageOnewayOrderly(CProducer* producer,
@@ -90,8 +89,8 @@ ROCKETMQCLIENT_API int SendMessageOrderlyAsync(CProducer* producer,
                                                CMessage* msg,
                                                QueueSelectorCallback callback,
                                                void* arg,
-                                               CSendSuccessCallback cSendSuccessCallback,
-                                               CSendExceptionCallback cSendExceptionCallback);
+                                               CSendSuccessCallback sendSuccessCallback,
+                                               CSendExceptionCallback sendExceptionCallback);
 ROCKETMQCLIENT_API int SendMessageOrderlyByShardingKey(CProducer* producer,
                                                        CMessage* msg,
                                                        const char* shardingKey,
diff --git a/include/c/CPushConsumer.h b/include/c/CPushConsumer.h
index 3754879..4a8bd14 100644
--- a/include/c/CPushConsumer.h
+++ b/include/c/CPushConsumer.h
@@ -24,7 +24,6 @@
 extern "C" {
 #endif
 
-// typedef struct _CConsumer_ _CConsumer;
 typedef struct CPushConsumer CPushConsumer;
 
 typedef enum E_CConsumeStatus { E_CONSUME_SUCCESS = 0, E_RECONSUME_LATER = 1 } CConsumeStatus;
@@ -40,8 +39,8 @@ ROCKETMQCLIENT_API const char* GetPushConsumerGroupID(CPushConsumer* consumer);
 ROCKETMQCLIENT_API int SetPushConsumerNameServerAddress(CPushConsumer* consumer, const char* namesrv);
 ROCKETMQCLIENT_API int SetPushConsumerNameServerDomain(CPushConsumer* consumer, const char* domain);
 ROCKETMQCLIENT_API int Subscribe(CPushConsumer* consumer, const char* topic, const char* expression);
-ROCKETMQCLIENT_API int RegisterMessageCallbackOrderly(CPushConsumer* consumer, MessageCallBack pCallback);
-ROCKETMQCLIENT_API int RegisterMessageCallback(CPushConsumer* consumer, MessageCallBack pCallback);
+ROCKETMQCLIENT_API int RegisterMessageCallbackOrderly(CPushConsumer* consumer, MessageCallBack callback);
+ROCKETMQCLIENT_API int RegisterMessageCallback(CPushConsumer* consumer, MessageCallBack callback);
 ROCKETMQCLIENT_API int UnregisterMessageCallbackOrderly(CPushConsumer* consumer);
 ROCKETMQCLIENT_API int UnregisterMessageCallback(CPushConsumer* consumer);
 ROCKETMQCLIENT_API int SetPushConsumerThreadCount(CPushConsumer* consumer, int threadCount);
diff --git a/package_rocketmq.mri b/package_rocketmq.mri
deleted file mode 100644
index fc5f690..0000000
--- a/package_rocketmq.mri
+++ /dev/null
@@ -1,22 +0,0 @@
-create librocketmq.a
-addlib ../bin/lib/libboost_chrono.a
-addlib ../bin/lib/libboost_date_time.a
-addlib ../bin/lib/libboost_filesystem.a
-addlib ../bin/lib/libboost_iostreams.a
-addlib ../bin/lib/libboost_locale.a
-addlib ../bin/lib/libboost_log.a
-addlib ../bin/lib/libboost_log_setup.a
-addlib ../bin/lib/libboost_regex.a
-addlib ../bin/lib/libboost_serialization.a
-addlib ../bin/lib/libboost_system.a
-addlib ../bin/lib/libboost_thread.a
-addlib ../bin/lib/libboost_wserialization.a
-addlib ../bin/lib/libevent.a
-addlib ../bin/lib/libevent_core.a
-addlib ../bin/lib/libevent_extra.a
-addlib ../bin/lib/libevent_pthreads.a
-addlib ../bin/lib/libjsoncpp.a
-addlib ../bin/lib/libSignature.a
-addlib ../bin/librocketmq.a
-save
-end
diff --git a/project/CMakeLists.txt b/project/CMakeLists.txt
index 074d55f..c65d319 100755
--- a/project/CMakeLists.txt
+++ b/project/CMakeLists.txt
@@ -13,23 +13,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# source files
 project(rocketmq-client)
 
+option(BUILD_ROCKETMQ_STATIC "build rocketmq-client static library" OFF)
+option(BUILD_ROCKETMQ_SHARED "build rocketmq-client shared library" ON)
+
+# source files
 file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/../src/*.c*)
 list(REMOVE_ITEM SRC_FILES ${PROJECT_SOURCE_DIR}/../src/dllmain.cpp)
 
 # subdirs
-SET(SUB_DIRS)
+set(SUB_DIRS)
 file(GLOB children ${PROJECT_SOURCE_DIR}/../src/*)
-FOREACH (child ${children})
-    IF (IS_DIRECTORY ${child})
-        LIST(APPEND SUB_DIRS ${child})
-    ENDIF ()
-ENDFOREACH ()
-LIST(APPEND SUB_DIRS ${PROJECT_SOURCE_DIR}/../src)
-
-include_directories(${SUB_DIRS})
+foreach (child ${children})
+    if (IS_DIRECTORY ${child})
+        list(APPEND SUB_DIRS ${child})
+    endif ()
+endforeach ()
+list(APPEND SUB_DIRS ${PROJECT_SOURCE_DIR}/../src)
 
 # libs_directories
 file(GLOB LIB_DIRS ${PROJECT_SOURCE_DIR}/../libs/*)
@@ -45,7 +46,7 @@ if (BUILD_ROCKETMQ_STATIC)
     add_library(rocketmq_static STATIC
             ${SRC_FILES})
     target_include_directories(rocketmq_static
-            PUBLIC ${PROJECT_SOURCE_DIR}/../include)
+            PUBLIC ${CMAKE_SOURCE_DIR}/include ${SUB_DIRS} ${JSONCPP_INCLUDE_DIRS} ${LIBEVENT_INCLUDE_DIRS})
     if (spdlog_FOUND)
         target_link_libraries(rocketmq_static
                 PUBLIC ${deplibs} Signature ${JSONCPP_LIBRARIES} ${LIBEVENT_LIBRARIES} spdlog::spdlog)
@@ -65,7 +66,7 @@ if (BUILD_ROCKETMQ_SHARED)
     add_library(rocketmq_shared SHARED
             ${SRC_FILES})
     target_include_directories(rocketmq_shared
-            PUBLIC ${PROJECT_SOURCE_DIR}/../include)
+            PUBLIC ${CMAKE_SOURCE_DIR}/include ${SUB_DIRS} ${JSONCPP_INCLUDE_DIRS} ${LIBEVENT_INCLUDE_DIRS})
     if (spdlog_FOUND)
         target_link_libraries(rocketmq_shared
                 PUBLIC ${deplibs} Signature ${JSONCPP_LIBRARIES} ${LIBEVENT_LIBRARIES} spdlog::spdlog)
diff --git a/src/ClientRemotingProcessor.cpp b/src/ClientRemotingProcessor.cpp
index a998947..4f8d8a4 100644
--- a/src/ClientRemotingProcessor.cpp
+++ b/src/ClientRemotingProcessor.cpp
@@ -16,27 +16,31 @@
  */
 #include "ClientRemotingProcessor.h"
 
-#include "CommandHeader.h"
 #include "ConsumerRunningInfo.h"
 #include "MQDecoder.h"
 #include "MQProtos.h"
+#include "MessageAccessor.h"
+#include "MessageSysFlag.h"
+#include "RequestFutureTable.h"
+#include "SocketUtil.h"
+#include "protocol/body/ResetOffsetBody.h"
+#include "protocol/header/CommandHeader.h"
+#include "protocol/header/ReplyMessageRequestHeader.h"
 
 namespace rocketmq {
 
-ClientRemotingProcessor::ClientRemotingProcessor(MQClientInstance* mqClientFactory)
-    : m_mqClientFactory(mqClientFactory) {}
+ClientRemotingProcessor::ClientRemotingProcessor(MQClientInstance* clientInstance) : m_clientInstance(clientInstance) {}
 
 ClientRemotingProcessor::~ClientRemotingProcessor() = default;
 
-RemotingCommand* ClientRemotingProcessor::processRequest(const std::string& addr, RemotingCommand* request) {
-  LOG_DEBUG("request Command received:processRequest, addr:%s, code:%d", addr.data(), request->getCode());
+RemotingCommand* ClientRemotingProcessor::processRequest(TcpTransportPtr channel, RemotingCommand* request) {
+  const auto& addr = channel->getPeerAddrAndPort();
+  LOG_DEBUG_NEW("processRequest, code:{}, addr:{}", request->getCode(), addr);
   switch (request->getCode()) {
     case CHECK_TRANSACTION_STATE:
       return checkTransactionState(addr, request);
-      break;
     case NOTIFY_CONSUMER_IDS_CHANGED:
       return notifyConsumerIdsChanged(request);
-      break;
     case RESET_CONSUMER_CLIENT_OFFSET:  // oneWayRPC
       return resetOffset(request);
     case GET_CONSUMER_STATUS_FROM_CLIENT:
@@ -44,23 +48,64 @@ RemotingCommand* ClientRemotingProcessor::processRequest(const std::string& addr
       break;
     case GET_CONSUMER_RUNNING_INFO:
       return getConsumerRunningInfo(addr, request);
-      break;
     case CONSUME_MESSAGE_DIRECTLY:
       // return consumeMessageDirectly( request);
       break;
+    case PUSH_REPLY_MESSAGE_TO_CLIENT:
+      return receiveReplyMessage(request);
     default:
       break;
   }
   return nullptr;
 }
 
+RemotingCommand* ClientRemotingProcessor::checkTransactionState(const std::string& addr, RemotingCommand* request) {
+  auto* requestHeader = request->decodeCommandCustomHeader<CheckTransactionStateRequestHeader>();
+  assert(requestHeader != nullptr);
+
+  auto requestBody = request->getBody();
+  if (requestBody != nullptr && requestBody->getSize() > 0) {
+    MQMessageExtPtr2 messageExt = MQDecoder::decode(*requestBody);
+    if (messageExt != nullptr) {
+      const auto& transactionId = messageExt->getProperty(MQMessageConst::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
+      if (!transactionId.empty()) {
+        messageExt->setTransactionId(transactionId);
+      }
+      const auto& group = messageExt->getProperty(MQMessageConst::PROPERTY_PRODUCER_GROUP);
+      if (!group.empty()) {
+        auto* producer = m_clientInstance->selectProducer(group);
+        if (producer != nullptr) {
+          producer->checkTransactionState(addr, messageExt, requestHeader);
+        } else {
+          LOG_DEBUG_NEW("checkTransactionState, pick producer by group[{}] failed", group);
+        }
+      } else {
+        LOG_WARN_NEW("checkTransactionState, pick producer group failed");
+      }
+    } else {
+      LOG_WARN_NEW("checkTransactionState, decode message failed");
+    }
+  } else {
+    LOG_ERROR_NEW("checkTransactionState, request body is empty, request header: {}", requestHeader->toString());
+  }
+
+  return nullptr;
+}
+
+RemotingCommand* ClientRemotingProcessor::notifyConsumerIdsChanged(RemotingCommand* request) {
+  auto* requestHeader = request->decodeCommandCustomHeader<NotifyConsumerIdsChangedRequestHeader>();
+  LOG_INFO_NEW("notifyConsumerIdsChanged, group:{}", requestHeader->getConsumerGroup());
+  m_clientInstance->rebalanceImmediately();
+  return nullptr;
+}
+
 RemotingCommand* ClientRemotingProcessor::resetOffset(RemotingCommand* request) {
   auto* responseHeader = request->decodeCommandCustomHeader<ResetOffsetRequestHeader>();
   auto requestBody = request->getBody();
   if (requestBody != nullptr && requestBody->getSize() > 0) {
     std::unique_ptr<ResetOffsetBody> body(ResetOffsetBody::Decode(*requestBody));
     if (body != nullptr) {
-      m_mqClientFactory->resetOffset(responseHeader->getGroup(), responseHeader->getTopic(), body->getOffsetTable());
+      m_clientInstance->resetOffset(responseHeader->getGroup(), responseHeader->getTopic(), body->getOffsetTable());
     } else {
       LOG_ERROR("resetOffset failed as received data could not be unserialized");
     }
@@ -68,91 +113,97 @@ RemotingCommand* ClientRemotingProcessor::resetOffset(RemotingCommand* request)
   return nullptr;  // as resetOffset is oneWayRPC, do not need return any response
 }
 
-ResetOffsetBody* ResetOffsetBody::Decode(MemoryBlock& mem) {
-  Json::Value root = RemotingSerializable::fromJson(mem);
-  Json::Value qds = root["offsetTable"];
-  std::unique_ptr<ResetOffsetBody> body(new ResetOffsetBody());
-  for (unsigned int i = 0; i < qds.size(); i++) {
-    Json::Value qd = qds[i];
-    MQMessageQueue mq(qd["brokerName"].asString(), qd["topic"].asString(), qd["queueId"].asInt());
-    int64_t offset = qd["offset"].asInt64();
-    body->setOffsetTable(mq, offset);
-  }
-  return body.release();
-}
-
-std::map<MQMessageQueue, int64_t> ResetOffsetBody::getOffsetTable() {
-  return m_offsetTable;
-}
-
-void ResetOffsetBody::setOffsetTable(const MQMessageQueue& mq, int64_t offset) {
-  m_offsetTable[mq] = offset;
-}
-
 RemotingCommand* ClientRemotingProcessor::getConsumerRunningInfo(const std::string& addr, RemotingCommand* request) {
   auto* requestHeader = request->decodeCommandCustomHeader<GetConsumerRunningInfoRequestHeader>();
-  LOG_INFO("getConsumerRunningInfo:%s", requestHeader->getConsumerGroup().c_str());
+  LOG_INFO("getConsumerRunningInfo, group:{}", requestHeader->getConsumerGroup());
 
-  RemotingCommand* response =
-      new RemotingCommand(request->getCode(), "CPP", request->getVersion(), request->getOpaque(), request->getFlag(),
-                          request->getRemark(), nullptr);
+  std::unique_ptr<RemotingCommand> response(
+      new RemotingCommand(MQResponseCode::SYSTEM_ERROR, "not set any response code"));
 
   std::unique_ptr<ConsumerRunningInfo> runningInfo(
-      m_mqClientFactory->consumerRunningInfo(requestHeader->getConsumerGroup()));
+      m_clientInstance->consumerRunningInfo(requestHeader->getConsumerGroup()));
   if (runningInfo != nullptr) {
     if (requestHeader->isJstackEnable()) {
       /*string jstack = UtilAll::jstack();
        consumerRunningInfo->setJstack(jstack);*/
     }
-    response->setCode(SUCCESS_VALUE);
-    std::string body = runningInfo->encode();
+    response->setCode(SUCCESS);
+    auto body = runningInfo->encode();
     response->setBody(body);
   } else {
     response->setCode(SYSTEM_ERROR);
     response->setRemark("The Consumer Group not exist in this consumer");
   }
 
-  return response;
+  return response.release();
 }
 
-RemotingCommand* ClientRemotingProcessor::notifyConsumerIdsChanged(RemotingCommand* request) {
-  auto* requestHeader = request->decodeCommandCustomHeader<NotifyConsumerIdsChangedRequestHeader>();
-  LOG_INFO("notifyConsumerIdsChanged:%s", requestHeader->getConsumerGroup().c_str());
-  m_mqClientFactory->rebalanceImmediately();
-  return nullptr;
-}
+RemotingCommand* ClientRemotingProcessor::receiveReplyMessage(RemotingCommand* request) {
+  std::unique_ptr<RemotingCommand> response(
+      new RemotingCommand(MQResponseCode::SYSTEM_ERROR, "not set any response code"));
 
-RemotingCommand* ClientRemotingProcessor::checkTransactionState(const std::string& addr, RemotingCommand* request) {
-  auto* requestHeader = request->decodeCommandCustomHeader<CheckTransactionStateRequestHeader>();
-  assert(requestHeader != nullptr);
+  auto receiveTime = UtilAll::currentTimeMillis();
+  auto* requestHeader = request->decodeCommandCustomHeader<ReplyMessageRequestHeader>();
 
-  auto requestBody = request->getBody();
-  if (requestBody != nullptr && requestBody->getSize() > 0) {
-    MQMessageExtPtr2 messageExt = MQDecoder::decode(*requestBody);
-    if (messageExt != nullptr) {
-      const auto& transactionId = messageExt->getProperty(MQMessageConst::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
-      if (!transactionId.empty()) {
-        messageExt->setTransactionId(transactionId);
-      }
-      const auto& group = messageExt->getProperty(MQMessageConst::PROPERTY_PRODUCER_GROUP);
-      if (!group.empty()) {
-        auto* producer = m_mqClientFactory->selectProducer(group);
-        if (producer != nullptr) {
-          producer->checkTransactionState(addr, messageExt, requestHeader);
-        } else {
-          LOG_DEBUG_NEW("checkTransactionState, pick producer by group[{}] failed", group);
-        }
+  try {
+    std::unique_ptr<MQMessageExt> msg(new MQMessageExt);
+
+    msg->setTopic(requestHeader->getTopic());
+    msg->setQueueId(requestHeader->getQueueId());
+    msg->setStoreTimestamp(requestHeader->getStoreTimestamp());
+
+    if (!requestHeader->getBornHost().empty()) {
+      msg->setBornHost(string2SocketAddress(requestHeader->getBornHost()));
+    }
+
+    if (!requestHeader->getStoreHost().empty()) {
+      msg->setStoreHost(string2SocketAddress(requestHeader->getStoreHost()));
+    }
+
+    auto body = request->getBody();
+    if ((requestHeader->getSysFlag() & MessageSysFlag::CompressedFlag) == MessageSysFlag::CompressedFlag) {
+      std::string outbody;
+      if (UtilAll::inflate(body->getData(), body->getSize(), outbody)) {
+        msg->setBody(std::move(outbody));
       } else {
-        LOG_WARN_NEW("checkTransactionState, pick producer group failed");
+        LOG_WARN_NEW("err when uncompress constant");
       }
     } else {
-      LOG_WARN_NEW("checkTransactionState, decode message failed");
+      msg->setBody(body->getData(), body->getSize());
     }
-  } else {
-    LOG_ERROR_NEW("checkTransactionState, request body is empty, request header: {}", requestHeader->toString());
+
+    msg->setFlag(requestHeader->getFlag());
+    MessageAccessor::setProperties(*msg, MQDecoder::string2messageProperties(requestHeader->getProperties()));
+    MessageAccessor::putProperty(*msg, MQMessageConst::PROPERTY_REPLY_MESSAGE_ARRIVE_TIME,
+                                 UtilAll::to_string(receiveTime));
+    msg->setBornTimestamp(requestHeader->getBornTimestamp());
+    msg->setReconsumeTimes(requestHeader->getReconsumeTimes());
+    LOG_DEBUG_NEW("receive reply message:{}", msg->toString());
+
+    processReplyMessage(std::move(msg));
+
+    response->setCode(MQResponseCode::SUCCESS);
+    response->setRemark(null);
+  } catch (const std::exception& e) {
+    LOG_WARN_NEW("unknown err when receiveReplyMsg, {}", e.what());
+    response->setCode(MQResponseCode::SYSTEM_ERROR);
+    response->setRemark("process reply message fail");
   }
 
-  return nullptr;
+  return response.release();
+}
+
+void ClientRemotingProcessor::processReplyMessage(std::unique_ptr<MQMessageExt> replyMsg) {
+  const auto& correlationId = replyMsg->getProperty(MQMessageConst::PROPERTY_CORRELATION_ID);
+  auto requestResponseFuture = RequestFutureTable::removeRequestFuture(correlationId);
+  if (requestResponseFuture != nullptr) {
+    requestResponseFuture->putResponseMessage(std::move(replyMsg));
+    requestResponseFuture->executeRequestCallback();
+  } else {
+    auto bornHost = replyMsg->getBornHostString();
+    LOG_WARN_NEW("receive reply message, but not matched any request, CorrelationId: {} , reply from host: {}",
+                 correlationId, bornHost);
+  }
 }
 
 }  // namespace rocketmq
diff --git a/src/ClientRemotingProcessor.h b/src/ClientRemotingProcessor.h
index efcb5fc..e758cbc 100644
--- a/src/ClientRemotingProcessor.h
+++ b/src/ClientRemotingProcessor.h
@@ -25,29 +25,22 @@ namespace rocketmq {
 
 class ClientRemotingProcessor : public RequestProcessor {
  public:
-  ClientRemotingProcessor(MQClientInstance* mqClientFactory);
+  ClientRemotingProcessor(MQClientInstance* clientInstance);
   virtual ~ClientRemotingProcessor();
 
-  RemotingCommand* processRequest(const std::string& addr, RemotingCommand* request) override;
+  RemotingCommand* processRequest(TcpTransportPtr channel, RemotingCommand* request) override;
 
+  RemotingCommand* checkTransactionState(const std::string& addr, RemotingCommand* request);
+  RemotingCommand* notifyConsumerIdsChanged(RemotingCommand* request);
   RemotingCommand* resetOffset(RemotingCommand* request);
   RemotingCommand* getConsumerRunningInfo(const std::string& addr, RemotingCommand* request);
-  RemotingCommand* notifyConsumerIdsChanged(RemotingCommand* request);
-  RemotingCommand* checkTransactionState(const std::string& addr, RemotingCommand* request);
+  RemotingCommand* receiveReplyMessage(RemotingCommand* request);
 
  private:
-  MQClientInstance* m_mqClientFactory;
-};
-
-class ResetOffsetBody {
- public:
-  static ResetOffsetBody* Decode(MemoryBlock& mem);
-
-  std::map<MQMessageQueue, int64_t> getOffsetTable();
-  void setOffsetTable(const MQMessageQueue& mq, int64_t offset);
+  void processReplyMessage(std::unique_ptr<MQMessageExt> replyMsg);
 
  private:
-  std::map<MQMessageQueue, int64_t> m_offsetTable;
+  MQClientInstance* m_clientInstance;
 };
 
 }  // namespace rocketmq
diff --git a/src/MQAdminImpl.cpp b/src/MQAdminImpl.cpp
index ea0651f..be67fce 100644
--- a/src/MQAdminImpl.cpp
+++ b/src/MQAdminImpl.cpp
@@ -27,9 +27,9 @@ void MQAdminImpl::createTopic(const std::string& key, const std::string& newTopi
 void MQAdminImpl::fetchSubscribeMessageQueues(const std::string& topic, std::vector<MQMessageQueue>& mqs) {
   try {
     TopicRouteDataPtr topicRouteData(
-        m_mqClientFactory->getMQClientAPIImpl()->getTopicRouteInfoFromNameServer(topic, 1000 * 3));
+        m_clientInstance->getMQClientAPIImpl()->getTopicRouteInfoFromNameServer(topic, 1000 * 3));
     if (topicRouteData != nullptr) {
-      mqs = m_mqClientFactory->topicRouteData2TopicSubscribeInfo(topic, topicRouteData);
+      mqs = m_clientInstance->topicRouteData2TopicSubscribeInfo(topic, topicRouteData);
       if (!mqs.empty()) {
         return;
       } else {
@@ -45,16 +45,16 @@ void MQAdminImpl::fetchSubscribeMessageQueues(const std::string& topic, std::vec
 }
 
 int64_t MQAdminImpl::searchOffset(const MQMessageQueue& mq, int64_t timestamp) {
-  std::string brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+  std::string brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   if (brokerAddr.empty()) {
-    m_mqClientFactory->updateTopicRouteInfoFromNameServer(mq.getTopic());
-    brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+    m_clientInstance->updateTopicRouteInfoFromNameServer(mq.getTopic());
+    brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   }
 
   if (!brokerAddr.empty()) {
     try {
-      return m_mqClientFactory->getMQClientAPIImpl()->searchOffset(brokerAddr, mq.getTopic(), mq.getQueueId(),
-                                                                   timestamp, 1000 * 3);
+      return m_clientInstance->getMQClientAPIImpl()->searchOffset(brokerAddr, mq.getTopic(), mq.getQueueId(), timestamp,
+                                                                  1000 * 3);
     } catch (MQException& e) {
       THROW_MQEXCEPTION(MQClientException, "Invoke Broker exception", -1);
     }
@@ -63,16 +63,15 @@ int64_t MQAdminImpl::searchOffset(const MQMessageQueue& mq, int64_t timestamp) {
 }
 
 int64_t MQAdminImpl::maxOffset(const MQMessageQueue& mq) {
-  std::string brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+  std::string brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   if (brokerAddr.empty()) {
-    m_mqClientFactory->updateTopicRouteInfoFromNameServer(mq.getTopic());
-    brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+    m_clientInstance->updateTopicRouteInfoFromNameServer(mq.getTopic());
+    brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   }
 
   if (!brokerAddr.empty()) {
     try {
-      return m_mqClientFactory->getMQClientAPIImpl()->getMaxOffset(brokerAddr, mq.getTopic(), mq.getQueueId(),
-                                                                   1000 * 3);
+      return m_clientInstance->getMQClientAPIImpl()->getMaxOffset(brokerAddr, mq.getTopic(), mq.getQueueId(), 1000 * 3);
     } catch (MQException& e) {
       THROW_MQEXCEPTION(MQClientException, "Invoke Broker exception", -1);
     }
@@ -81,16 +80,15 @@ int64_t MQAdminImpl::maxOffset(const MQMessageQueue& mq) {
 }
 
 int64_t MQAdminImpl::minOffset(const MQMessageQueue& mq) {
-  std::string brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+  std::string brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   if (brokerAddr.empty()) {
-    m_mqClientFactory->updateTopicRouteInfoFromNameServer(mq.getTopic());
-    brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+    m_clientInstance->updateTopicRouteInfoFromNameServer(mq.getTopic());
+    brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   }
 
   if (!brokerAddr.empty()) {
     try {
-      return m_mqClientFactory->getMQClientAPIImpl()->getMinOffset(brokerAddr, mq.getTopic(), mq.getQueueId(),
-                                                                   1000 * 3);
+      return m_clientInstance->getMQClientAPIImpl()->getMinOffset(brokerAddr, mq.getTopic(), mq.getQueueId(), 1000 * 3);
     } catch (const std::exception& e) {
       THROW_MQEXCEPTION(MQClientException, "Invoke Broker[" + brokerAddr + "] exception", -1);
     }
@@ -100,16 +98,16 @@ int64_t MQAdminImpl::minOffset(const MQMessageQueue& mq) {
 }
 
 int64_t MQAdminImpl::earliestMsgStoreTime(const MQMessageQueue& mq) {
-  std::string brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+  std::string brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   if (brokerAddr.empty()) {
-    m_mqClientFactory->updateTopicRouteInfoFromNameServer(mq.getTopic());
-    brokerAddr = m_mqClientFactory->findBrokerAddressInPublish(mq.getBrokerName());
+    m_clientInstance->updateTopicRouteInfoFromNameServer(mq.getTopic());
+    brokerAddr = m_clientInstance->findBrokerAddressInPublish(mq.getBrokerName());
   }
 
   if (!brokerAddr.empty()) {
     try {
-      return m_mqClientFactory->getMQClientAPIImpl()->getEarliestMsgStoretime(brokerAddr, mq.getTopic(),
-                                                                              mq.getQueueId(), 1000 * 3);
+      return m_clientInstance->getMQClientAPIImpl()->getEarliestMsgStoretime(brokerAddr, mq.getTopic(), mq.getQueueId(),
+                                                                             1000 * 3);
     } catch (MQException& e) {
       THROW_MQEXCEPTION(MQClientException, "Invoke Broker exception", -1);
     }
diff --git a/src/MQAdminImpl.h b/src/MQAdminImpl.h
index 244d9a3..ee3d18d 100644
--- a/src/MQAdminImpl.h
+++ b/src/MQAdminImpl.h
@@ -29,7 +29,7 @@ namespace rocketmq {
 
 class MQAdminImpl {
  public:
-  MQAdminImpl(MQClientInstance* mqClientFactory) : m_mqClientFactory(mqClientFactory) {}
+  MQAdminImpl(MQClientInstance* clientInstance) : m_clientInstance(clientInstance) {}
 
   void createTopic(const std::string& key, const std::string& newTopic, int queueNum);
 
@@ -38,13 +38,13 @@ class MQAdminImpl {
   int64_t searchOffset(const MQMessageQueue& mq, int64_t timestamp);
   int64_t maxOffset(const MQMessageQueue& mq);
   int64_t minOffset(const MQMessageQueue& mq);
-  int64_t earliestMsgStoreTime(const MQMessageQueue& mqClientFactory);
+  int64_t earliestMsgStoreTime(const MQMessageQueue& mq);
 
   MQMessageExtPtr viewMessage(const std::string& msgId);
   QueryResult queryMessage(const std::string& topic, const std::string& key, int maxNum, int64_t begin, int64_t end);
 
  private:
-  MQClientInstance* m_mqClientFactory;
+  MQClientInstance* m_clientInstance;
 };
 
 }  // namespace rocketmq
diff --git a/src/MQClientAPIImpl.cpp b/src/MQClientAPIImpl.cpp
index 22d937a..53da586 100644
--- a/src/MQClientAPIImpl.cpp
+++ b/src/MQClientAPIImpl.cpp
@@ -32,18 +32,19 @@
 namespace rocketmq {
 
 MQClientAPIImpl::MQClientAPIImpl(ClientRemotingProcessor* clientRemotingProcessor,
-                                 std::shared_ptr<RPCHook> rpcHook,
-                                 const MQClientConfig* clientConfig)
-    : m_remotingClient(new TcpRemotingClient(clientConfig->getTcpTransportWorkerThreadNum(),
-                                             clientConfig->getTcpTransportConnectTimeout(),
-                                             clientConfig->getTcpTransportTryLockTimeout())) {
+                                 RPCHookPtr rpcHook,
+                                 const MQClientConfig& clientConfig)
+    : m_remotingClient(new TcpRemotingClient(clientConfig.getTcpTransportWorkerThreadNum(),
+                                             clientConfig.getTcpTransportConnectTimeout(),
+                                             clientConfig.getTcpTransportTryLockTimeout())) {
   m_remotingClient->registerRPCHook(rpcHook);
   m_remotingClient->registerProcessor(CHECK_TRANSACTION_STATE, clientRemotingProcessor);
+  m_remotingClient->registerProcessor(NOTIFY_CONSUMER_IDS_CHANGED, clientRemotingProcessor);
   m_remotingClient->registerProcessor(RESET_CONSUMER_CLIENT_OFFSET, clientRemotingProcessor);
   m_remotingClient->registerProcessor(GET_CONSUMER_STATUS_FROM_CLIENT, clientRemotingProcessor);
   m_remotingClient->registerProcessor(GET_CONSUMER_RUNNING_INFO, clientRemotingProcessor);
-  m_remotingClient->registerProcessor(NOTIFY_CONSUMER_IDS_CHANGED, clientRemotingProcessor);
   m_remotingClient->registerProcessor(CONSUME_MESSAGE_DIRECTLY, clientRemotingProcessor);
+  m_remotingClient->registerProcessor(PUSH_REPLY_MESSAGE_TO_CLIENT, clientRemotingProcessor);
 }
 
 MQClientAPIImpl::~MQClientAPIImpl() = default;
@@ -57,13 +58,11 @@ void MQClientAPIImpl::shutdown() {
 }
 
 void MQClientAPIImpl::updateNameServerAddr(const std::string& addrs) {
-  if (m_remotingClient != nullptr) {
-    m_remotingClient->updateNameServerAddressList(addrs);
-  }
+  m_remotingClient->updateNameServerAddressList(addrs);
 }
 
 void MQClientAPIImpl::createTopic(const std::string& addr, const std::string& defaultTopic, TopicConfig topicConfig) {
-  CreateTopicRequestHeader* requestHeader = new CreateTopicRequestHeader();
+  auto* requestHeader = new CreateTopicRequestHeader();
   requestHeader->topic = topicConfig.getTopicName();
   requestHeader->defaultTopic = defaultTopic;
   requestHeader->readQueueNums = topicConfig.getReadQueueNums();
@@ -76,7 +75,7 @@ void MQClientAPIImpl::createTopic(const std::string& addr, const std::string& de
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       return;
     }
     default:
@@ -111,8 +110,17 @@ SendResult* MQClientAPIImpl::sendMessage(const std::string& addr,
   int code = SEND_MESSAGE;
   std::unique_ptr<CommandCustomHeader> header;
 
-  if (msg->isBatch()) {
+  const auto& msgType = msg->getProperty(MQMessageConst::PROPERTY_MESSAGE_TYPE);
+  bool isReply = msgType == REPLY_MESSAGE_FLAG;
+  if (isReply) {
+    code = SEND_REPLY_MESSAGE_V2;
+  } else if (msg->isBatch()) {
     code = SEND_BATCH_MESSAGE;
+  } else {
+    code = SEND_MESSAGE_V2;
+  }
+
+  if (code != SEND_MESSAGE && code != SEND_REPLY_MESSAGE) {
     header.reset(SendMessageRequestHeaderV2::createSendMessageRequestHeaderV2(requestHeader.get()));
   } else {
     header = std::move(requestHeader);
@@ -150,8 +158,8 @@ void MQClientAPIImpl::sendMessageAsync(const std::string& addr,
                                        int retryTimesWhenSendFailed,
                                        DefaultMQProducerImplPtr producer) throw(RemotingException) {
   // delete in future
-  auto cbw = new SendCallbackWrap(addr, brokerName, msg, std::forward<RemotingCommand>(request), sendCallback,
-                                  topicPublishInfo, instance, retryTimesWhenSendFailed, 0, producer);
+  auto* cbw = new SendCallbackWrap(addr, brokerName, msg, std::forward<RemotingCommand>(request), sendCallback,
+                                   topicPublishInfo, instance, retryTimesWhenSendFailed, 0, producer);
 
   try {
     sendMessageAsyncImpl(cbw, timeoutMillis);
@@ -192,7 +200,7 @@ SendResult* MQClientAPIImpl::processSendResponse(const std::string& brokerName,
     case SLAVE_NOT_AVAILABLE:
       sendStatus = SEND_SLAVE_NOT_AVAILABLE;
       break;
-    case SUCCESS_VALUE:
+    case SUCCESS:
       sendStatus = SEND_OK;
       break;
     default:
@@ -212,9 +220,11 @@ SendResult* MQClientAPIImpl::processSendResponse(const std::string& brokerName,
     const auto& messages = static_cast<const MessageBatch*>(msg)->getMessages();
     uniqMsgId.clear();
     uniqMsgId.reserve(33 * messages.size());
+    bool isFirst = true;
     for (const auto& message : messages) {
-      if (!uniqMsgId.empty()) {
+      if (!isFirst) {
         uniqMsgId.append(",");
+        isFirst = false;
       }
       uniqMsgId.append(MessageClientIDSetter::getUniqID(*message));
     }
@@ -270,14 +280,18 @@ PullResult* MQClientAPIImpl::pullMessageSync(const std::string& addr, RemotingCo
 PullResult* MQClientAPIImpl::processPullResponse(RemotingCommand* response) {
   PullStatus pullStatus = NO_NEW_MSG;
   switch (response->getCode()) {
-    case SUCCESS_VALUE:
+    case SUCCESS:
       pullStatus = FOUND;
       break;
     case PULL_NOT_FOUND:
       pullStatus = NO_NEW_MSG;
       break;
     case PULL_RETRY_IMMEDIATELY:
-      pullStatus = NO_MATCHED_MSG;
+      if ("OFFSET_OVERFLOW_BADLY" == response->getRemark()) {
+        pullStatus = NO_LATEST_MSG;
+      } else {
+        pullStatus = NO_MATCHED_MSG;
+      }
       break;
     case PULL_OFFSET_MOVED:
       pullStatus = OFFSET_ILLEGAL;
@@ -295,7 +309,7 @@ PullResult* MQClientAPIImpl::processPullResponse(RemotingCommand* response) {
 }
 
 MQMessageExtPtr MQClientAPIImpl::viewMessage(const std::string& addr, int64_t phyoffset, int timeoutMillis) {
-  ViewMessageRequestHeader* requestHeader = new ViewMessageRequestHeader();
+  auto* requestHeader = new ViewMessageRequestHeader();
   requestHeader->offset = phyoffset;
 
   RemotingCommand request(VIEW_MESSAGE_BY_ID, requestHeader);
@@ -303,7 +317,7 @@ MQMessageExtPtr MQClientAPIImpl::viewMessage(const std::string& addr, int64_t ph
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       // TODO: ...
     }
     default:
@@ -318,7 +332,7 @@ int64_t MQClientAPIImpl::searchOffset(const std::string& addr,
                                       int queueId,
                                       uint64_t timestamp,
                                       int timeoutMillis) {
-  SearchOffsetRequestHeader* requestHeader = new SearchOffsetRequestHeader();
+  auto* requestHeader = new SearchOffsetRequestHeader();
   requestHeader->topic = topic;
   requestHeader->queueId = queueId;
   requestHeader->timestamp = timestamp;
@@ -328,7 +342,7 @@ int64_t MQClientAPIImpl::searchOffset(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto* responseHeader = response->decodeCommandCustomHeader<SearchOffsetResponseHeader>();
       assert(responseHeader != nullptr);
       return responseHeader->offset;
@@ -344,7 +358,7 @@ int64_t MQClientAPIImpl::getMaxOffset(const std::string& addr,
                                       const std::string& topic,
                                       int queueId,
                                       int timeoutMillis) {
-  GetMaxOffsetRequestHeader* requestHeader = new GetMaxOffsetRequestHeader();
+  auto* requestHeader = new GetMaxOffsetRequestHeader();
   requestHeader->topic = topic;
   requestHeader->queueId = queueId;
 
@@ -353,7 +367,7 @@ int64_t MQClientAPIImpl::getMaxOffset(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto* responseHeader = response->decodeCommandCustomHeader<GetMaxOffsetResponseHeader>(GET_MAX_OFFSET);
       return responseHeader->offset;
     }
@@ -368,7 +382,7 @@ int64_t MQClientAPIImpl::getMinOffset(const std::string& addr,
                                       const std::string& topic,
                                       int queueId,
                                       int timeoutMillis) {
-  GetMinOffsetRequestHeader* requestHeader = new GetMinOffsetRequestHeader();
+  auto* requestHeader = new GetMinOffsetRequestHeader();
   requestHeader->topic = topic;
   requestHeader->queueId = queueId;
 
@@ -377,7 +391,7 @@ int64_t MQClientAPIImpl::getMinOffset(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto* responseHeader = response->decodeCommandCustomHeader<GetMinOffsetResponseHeader>();
       assert(responseHeader != nullptr);
       return responseHeader->offset;
@@ -393,7 +407,7 @@ int64_t MQClientAPIImpl::getEarliestMsgStoretime(const std::string& addr,
                                                  const std::string& topic,
                                                  int queueId,
                                                  int timeoutMillis) {
-  GetEarliestMsgStoretimeRequestHeader* requestHeader = new GetEarliestMsgStoretimeRequestHeader();
+  auto* requestHeader = new GetEarliestMsgStoretimeRequestHeader();
   requestHeader->topic = topic;
   requestHeader->queueId = queueId;
 
@@ -402,7 +416,7 @@ int64_t MQClientAPIImpl::getEarliestMsgStoretime(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto* responseHeader = response->decodeCommandCustomHeader<GetEarliestMsgStoretimeResponseHeader>();
       assert(responseHeader != nullptr);
       return responseHeader->timestamp;
@@ -418,7 +432,7 @@ void MQClientAPIImpl::getConsumerIdListByGroup(const std::string& addr,
                                                const std::string& consumerGroup,
                                                std::vector<std::string>& cids,
                                                int timeoutMillis) {
-  GetConsumerListByGroupRequestHeader* requestHeader = new GetConsumerListByGroupRequestHeader();
+  auto* requestHeader = new GetConsumerListByGroupRequestHeader();
   requestHeader->consumerGroup = consumerGroup;
 
   RemotingCommand request(GET_CONSUMER_LIST_BY_GROUP, requestHeader);
@@ -426,15 +440,17 @@ void MQClientAPIImpl::getConsumerIdListByGroup(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto responseBody = response->getBody();
       if (responseBody != nullptr && responseBody->getSize() > 0) {
         std::unique_ptr<GetConsumerListByGroupResponseBody> body(
             GetConsumerListByGroupResponseBody::Decode(*responseBody));
-        cids = body->consumerIdList;
+        cids = std::move(body->consumerIdList);
         return;
       }
     }
+    case SYSTEM_ERROR:
+    // no consumer for this group
     default:
       break;
   }
@@ -450,7 +466,7 @@ int64_t MQClientAPIImpl::queryConsumerOffset(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto* responseHeader = response->decodeCommandCustomHeader<QueryConsumerOffsetResponseHeader>();
       assert(responseHeader != nullptr);
       return responseHeader->offset;
@@ -470,7 +486,7 @@ void MQClientAPIImpl::updateConsumerOffset(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       return;
     }
     default:
@@ -488,15 +504,15 @@ void MQClientAPIImpl::updateConsumerOffsetOneway(const std::string& addr,
   m_remotingClient->invokeOneway(addr, request);
 }
 
-void MQClientAPIImpl::sendHearbeat(const std::string& addr, HeartbeatData* heartbeatData) {
+void MQClientAPIImpl::sendHearbeat(const std::string& addr, HeartbeatData* heartbeatData, long timeoutMillis) {
   RemotingCommand request(HEART_BEAT, nullptr);
   request.setBody(heartbeatData->encode());
 
-  std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request));
+  std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
-      LOG_INFO("sendheartbeat to broker:%s success", addr.c_str());
+    case SUCCESS: {
+      LOG_DEBUG_NEW("sendHeartbeat to broker:{} success", addr);
       return;
     }
     default:
@@ -516,7 +532,7 @@ void MQClientAPIImpl::unregisterClient(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE:
+    case SUCCESS:
       LOG_INFO("unregisterClient to:%s success", addr.c_str());
       return;
     default:
@@ -542,7 +558,7 @@ void MQClientAPIImpl::consumerSendMessageBack(const std::string& addr,
                                               int delayLevel,
                                               int timeoutMillis,
                                               int maxConsumeRetryTimes) {
-  ConsumerSendMsgBackRequestHeader* requestHeader = new ConsumerSendMsgBackRequestHeader();
+  auto* requestHeader = new ConsumerSendMsgBackRequestHeader();
   requestHeader->group = consumerGroup;
   requestHeader->originTopic = msg.getTopic();
   requestHeader->offset = msg.getCommitLogOffset();
@@ -555,7 +571,7 @@ void MQClientAPIImpl::consumerSendMessageBack(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       return;
     }
     default:
@@ -575,7 +591,7 @@ void MQClientAPIImpl::lockBatchMQ(const std::string& addr,
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto requestBody = response->getBody();
       if (requestBody != nullptr && requestBody->getSize() > 0) {
         std::unique_ptr<LockBatchResponseBody> body(LockBatchResponseBody::Decode(*requestBody));
@@ -605,7 +621,7 @@ void MQClientAPIImpl::unlockBatchMQ(const std::string& addr,
     std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(addr, request, timeoutMillis));
     assert(response != nullptr);
     switch (response->getCode()) {
-      case SUCCESS_VALUE: {
+      case SUCCESS: {
         return;
       } break;
       default:
@@ -625,7 +641,7 @@ TopicRouteData* MQClientAPIImpl::getTopicRouteInfoFromNameServer(const std::stri
     case TOPIC_NOT_EXIST: {
       break;
     }
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto responseBody = response->getBody();
       if (responseBody != nullptr && responseBody->getSize() > 0) {
         return TopicRouteData::Decode(*responseBody);
@@ -644,7 +660,7 @@ TopicList* MQClientAPIImpl::getTopicListFromNameServer() {
   std::unique_ptr<RemotingCommand> response(m_remotingClient->invokeSync(null, request));
   assert(response != nullptr);
   switch (response->getCode()) {
-    case SUCCESS_VALUE: {
+    case SUCCESS: {
       auto responseBody = response->getBody();
       if (responseBody != nullptr && responseBody->getSize() > 0) {
         return TopicList::Decode(*responseBody);
diff --git a/src/MQClientAPIImpl.h b/src/MQClientAPIImpl.h
index 0b38447..b2f94fa 100644
--- a/src/MQClientAPIImpl.h
+++ b/src/MQClientAPIImpl.h
@@ -17,12 +17,10 @@
 #ifndef __MQ_CLIENT_API_IMPL_H__
 #define __MQ_CLIENT_API_IMPL_H__
 
-#include "CommandHeader.h"
 #include "CommunicationMode.h"
 #include "DefaultMQProducerImpl.h"
 #include "HeartbeatData.h"
 #include "KVTable.h"
-#include "LockBatchBody.h"
 #include "MQClientException.h"
 #include "MQClientInstance.h"
 #include "MQMessageExt.h"
@@ -33,6 +31,8 @@
 #include "TopicList.h"
 #include "TopicPublishInfo.h"
 #include "TopicRouteData.h"
+#include "protocol/body/LockBatchBody.h"
+#include "protocol/header/CommandHeader.h"
 
 namespace rocketmq {
 
@@ -47,8 +47,8 @@ class SendCallbackWrap;
 class MQClientAPIImpl {
  public:
   MQClientAPIImpl(ClientRemotingProcessor* clientRemotingProcessor,
-                  std::shared_ptr<RPCHook> rpcHook,
-                  const MQClientConfig* clientConfig);
+                  RPCHookPtr rpcHook,
+                  const MQClientConfig& clientConfig);
   virtual ~MQClientAPIImpl();
 
   void start();
@@ -79,7 +79,7 @@ class MQClientAPIImpl {
   SendResult* processSendResponse(const std::string& brokerName, const MQMessagePtr msg, RemotingCommand* pResponse);
 
   PullResult* pullMessage(const std::string& addr,
-                          PullMessageRequestHeader* pRequestHeader,
+                          PullMessageRequestHeader* requestHeader,
                           int timeoutMillis,
                           CommunicationMode communicationMode,
                           PullCallback* pullCallback);
@@ -104,17 +104,17 @@ class MQClientAPIImpl {
                                 int timeoutMillis);
 
   int64_t queryConsumerOffset(const std::string& addr,
-                              QueryConsumerOffsetRequestHeader* pRequestHeader,
+                              QueryConsumerOffsetRequestHeader* requestHeader,
                               int timeoutMillis);
 
   void updateConsumerOffset(const std::string& addr,
-                            UpdateConsumerOffsetRequestHeader* pRequestHeader,
+                            UpdateConsumerOffsetRequestHeader* requestHeader,
                             int timeoutMillis);
   void updateConsumerOffsetOneway(const std::string& addr,
-                                  UpdateConsumerOffsetRequestHeader* pRequestHeader,
+                                  UpdateConsumerOffsetRequestHeader* requestHeader,
                                   int timeoutMillis);
 
-  void sendHearbeat(const std::string& addr, HeartbeatData* pHeartbeatData);
+  void sendHearbeat(const std::string& addr, HeartbeatData* heartbeatData, long timeoutMillis);
   void unregisterClient(const std::string& addr,
                         const std::string& clientID,
                         const std::string& producerGroup,
@@ -192,7 +192,6 @@ class MQClientAPIImpl {
 
  private:
   std::unique_ptr<TcpRemotingClient> m_remotingClient;
-  std::string m_nameSrvAddr;
 };
 
 }  // namespace rocketmq
diff --git a/src/MQClientConfig.cpp b/src/MQClientConfigImpl.cpp
similarity index 65%
rename from src/MQClientConfig.cpp
rename to src/MQClientConfigImpl.cpp
index 7495d03..b8a24f8 100644
--- a/src/MQClientConfig.cpp
+++ b/src/MQClientConfigImpl.cpp
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "MQClientConfig.h"
+#include "MQClientConfigImpl.h"
 
 #include <algorithm>
 #include <thread>
@@ -26,7 +26,7 @@ namespace rocketmq {
 
 static const std::string DEFAULT_INSTANCE_NAME = "DEFAULT";
 
-MQClientConfig::MQClientConfig()
+MQClientConfigImpl::MQClientConfigImpl()
     : m_instanceName(DEFAULT_INSTANCE_NAME),
       m_tcpWorkerThreadNum(std::min(4, (int)std::thread::hardware_concurrency())),
       m_tcpConnectTimeout(3000),
@@ -37,11 +37,11 @@ MQClientConfig::MQClientConfig()
   }
 }
 
-std::string MQClientConfig::buildMQClientId() const {
+std::string MQClientConfigImpl::buildMQClientId() const {
   std::string clientId;
   clientId.append(UtilAll::getLocalAddress());  // clientIP
   clientId.append("@");
-  clientId.append(m_instanceName);  // processId
+  clientId.append(m_instanceName);  // instanceName
   if (!m_unitName.empty()) {
     clientId.append("@");
     clientId.append(m_unitName);  // unitName
@@ -49,68 +49,68 @@ std::string MQClientConfig::buildMQClientId() const {
   return clientId;
 }
 
-const std::string& MQClientConfig::getGroupName() const {
+const std::string& MQClientConfigImpl::getGroupName() const {
   return m_groupName;
 }
 
-void MQClientConfig::setGroupName(const std::string& groupname) {
+void MQClientConfigImpl::setGroupName(const std::string& groupname) {
   m_groupName = groupname;
 }
 
-const std::string& MQClientConfig::getNamesrvAddr() const {
+const std::string& MQClientConfigImpl::getNamesrvAddr() const {
   return m_namesrvAddr;
 }
 
-void MQClientConfig::setNamesrvAddr(const std::string& namesrvAddr) {
+void MQClientConfigImpl::setNamesrvAddr(const std::string& namesrvAddr) {
   m_namesrvAddr = NameSpaceUtil::formatNameServerURL(namesrvAddr);
 }
 
-const std::string& MQClientConfig::getInstanceName() const {
+const std::string& MQClientConfigImpl::getInstanceName() const {
   return m_instanceName;
 }
 
-void MQClientConfig::setInstanceName(const std::string& instanceName) {
+void MQClientConfigImpl::setInstanceName(const std::string& instanceName) {
   m_instanceName = instanceName;
 }
 
-void MQClientConfig::changeInstanceNameToPID() {
+void MQClientConfigImpl::changeInstanceNameToPID() {
   if (m_instanceName == DEFAULT_INSTANCE_NAME) {
     m_instanceName = UtilAll::to_string(UtilAll::getProcessId());
   }
 }
 
-int MQClientConfig::getTcpTransportWorkerThreadNum() const {
+const std::string& MQClientConfigImpl::getUnitName() const {
+  return m_unitName;
+}
+
+void MQClientConfigImpl::setUnitName(std::string unitName) {
+  m_unitName = unitName;
+}
+
+int MQClientConfigImpl::getTcpTransportWorkerThreadNum() const {
   return m_tcpWorkerThreadNum;
 }
 
-void MQClientConfig::setTcpTransportWorkerThreadNum(int num) {
+void MQClientConfigImpl::setTcpTransportWorkerThreadNum(int num) {
   if (num > m_tcpWorkerThreadNum) {
     m_tcpWorkerThreadNum = num;
   }
 }
 
-uint64_t MQClientConfig::getTcpTransportConnectTimeout() const {
+uint64_t MQClientConfigImpl::getTcpTransportConnectTimeout() const {
   return m_tcpConnectTimeout;
 }
 
-void MQClientConfig::setTcpTransportConnectTimeout(uint64_t timeout) {
+void MQClientConfigImpl::setTcpTransportConnectTimeout(uint64_t timeout) {
   m_tcpConnectTimeout = timeout;
 }
 
-uint64_t MQClientConfig::getTcpTransportTryLockTimeout() const {
+uint64_t MQClientConfigImpl::getTcpTransportTryLockTimeout() const {
   return m_tcpTransportTryLockTimeout;
 }
 
-void MQClientConfig::setTcpTransportTryLockTimeout(uint64_t timeout) {
+void MQClientConfigImpl::setTcpTransportTryLockTimeout(uint64_t timeout) {
   m_tcpTransportTryLockTimeout = std::max<uint64_t>(1000, timeout) / 1000;
 }
 
-const std::string& MQClientConfig::getUnitName() const {
-  return m_unitName;
-}
-
-void MQClientConfig::setUnitName(std::string unitName) {
-  m_unitName = unitName;
-}
-
 }  // namespace rocketmq
diff --git a/src/MQClientConfigImpl.h b/src/MQClientConfigImpl.h
new file mode 100644
index 0000000..a4e522c
--- /dev/null
+++ b/src/MQClientConfigImpl.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+#ifndef __MQ_CLIENT_CONFIG_IMPL_H__
+#define __MQ_CLIENT_CONFIG_IMPL_H__
+
+#include "MQClientConfig.h"
+
+namespace rocketmq {
+
+/**
+ * MQ Client Config
+ */
+class MQClientConfigImpl : virtual public MQClientConfig {
+ public:
+  MQClientConfigImpl();
+  virtual ~MQClientConfigImpl() = default;
+
+  std::string buildMQClientId() const override;
+
+  const std::string& getGroupName() const override;
+  void setGroupName(const std::string& groupname) override;
+
+  const std::string& getNamesrvAddr() const override;
+  void setNamesrvAddr(const std::string& namesrvAddr) override;
+
+  const std::string& getInstanceName() const override;
+  void setInstanceName(const std::string& instanceName) override;
+
+  void changeInstanceNameToPID() override;
+
+  const std::string& getUnitName() const override;
+  void setUnitName(std::string unitName) override;
+
+  int getTcpTransportWorkerThreadNum() const override;
+  void setTcpTransportWorkerThreadNum(int num) override;
+
+  uint64_t getTcpTransportConnectTimeout() const override;
+  void setTcpTransportConnectTimeout(uint64_t timeout) override;  // ms
+
+  uint64_t getTcpTransportTryLockTimeout() const override;
+  void setTcpTransportTryLockTimeout(uint64_t timeout) override;  // ms
+
+ protected:
+  std::string m_namesrvAddr;
+  std::string m_instanceName;
+  std::string m_groupName;
+  std::string m_unitName;
+
+  int m_tcpWorkerThreadNum;
+  uint64_t m_tcpConnectTimeout;           // ms
+  uint64_t m_tcpTransportTryLockTimeout;  // s
+};
+
+}  // namespace rocketmq
+
+#endif  // __MQ_CLIENT_CONFIG_H__
diff --git a/src/MQClientImpl.cpp b/src/MQClientImpl.cpp
index fac8659..58376b5 100644
--- a/src/MQClientImpl.cpp
+++ b/src/MQClientImpl.cpp
@@ -24,19 +24,23 @@
 
 namespace rocketmq {
 
-#define ROCKETMQCPP_VERSION "1.0.1"
-#define BUILD_DATE "03-14-2018"
+#define ROCKETMQCPP_VERSION "3.0.0"
+#define BUILD_DATE __DATE__ " " __TIME__
 
 // display version: strings bin/librocketmq.so |grep VERSION
 const char* rocketmq_build_time = "VERSION: " ROCKETMQCPP_VERSION ", BUILD DATE: " BUILD_DATE;
 
 void MQClientImpl::start() {
-  if (m_clientInstance == nullptr) {
-    m_clientInstance = MQClientManager::getInstance()->getOrCreateMQClientInstance(m_clientConfig, m_rpcHook);
+  if (nullptr == m_clientInstance) {
+    if (nullptr == m_clientConfig) {
+      THROW_MQEXCEPTION(MQClientException, "have not clientConfig for create clientInstance.", -1);
+    }
+
+    m_clientInstance = MQClientManager::getInstance()->getOrCreateMQClientInstance(*m_clientConfig, m_rpcHook);
   }
-  LOG_INFO_NEW("MQClientImpl start, nameserveraddr:{}, instanceName:{}, groupName:{}, clientId:{}",
-               m_clientConfig->getNamesrvAddr(), m_clientConfig->getInstanceName(), m_clientConfig->getGroupName(),
-               m_clientInstance->getClientId());
+
+  LOG_INFO_NEW("MQClientImpl start, clientId:{}, real nameservAddr:{}", m_clientInstance->getClientId(),
+               m_clientInstance->getNamesrvAddr());
 }
 
 void MQClientImpl::shutdown() {
@@ -79,12 +83,20 @@ QueryResult MQClientImpl::queryMessage(const std::string& topic,
   return m_clientInstance->getMQAdminImpl()->queryMessage(topic, key, maxNum, begin, end);
 }
 
-MQClientInstancePtr MQClientImpl::getFactory() const {
+bool MQClientImpl::isServiceStateOk() {
+  return m_serviceState == RUNNING;
+}
+
+MQClientInstancePtr MQClientImpl::getClientInstance() const {
   return m_clientInstance;
 }
 
-bool MQClientImpl::isServiceStateOk() {
-  return m_serviceState == RUNNING;
+void MQClientImpl::setClientInstance(MQClientInstancePtr clientInstance) {
+  if (m_serviceState == CREATE_JUST) {
+    m_clientInstance = clientInstance;
+  } else {
+    THROW_MQEXCEPTION(MQClientException, "Client already start, can not reset clientInstance!", -1);
+  }
 }
 
 }  // namespace rocketmq
diff --git a/src/MQClientImpl.h b/src/MQClientImpl.h
index f116407..3b689bd 100644
--- a/src/MQClientImpl.h
+++ b/src/MQClientImpl.h
@@ -24,9 +24,9 @@
 
 namespace rocketmq {
 
-class MQClientImpl : virtual public MQAdmin {
+class MQClientImpl : public MQAdmin {
  public:
-  MQClientImpl(MQClientConfig* config, std::shared_ptr<RPCHook> rpcHook)
+  MQClientImpl(MQClientConfigPtr config, RPCHookPtr rpcHook)
       : m_clientConfig(config), m_rpcHook(rpcHook), m_serviceState(CREATE_JUST), m_clientInstance(nullptr) {}
 
  public:  // MQAdmin
@@ -46,16 +46,18 @@ class MQClientImpl : virtual public MQAdmin {
   virtual void start();
   virtual void shutdown();
 
-  MQClientInstancePtr getFactory() const;
   virtual bool isServiceStateOk();
 
-  std::shared_ptr<RPCHook> getRPCHook() { return m_rpcHook; }
-  void setRPCHook(std::shared_ptr<RPCHook> rpcHook) { m_rpcHook = rpcHook; }
+  MQClientInstancePtr getClientInstance() const;
+  void setClientInstance(MQClientInstancePtr clientInstance);
+
+  RPCHookPtr getRPCHook() { return m_rpcHook; }
+  void setRPCHook(RPCHookPtr rpcHook) { m_rpcHook = rpcHook; }
 
  protected:
-  MQClientConfig* m_clientConfig;
-  std::shared_ptr<RPCHook> m_rpcHook;
-  ServiceState m_serviceState;
+  MQClientConfigPtr m_clientConfig;
+  RPCHookPtr m_rpcHook;
+  volatile ServiceState m_serviceState;
   MQClientInstancePtr m_clientInstance;
 };
 
diff --git a/src/MQClientInstance.cpp b/src/MQClientInstance.cpp
index fff4d60..1ac6516 100644
--- a/src/MQClientInstance.cpp
+++ b/src/MQClientInstance.cpp
@@ -26,7 +26,7 @@
 #include "MQClientManager.h"
 #include "MQVersion.h"
 #include "PermName.h"
-#include "PullMessageService.h"
+#include "PullMessageService.hpp"
 #include "PullRequest.h"
 #include "RebalanceImpl.h"
 #include "RebalanceService.h"
@@ -42,14 +42,11 @@ namespace rocketmq {
 
 static const long LOCK_TIMEOUT_MILLIS = 3000L;
 
-MQClientInstance::MQClientInstance(MQClientConfig clientConfig, const std::string& clientId)
+MQClientInstance::MQClientInstance(const MQClientConfig& clientConfig, const std::string& clientId)
     : MQClientInstance(clientConfig, clientId, nullptr) {}
 
-MQClientInstance::MQClientInstance(MQClientConfig clientConfig,
-                                   const std::string& clientId,
-                                   std::shared_ptr<RPCHook> rpcHook)
-    : m_clientConfig(clientConfig),
-      m_clientId(clientId),
+MQClientInstance::MQClientInstance(const MQClientConfig& clientConfig, const std::string& clientId, RPCHookPtr rpcHook)
+    : m_clientId(clientId),
       m_rebalanceService(new RebalanceService(this)),
       m_pullMessageService(new PullMessageService(this)),
       m_scheduledExecutorService("MQClient", false) {
@@ -58,9 +55,9 @@ MQClientInstance::MQClientInstance(MQClientConfig clientConfig,
   m_topicPublishInfoTable[AUTO_CREATE_TOPIC_KEY_TOPIC] = defaultTopicInfo;
 
   m_clientRemotingProcessor.reset(new ClientRemotingProcessor(this));
-  m_mqClientAPIImpl.reset(new MQClientAPIImpl(m_clientRemotingProcessor.get(), rpcHook, &m_clientConfig));
+  m_mqClientAPIImpl.reset(new MQClientAPIImpl(m_clientRemotingProcessor.get(), rpcHook, clientConfig));
 
-  std::string namesrvAddr = m_clientConfig.getNamesrvAddr();
+  std::string namesrvAddr = clientConfig.getNamesrvAddr();
   if (!namesrvAddr.empty()) {
     m_mqClientAPIImpl->updateNameServerAddr(namesrvAddr);
     LOG_INFO_NEW("user specified name server address: {}", namesrvAddr);
@@ -85,11 +82,22 @@ MQClientInstance::~MQClientInstance() {
   m_mqClientAPIImpl = nullptr;
 }
 
+std::string MQClientInstance::getNamesrvAddr() const {
+  auto namesrvAddrs = m_mqClientAPIImpl->getRemotingClient()->getNameServerAddressList();
+  std::ostringstream oss;
+  for (const auto& addr : namesrvAddrs) {
+    oss << addr << ";";
+  }
+  return oss.str();
+}
+
 TopicPublishInfoPtr MQClientInstance::topicRouteData2TopicPublishInfo(const std::string& topic,
                                                                       TopicRouteDataPtr route) {
-  TopicPublishInfoPtr info(new TopicPublishInfo());
+  auto info = std::make_shared<TopicPublishInfo>();
   info->setTopicRouteData(route);
 
+  auto& mqList = const_cast<TopicPublishInfo::QueuesVec&>(info->getMessageQueueList());
+
   std::string orderTopicConf = route->getOrderTopicConf();
   if (!orderTopicConf.empty()) {  // order msg
     // "broker-a:8";"broker-b:8"
@@ -100,7 +108,7 @@ TopicPublishInfoPtr MQClientInstance::topicRouteData2TopicPublishInfo(const std:
       UtilAll::Split(item, broker, ':');
       int nums = atoi(item[1].c_str());
       for (int i = 0; i < nums; i++) {
-        info->getMessageQueueList().emplace_back(topic, item[0], i);
+        mqList.emplace_back(topic, item[0], i);
       }
     }
     info->setOrderTopic(true);
@@ -127,20 +135,19 @@ TopicPublishInfoPtr MQClientInstance::topicRouteData2TopicPublishInfo(const std:
         }
 
         for (int i = 0; i < qd.writeQueueNums; i++) {
-          info->getMessageQueueList().emplace_back(topic, qd.brokerName, i);
+          mqList.emplace_back(topic, qd.brokerName, i);
         }
       }
     }
 
     // sort, make brokerName is staggered.
-    std::sort(info->getMessageQueueList().begin(), info->getMessageQueueList().end(),
-              [](const MQMessageQueue& a, const MQMessageQueue& b) {
-                auto result = a.getQueueId() - b.getQueueId();
-                if (result == 0) {
-                  result = a.getBrokerName().compare(b.getBrokerName());
-                }
-                return result < 0;
-              });
+    std::sort(mqList.begin(), mqList.end(), [](const MQMessageQueue& a, const MQMessageQueue& b) {
+      auto result = a.getQueueId() - b.getQueueId();
+      if (result == 0) {
+        result = a.getBrokerName().compare(b.getBrokerName());
+      }
+      return result < 0;
+    });
 
     info->setOrderTopic(false);
   }
@@ -166,7 +173,7 @@ std::vector<MQMessageQueue> MQClientInstance::topicRouteData2TopicSubscribeInfo(
 void MQClientInstance::start() {
   switch (m_serviceState) {
     case CREATE_JUST:
-      LOG_INFO_NEW("MQClientInstance:{} start", m_clientId);
+      LOG_INFO_NEW("the client instance [{}] is starting", m_clientId);
       m_serviceState = START_FAILED;
 
       m_mqClientAPIImpl->start();
@@ -180,13 +187,15 @@ void MQClientInstance::start() {
       // start rebalance service
       m_rebalanceService->start();
 
-      LOG_INFO_NEW("the client factory [{}] start OK", m_clientId);
+      LOG_INFO_NEW("the client instance [{}] start OK", m_clientId);
       m_serviceState = RUNNING;
       break;
     case RUNNING:
+      LOG_INFO_NEW("the client instance [{}] already running.", m_clientId, m_serviceState);
+      break;
     case SHUTDOWN_ALREADY:
     case START_FAILED:
-      LOG_INFO_NEW("The Factory object:{} start failed with fault state:{}", m_clientId, m_serviceState);
+      LOG_INFO_NEW("the client instance [{}] start failed with fault state:{}", m_clientId, m_serviceState);
       break;
     default:
       break;
@@ -194,11 +203,13 @@ void MQClientInstance::start() {
 }
 
 void MQClientInstance::shutdown() {
-  if (getConsumerTableSize() != 0)
+  if (getConsumerTableSize() != 0) {
     return;
+  }
 
-  if (getProducerTableSize() != 0)
+  if (getProducerTableSize() != 0) {
     return;
+  }
 
   switch (m_serviceState) {
     case CREATE_JUST:
@@ -211,7 +222,7 @@ void MQClientInstance::shutdown() {
       m_rebalanceService->shutdown();
 
       MQClientManager::getInstance()->removeMQClientInstance(m_clientId);
-      LOG_INFO_NEW("the client factory [{}] shutdown OK", m_clientId);
+      LOG_INFO_NEW("the client instance [{}] shutdown OK", m_clientId);
     } break;
     case SHUTDOWN_ALREADY:
       break;
@@ -266,7 +277,7 @@ void MQClientInstance::persistAllConsumerOffsetPeriodically() {
                                       1000 * 5, time_unit::milliseconds);
 }
 
-std::string MQClientInstance::getClientId() {
+const std::string& MQClientInstance::getClientId() const {
   return m_clientId;
 }
 
@@ -291,6 +302,7 @@ void MQClientInstance::cleanOfflineBroker() {
   if (UtilAll::try_lock_for(m_lockNamesrv, LOCK_TIMEOUT_MILLIS)) {
     std::lock_guard<std::timed_mutex> lock(m_lockNamesrv, std::adopt_lock);
 
+    std::set<std::string> offlineBrokers;
     BrokerAddrMAP updatedTable(getBrokerAddrTable());
     for (auto itBrokerTable = updatedTable.begin(); itBrokerTable != updatedTable.end();) {
       const auto& brokerName = itBrokerTable->first;
@@ -299,6 +311,7 @@ void MQClientInstance::cleanOfflineBroker() {
       for (auto it = cloneAddrTable.begin(); it != cloneAddrTable.end();) {
         const auto& addr = it->second;
         if (!isBrokerAddrExistInTopicRouteTable(addr)) {
+          offlineBrokers.insert(addr);
           it = cloneAddrTable.erase(it);
           LOG_INFO_NEW("the broker addr[{} {}] is offline, remove it", brokerName, addr);
         } else {
@@ -314,7 +327,18 @@ void MQClientInstance::cleanOfflineBroker() {
       }
     }
 
-    resetBrokerAddrTable(std::move(updatedTable));
+    if (offlineBrokers.size() > 0) {
+      resetBrokerAddrTable(std::move(updatedTable));
+
+      std::lock_guard<std::mutex> lock(m_topicBrokerAddrTableMutex);
+      for (auto it = m_topicBrokerAddrTable.begin(); it != m_topicBrokerAddrTable.end();) {
+        if (offlineBrokers.find(it->second.first) != offlineBrokers.end()) {
+          it = m_topicBrokerAddrTable.erase(it);
+        } else {
+          it++;
+        }
+      }
+    }
   } else {
     LOG_WARN_NEW("lock namesrv, but failed.");
   }
@@ -348,7 +372,7 @@ void MQClientInstance::sendHeartbeatToAllBrokerWithLock() {
 void MQClientInstance::persistAllConsumerOffset() {
   std::lock_guard<std::mutex> lock(m_consumerTableMutex);
   for (const auto& it : m_consumerTable) {
-    LOG_DEBUG_NEW("Client factory start persistAllConsumerOffset");
+    LOG_DEBUG_NEW("the client instance [{}] start persistAllConsumerOffset", m_clientId);
     it.second->persistConsumerOffset();
   }
 }
@@ -362,7 +386,7 @@ void MQClientInstance::sendHeartbeatToAllBroker() {
     return;
   }
 
-  BrokerAddrMAP brokerAddrTable(getBrokerAddrTable());
+  auto brokerAddrTable = getBrokerAddrTable();
   if (!brokerAddrTable.empty()) {
     for (const auto& it : brokerAddrTable) {
       // const auto& brokerName = it.first;
@@ -375,8 +399,8 @@ void MQClientInstance::sendHeartbeatToAllBroker() {
         }
 
         try {
-          m_mqClientAPIImpl->sendHearbeat(addr, heartbeatData.get());
-        } catch (MQException& e) {
+          m_mqClientAPIImpl->sendHearbeat(addr, heartbeatData.get(), 3000);
+        } catch (const MQException& e) {
           LOG_ERROR_NEW("{}", e.what());
         }
       }
@@ -426,7 +450,6 @@ bool MQClientInstance::updateTopicRouteInfoFromNameServer(const std::string& top
           // update publish info
           {
             TopicPublishInfoPtr publishInfo(topicRouteData2TopicPublishInfo(topic, topicRouteData));
-            publishInfo->setHaveTopicRouterInfo(true);
             updateProducerTopicPublishInfo(topic, publishInfo);
           }
 
@@ -507,11 +530,11 @@ bool MQClientInstance::topicRouteDataIsChange(TopicRouteData* olddata, TopicRout
 
 TopicRouteDataPtr MQClientInstance::getTopicRouteData(const std::string& topic) {
   std::lock_guard<std::mutex> lock(m_topicRouteTableMutex);
-  auto iter = m_topicRouteTable.find(topic);
-  if (iter != m_topicRouteTable.end()) {
-    return iter->second;
+  const auto& it = m_topicRouteTable.find(topic);
+  if (it != m_topicRouteTable.end()) {
+    return it->second;
   }
-  return TopicRouteDataPtr();
+  return nullptr;
 }
 
 void MQClientInstance::addTopicRouteData(const std::string& topic, TopicRouteDataPtr topicRouteData) {
@@ -595,22 +618,23 @@ void MQClientInstance::rebalanceImmediately() {
 }
 
 void MQClientInstance::doRebalance() {
-  LOG_INFO_NEW("Client factory:{} start dorebalance", m_clientId);
+  LOG_INFO_NEW("the client instance:{} start doRebalance", m_clientId);
   if (getConsumerTableSize() > 0) {
     std::lock_guard<std::mutex> lock(m_consumerTableMutex);
     for (auto& it : m_consumerTable) {
       it.second->doRebalance();
     }
   }
-  LOG_INFO_NEW("Client factory:{} finish dorebalance", m_clientId);
+  LOG_INFO_NEW("the client instance [{}] finish doRebalance", m_clientId);
 }
 
 void MQClientInstance::doRebalanceByConsumerGroup(const std::string& consumerGroup) {
   std::lock_guard<std::mutex> lock(m_consumerTableMutex);
-  if (m_consumerTable.find(consumerGroup) != m_consumerTable.end()) {
+  const auto& it = m_consumerTable.find(consumerGroup);
+  if (it != m_consumerTable.end()) {
     try {
-      LOG_INFO_NEW("Client factory:{} start dorebalance for consumer:{}", m_clientId, consumerGroup);
-      auto* consumer = m_consumerTable[consumerGroup];
+      LOG_INFO_NEW("the client instance [{}] start doRebalance for consumer [{}]", m_clientId, consumerGroup);
+      auto* consumer = it->second;
       consumer->doRebalance();
     } catch (const std::exception& e) {
       LOG_ERROR_NEW("{}", e.what());
@@ -620,24 +644,28 @@ void MQClientInstance::doRebalanceByConsumerGroup(const std::string& consumerGro
 
 MQProducerInner* MQClientInstance::selectProducer(const std::string& producerName) {
   std::lock_guard<std::mutex> lock(m_producerTableMutex);
-  if (m_producerTable.find(producerName) != m_producerTable.end()) {
-    return m_producerTable[producerName];
+  const auto& it = m_producerTable.find(producerName);
+  if (it != m_producerTable.end()) {
+    return it->second;
   }
   return nullptr;
 }
 
 bool MQClientInstance::addProducerToTable(const std::string& producerName, MQProducerInner* producer) {
   std::lock_guard<std::mutex> lock(m_producerTableMutex);
-  if (m_producerTable.find(producerName) != m_producerTable.end())
+  if (m_producerTable.find(producerName) != m_producerTable.end()) {
     return false;
-  m_producerTable[producerName] = producer;
-  return true;
+  } else {
+    m_producerTable[producerName] = producer;
+    return true;
+  }
 }
 
 void MQClientInstance::eraseProducerFromTable(const std::string& producerName) {
   std::lock_guard<std::mutex> lock(m_producerTableMutex);
-  if (m_producerTable.find(producerName) != m_producerTable.end()) {
-    m_producerTable.erase(producerName);
+  const auto& it = m_producerTable.find(producerName);
+  if (it != m_producerTable.end()) {
+    m_producerTable.erase(it);
   }
 }
 
@@ -659,8 +687,9 @@ void MQClientInstance::updateProducerTopicPublishInfo(const std::string& topic,
 
 MQConsumerInner* MQClientInstance::selectConsumer(const std::string& group) {
   std::lock_guard<std::mutex> lock(m_consumerTableMutex);
-  if (m_consumerTable.find(group) != m_consumerTable.end()) {
-    return m_consumerTable[group];
+  const auto& it = m_consumerTable.find(group);
+  if (it != m_consumerTable.end()) {
+    return it->second;
   }
   return nullptr;
 }
@@ -677,8 +706,9 @@ bool MQClientInstance::addConsumerToTable(const std::string& consumerName, MQCon
 
 void MQClientInstance::eraseConsumerFromTable(const std::string& consumerName) {
   std::lock_guard<std::mutex> lock(m_consumerTableMutex);
-  if (m_consumerTable.find(consumerName) != m_consumerTable.end()) {
-    m_consumerTable.erase(consumerName);  // do not need free consumer, as it was allocated by user
+  const auto& it = m_consumerTable.find(consumerName);
+  if (it != m_consumerTable.end()) {
+    m_consumerTable.erase(it);  // do not need free consumer, as it was allocated by user
   } else {
     LOG_WARN_NEW("could not find consumer:{} from table", consumerName);
   }
@@ -714,36 +744,34 @@ void MQClientInstance::addTopicInfoToTable(const std::string& topic, TopicPublis
 
 void MQClientInstance::eraseTopicInfoFromTable(const std::string& topic) {
   std::lock_guard<std::mutex> lock(m_topicPublishInfoTableMutex);
-  if (m_topicPublishInfoTable.find(topic) != m_topicPublishInfoTable.end()) {
-    m_topicPublishInfoTable.erase(topic);
+  const auto& it = m_topicPublishInfoTable.find(topic);
+  if (it != m_topicPublishInfoTable.end()) {
+    m_topicPublishInfoTable.erase(it);
   }
 }
 
 TopicPublishInfoPtr MQClientInstance::getTopicPublishInfoFromTable(const std::string& topic) {
   std::lock_guard<std::mutex> lock(m_topicPublishInfoTableMutex);
-  if (m_topicPublishInfoTable.find(topic) != m_topicPublishInfoTable.end()) {
-    return m_topicPublishInfoTable[topic];
+  const auto& it = m_topicPublishInfoTable.find(topic);
+  if (it != m_topicPublishInfoTable.end()) {
+    return it->second;
   }
-  return TopicPublishInfoPtr();
+  return nullptr;
 }
 
 bool MQClientInstance::isTopicInfoValidInTable(const std::string& topic) {
   std::lock_guard<std::mutex> lock(m_topicPublishInfoTableMutex);
-  auto iter = m_topicPublishInfoTable.find(topic);
-  if (iter != m_topicPublishInfoTable.end()) {
-    return iter->second->ok();
-  }
-  return false;
+  return m_topicPublishInfoTable.find(topic) != m_topicPublishInfoTable.end();
 }
 
 TopicPublishInfoPtr MQClientInstance::tryToFindTopicPublishInfo(const std::string& topic) {
   auto topicPublishInfo = getTopicPublishInfoFromTable(topic);
-  if (nullptr == topicPublishInfo || !topicPublishInfo->ok()) {
+  if (nullptr == topicPublishInfo) {
     updateTopicRouteInfoFromNameServer(topic);
     topicPublishInfo = getTopicPublishInfoFromTable(topic);
   }
 
-  if (nullptr != topicPublishInfo && (topicPublishInfo->isHaveTopicRouterInfo() || topicPublishInfo->ok())) {
+  if (nullptr != topicPublishInfo && topicPublishInfo->ok()) {
     return topicPublishInfo;
   } else {
     LOG_INFO_NEW("updateTopicRouteInfoFromNameServer with default");
@@ -758,9 +786,10 @@ FindBrokerResult* MQClientInstance::findBrokerAddressInAdmin(const std::string&
   bool slave = false;
   std::string brokerAddr;
 
-  if (brokerTable.find(brokerName) != brokerTable.end()) {
-    std::map<int, std::string> brokerMap(brokerTable[brokerName]);
-    std::map<int, std::string>::iterator it1 = brokerMap.begin();
+  const auto& it = brokerTable.find(brokerName);
+  if (it != brokerTable.end()) {
+    const auto& brokerMap = it->second;
+    const auto& it1 = brokerMap.begin();
     if (it1 != brokerMap.end()) {
       slave = (it1->first != MASTER_ID);
       found = true;
@@ -781,11 +810,12 @@ std::string MQClientInstance::findBrokerAddressInPublish(const std::string& brok
   std::string brokerAddr;
   bool found = false;
 
-  if (brokerTable.find(brokerName) != brokerTable.end()) {
-    const auto& brokerMap = brokerTable[brokerName];
-    auto it = brokerMap.find(MASTER_ID);
-    if (it != brokerMap.end()) {
-      brokerAddr = it->second;
+  const auto& it = brokerTable.find(brokerName);
+  if (it != brokerTable.end()) {
+    const auto& brokerMap = it->second;
+    const auto& it1 = brokerMap.find(MASTER_ID);
+    if (it1 != brokerMap.end()) {
+      brokerAddr = it1->second;
       found = true;
     }
   }
@@ -806,18 +836,19 @@ FindBrokerResult* MQClientInstance::findBrokerAddressInSubscribe(const std::stri
   bool found = false;
   BrokerAddrMAP brokerTable(getBrokerAddrTable());
 
-  if (brokerTable.find(brokerName) != brokerTable.end()) {
-    std::map<int, std::string> brokerMap(brokerTable[brokerName]);
+  const auto& it = brokerTable.find(brokerName);
+  if (it != brokerTable.end()) {
+    const auto& brokerMap = it->second;
     if (!brokerMap.empty()) {
-      auto iter = brokerMap.find(brokerId);
-      if (iter != brokerMap.end()) {
-        brokerAddr = iter->second;
-        slave = (brokerId != MASTER_ID);
+      const auto& it1 = brokerMap.find(brokerId);
+      if (it1 != brokerMap.end()) {
+        brokerAddr = it1->second;
+        slave = it1->first != MASTER_ID;
         found = true;
       } else if (!onlyThisBroker) {  // not only from master
-        iter = brokerMap.begin();
-        brokerAddr = iter->second;
-        slave = iter->first != MASTER_ID;
+        const auto& it2 = brokerMap.begin();
+        brokerAddr = it2->second;
+        slave = it2->first != MASTER_ID;
         found = true;
       }
     }
@@ -835,18 +866,42 @@ FindBrokerResult* MQClientInstance::findBrokerAddressInSubscribe(const std::stri
 void MQClientInstance::findConsumerIds(const std::string& topic,
                                        const std::string& group,
                                        std::vector<std::string>& cids) {
-  std::string brokerAddr = findBrokerAddrByTopic(topic);
+  std::string brokerAddr;
+
+  // find consumerIds from same broker every 40s
+  {
+    std::lock_guard<std::mutex> lock(m_topicBrokerAddrTableMutex);
+    const auto& it = m_topicBrokerAddrTable.find(topic);
+    if (it != m_topicBrokerAddrTable.end()) {
+      if (UtilAll::currentTimeMillis() < it->second.second + 40000) {
+        brokerAddr = it->second.first;
+      }
+    }
+  }
+
   if (brokerAddr.empty()) {
-    updateTopicRouteInfoFromNameServer(topic);
+    // select new one
     brokerAddr = findBrokerAddrByTopic(topic);
+    if (brokerAddr.empty()) {
+      updateTopicRouteInfoFromNameServer(topic);
+      brokerAddr = findBrokerAddrByTopic(topic);
+    }
+
+    if (!brokerAddr.empty()) {
+      std::lock_guard<std::mutex> lock(m_topicBrokerAddrTableMutex);
+      m_topicBrokerAddrTable[topic] = std::make_pair(brokerAddr, UtilAll::currentTimeMillis());
+    }
   }
 
   if (!brokerAddr.empty()) {
     try {
       LOG_INFO_NEW("getConsumerIdList from broker:{}", brokerAddr);
       return m_mqClientAPIImpl->getConsumerIdListByGroup(brokerAddr, group, cids, 5000);
-    } catch (MQException& e) {
-      LOG_ERROR_NEW("{}", e.what());
+    } catch (const MQException& e) {
+      LOG_ERROR_NEW("encounter exception when getConsumerIdList: {}", e.what());
+
+      std::lock_guard<std::mutex> lock(m_topicBrokerAddrTableMutex);
+      m_topicBrokerAddrTable.erase(topic);
     }
   }
 }
@@ -887,7 +942,7 @@ void MQClientInstance::resetOffset(const std::string& group,
 
     for (const auto& it : processQueueTable) {
       const auto& mq = it.first;
-      auto it2 = offsetTable.find(mq);
+      const auto& it2 = offsetTable.find(mq);
       if (it2 != offsetTable.end()) {
         auto offset = it2->second;
         consumer->updateConsumeOffset(mq, offset);
@@ -911,19 +966,15 @@ ConsumerRunningInfo* MQClientInstance::consumerRunningInfo(const std::string& co
   if (consumer != nullptr) {
     std::unique_ptr<ConsumerRunningInfo> runningInfo(consumer->consumerRunningInfo());
     if (runningInfo != nullptr) {
-      auto nsList = m_mqClientAPIImpl->getRemotingClient()->getNameServerAddressList();
-
-      std::string nsAddr;
-      for (const auto& addr : nsList) {
-        nsAddr.append(addr);
-      }
-
+      std::string nsAddr = getNamesrvAddr();
       runningInfo->setProperty(ConsumerRunningInfo::PROP_NAMESERVER_ADDR, nsAddr);
+
       if (consumer->consumeType() == CONSUME_PASSIVELY) {
         runningInfo->setProperty(ConsumerRunningInfo::PROP_CONSUME_TYPE, "CONSUME_PASSIVELY");
       } else {
         runningInfo->setProperty(ConsumerRunningInfo::PROP_CONSUME_TYPE, "CONSUME_ACTIVELY");
       }
+
       runningInfo->setProperty(ConsumerRunningInfo::PROP_CLIENT_VERSION,
                                MQVersion::GetVersionDesc(MQVersion::s_CurrentVersion));
 
@@ -938,10 +989,7 @@ ConsumerRunningInfo* MQClientInstance::consumerRunningInfo(const std::string& co
 void MQClientInstance::addBrokerToAddrTable(const std::string& brokerName,
                                             const std::map<int, std::string>& brokerAddrs) {
   std::lock_guard<std::mutex> lock(m_brokerAddrTableMutex);
-  if (m_brokerAddrTable.find(brokerName) != m_brokerAddrTable.end()) {
-    m_brokerAddrTable.erase(brokerName);
-  }
-  m_brokerAddrTable.emplace(brokerName, brokerAddrs);
+  m_brokerAddrTable[brokerName] = brokerAddrs;
 }
 
 void MQClientInstance::resetBrokerAddrTable(BrokerAddrMAP&& table) {
diff --git a/src/MQClientInstance.h b/src/MQClientInstance.h
index be6993f..77ee4b6 100644
--- a/src/MQClientInstance.h
+++ b/src/MQClientInstance.h
@@ -20,6 +20,7 @@
 #include <memory>
 #include <mutex>
 #include <set>
+#include <utility>
 
 #include "ConsumerRunningInfo.h"
 #include "FindBrokerResult.h"
@@ -37,6 +38,8 @@
 namespace rocketmq {
 
 class RPCHook;
+typedef std::shared_ptr<RPCHook> RPCHookPtr;
+
 class MQClientAPIImpl;
 class MQAdminImpl;
 class ClientRemotingProcessor;
@@ -48,15 +51,16 @@ typedef std::shared_ptr<MQClientInstance> MQClientInstancePtr;
 
 class MQClientInstance {
  public:
-  MQClientInstance(MQClientConfig clientConfig, const std::string& clientId);
-  MQClientInstance(MQClientConfig clientConfig, const std::string& clientId, std::shared_ptr<RPCHook> rpcHook);
+  MQClientInstance(const MQClientConfig& clientConfig, const std::string& clientId);
+  MQClientInstance(const MQClientConfig& clientConfig, const std::string& clientId, RPCHookPtr rpcHook);
   virtual ~MQClientInstance();
 
   static TopicPublishInfoPtr topicRouteData2TopicPublishInfo(const std::string& topic, TopicRouteDataPtr route);
   static std::vector<MQMessageQueue> topicRouteData2TopicSubscribeInfo(const std::string& topic,
                                                                        TopicRouteDataPtr route);
 
-  std::string getClientId();
+  const std::string& getClientId() const;
+  std::string getNamesrvAddr() const;
 
   void start();
   void shutdown();
@@ -96,6 +100,8 @@ class MQClientInstance {
  public:
   TopicPublishInfoPtr tryToFindTopicPublishInfo(const std::string& topic);
 
+  TopicRouteDataPtr getTopicRouteData(const std::string& topic);
+
  public:
   MQClientAPIImpl* getMQClientAPIImpl() const { return m_mqClientAPIImpl.get(); }
   MQAdminImpl* getMQAdminImpl() const { return m_mqAdminImpl.get(); }
@@ -123,7 +129,6 @@ class MQClientInstance {
 
   // topic route
   bool topicRouteDataIsChange(TopicRouteData* old, TopicRouteData* now);
-  TopicRouteDataPtr getTopicRouteData(const std::string& topic);
   void addTopicRouteData(const std::string& topic, TopicRouteDataPtr topicRouteData);
 
   // heartbeat
@@ -159,9 +164,8 @@ class MQClientInstance {
   bool isTopicInfoValidInTable(const std::string& topic);
 
  private:
-  MQClientConfig m_clientConfig;
   std::string m_clientId;
-  ServiceState m_serviceState;
+  volatile ServiceState m_serviceState;
 
   // group -> MQProducer
   typedef std::map<std::string, MQProducerInner*> MQPMAP;
@@ -187,6 +191,11 @@ class MQClientInstance {
   TPMAP m_topicPublishInfoTable;
   std::mutex m_topicPublishInfoTableMutex;
 
+  // topic -> <broker, time>
+  typedef std::map<std::string, std::pair<std::string, uint64_t>> TBAMAP;
+  TBAMAP m_topicBrokerAddrTable;
+  std::mutex m_topicBrokerAddrTableMutex;
+
   std::timed_mutex m_lockNamesrv;
   std::timed_mutex m_lockHeartbeat;
 
diff --git a/src/MQClientManager.cpp b/src/MQClientManager.cpp
index d768e8e..a0b0fac 100644
--- a/src/MQClientManager.cpp
+++ b/src/MQClientManager.cpp
@@ -28,20 +28,20 @@ MQClientManager* MQClientManager::getInstance() {
 MQClientManager::MQClientManager() = default;
 MQClientManager::~MQClientManager() = default;
 
-MQClientInstancePtr MQClientManager::getOrCreateMQClientInstance(const MQClientConfig* clientConfig) {
+MQClientInstancePtr MQClientManager::getOrCreateMQClientInstance(const MQClientConfig& clientConfig) {
   return getOrCreateMQClientInstance(clientConfig, nullptr);
 }
 
-MQClientInstancePtr MQClientManager::getOrCreateMQClientInstance(const MQClientConfig* clientConfig,
-                                                                 std::shared_ptr<RPCHook> rpcHook) {
-  std::string clientId = clientConfig->buildMQClientId();
+MQClientInstancePtr MQClientManager::getOrCreateMQClientInstance(const MQClientConfig& clientConfig,
+                                                                 RPCHookPtr rpcHook) {
+  std::string clientId = clientConfig.buildMQClientId();
   std::lock_guard<std::mutex> lock(m_mutex);
-  auto it = m_instanceTable.find(clientId);
+  const auto& it = m_instanceTable.find(clientId);
   if (it != m_instanceTable.end()) {
     return it->second;
   } else {
-    // clone clientConfig
-    auto instance = std::make_shared<MQClientInstance>(*clientConfig, clientId, rpcHook);
+    // Clone clientConfig in Java, but we don't now.
+    auto instance = std::make_shared<MQClientInstance>(clientConfig, clientId, rpcHook);
     m_instanceTable[clientId] = instance;
     LOG_INFO_NEW("Created new MQClientInstance for clientId:[{}]", clientId);
     return instance;
@@ -50,7 +50,7 @@ MQClientInstancePtr MQClientManager::getOrCreateMQClientInstance(const MQClientC
 
 void MQClientManager::removeMQClientInstance(const std::string& clientId) {
   std::lock_guard<std::mutex> lock(m_mutex);
-  auto it = m_instanceTable.find(clientId);
+  const auto& it = m_instanceTable.find(clientId);
   if (it != m_instanceTable.end()) {
     m_instanceTable.erase(it);
   }
diff --git a/src/MQClientManager.h b/src/MQClientManager.h
index eee63bc..7ecec15 100644
--- a/src/MQClientManager.h
+++ b/src/MQClientManager.h
@@ -31,8 +31,8 @@ class MQClientManager {
 
   virtual ~MQClientManager();
 
-  MQClientInstancePtr getOrCreateMQClientInstance(const MQClientConfig* clientConfig);
-  MQClientInstancePtr getOrCreateMQClientInstance(const MQClientConfig* clientConfig, std::shared_ptr<RPCHook> rpcHook);
+  MQClientInstancePtr getOrCreateMQClientInstance(const MQClientConfig& clientConfig);
+  MQClientInstancePtr getOrCreateMQClientInstance(const MQClientConfig& clientConfig, RPCHookPtr rpcHook);
 
   void removeMQClientInstance(const std::string& clientId);
 
diff --git a/include/DefaultMQConsumer.h b/src/common/ClientErrorCode.h
similarity index 63%
copy from include/DefaultMQConsumer.h
copy to src/common/ClientErrorCode.h
index 1f103ac..d43e90f 100644
--- a/include/DefaultMQConsumer.h
+++ b/src/common/ClientErrorCode.h
@@ -14,25 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __DEFAULT_MQ_CONSUMER_H__
-#define __DEFAULT_MQ_CONSUMER_H__
-
-#include "ConsumeType.h"
-#include "MQClientConfig.h"
+#ifndef __CLIENT_ERROR_CODE_H__
+#define __CLIENT_ERROR_CODE_H__
 
 namespace rocketmq {
 
-class ROCKETMQCLIENT_API DefaultMQConsumerConfig : public MQClientConfig {
+class ClientErrorCode {
  public:
-  DefaultMQConsumerConfig() : m_messageModel(CLUSTERING) {}
-
-  MessageModel getMessageModel() const { return m_messageModel; }
-  void setMessageModel(MessageModel messageModel) { m_messageModel = messageModel; }
-
- protected:
-  MessageModel m_messageModel;
+  static const int CONNECT_BROKER_EXCEPTION = 10001;
+  static const int ACCESS_BROKER_TIMEOUT = 10002;
+  static const int BROKER_NOT_EXIST_EXCEPTION = 10003;
+  static const int NO_NAME_SERVER_EXCEPTION = 10004;
+  static const int NOT_FOUND_TOPIC_EXCEPTION = 10005;
+  static const int REQUEST_TIMEOUT_EXCEPTION = 10006;
+  static const int CREATE_REPLY_MESSAGE_EXCEPTION = 10007;
 };
 
 }  // namespace rocketmq
 
-#endif  // __DEFAULT_MQ_CONSUMER_H__
+#endif  // __CLIENT_ERROR_CODE_H__
diff --git a/src/common/ClientRPCHook.cpp b/src/common/ClientRPCHook.cpp
index 0f7c101..356b0cf 100644
--- a/src/common/ClientRPCHook.cpp
+++ b/src/common/ClientRPCHook.cpp
@@ -18,11 +18,10 @@
 
 #include <string>
 
-#include "CommandHeader.h"
 #include "DataBlock.h"
 #include "Logging.h"
 #include "RemotingCommand.h"
-
+#include "protocol/header/CommandHeader.h"
 #include "spas_client.h"
 
 namespace rocketmq {
@@ -55,12 +54,12 @@ void ClientRPCHook::signCommand(RemotingCommand& command) {
   headerMap.insert(std::make_pair(SessionCredentials::AccessKey, sessionCredentials_.getAccessKey()));
   headerMap.insert(std::make_pair(SessionCredentials::ONSChannelKey, sessionCredentials_.getAuthChannel()));
 
-  LOG_DEBUG("before insert declared filed, MAP SIZE is:" SIZET_FMT "", headerMap.size());
+  LOG_DEBUG_NEW("before insert declared filed, MAP SIZE is:{}", headerMap.size());
   auto* header = command.readCustomHeader();
   if (header != nullptr) {
     header->SetDeclaredFieldOfCommandHeader(headerMap);
   }
-  LOG_DEBUG("after insert declared filed, MAP SIZE is:" SIZET_FMT "", headerMap.size());
+  LOG_DEBUG_NEW("after insert declared filed, MAP SIZE is:{}", headerMap.size());
 
   std::string totalMsg;
   for (const auto& it : headerMap) {
@@ -71,18 +70,18 @@ void ClientRPCHook::signCommand(RemotingCommand& command) {
     LOG_DEBUG_NEW("request have msgBody, length is:{}", body->getSize());
     totalMsg.append(body->getData(), body->getSize());
   }
-  LOG_DEBUG("total msg info are:%s, size is:" SIZET_FMT "", totalMsg.c_str(), totalMsg.size());
+  LOG_DEBUG_NEW("total msg info are:{}, size is:{}", totalMsg, totalMsg.size());
 
-  char* pSignature =
+  char* sign =
       rocketmqSignature::spas_sign(totalMsg.c_str(), totalMsg.size(), sessionCredentials_.getSecretKey().c_str());
-  if (pSignature != nullptr) {
-    std::string signature(static_cast<const char*>(pSignature));
+  if (sign != nullptr) {
+    std::string signature(static_cast<const char*>(sign));
     command.addExtField(SessionCredentials::Signature, signature);
     command.addExtField(SessionCredentials::AccessKey, sessionCredentials_.getAccessKey());
     command.addExtField(SessionCredentials::ONSChannelKey, sessionCredentials_.getAuthChannel());
-    rocketmqSignature::spas_mem_free(pSignature);
+    rocketmqSignature::spas_mem_free(sign);
   } else {
-    LOG_ERROR("signature for request failed");
+    LOG_ERROR_NEW("signature for request failed");
   }
 }
 
diff --git a/src/common/DataBlock.cpp b/src/common/DataBlock.cpp
index 7dba95a..6592b85 100644
--- a/src/common/DataBlock.cpp
+++ b/src/common/DataBlock.cpp
@@ -127,7 +127,7 @@ void MemoryPool::reset() {
 
 void MemoryPool::reset(char* data, size_t size) {
   if (size != 0) {
-    throw std::runtime_error("MemoryBlock can't set external pointer as data.");
+    throw std::runtime_error("MemoryPool can't set external pointer as data.");
   }
 
   std::free(data_);
diff --git a/src/common/InputStream.cpp b/src/common/InputStream.cpp
index 046d048..5a53819 100644
--- a/src/common/InputStream.cpp
+++ b/src/common/InputStream.cpp
@@ -78,10 +78,10 @@ int64_t InputStream::readInt64BigEndian() {
 
 float InputStream::readFloatBigEndian() {
   union {
-    int32 asInt;
+    int32_t asInt;
     float asFloat;
   } n;
-  n.asInt = (int32)readIntBigEndian();
+  n.asInt = (int32_t)readIntBigEndian();
   return n.asFloat;
 }
 
diff --git a/src/common/InputStream.h b/src/common/InputStream.h
index 12a07fb..1a29bc8 100644
--- a/src/common/InputStream.h
+++ b/src/common/InputStream.h
@@ -14,10 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef INPUTSTREAM_H_INCLUDED
-#define INPUTSTREAM_H_INCLUDED
+#ifndef __INPUT_STREAM_H__
+#define __INPUT_STREAM_H__
 
 #include "DataBlock.h"
+
 //==============================================================================
 /** The base class for streams that read data.
 
@@ -28,6 +29,7 @@
     @see OutputStream, MemoryInputStream, BufferedInputStream, FileInputStream
 */
 namespace rocketmq {
+
 class ROCKETMQCLIENT_API InputStream {
  public:
   /** Destructor. */
@@ -189,5 +191,7 @@ class ROCKETMQCLIENT_API InputStream {
   //==============================================================================
   InputStream() {}
 };
+
 }  // namespace rocketmq
-#endif  // INPUTSTREAM_H_INCLUDED
+
+#endif  // __INPUT_STREAM_H__
diff --git a/src/common/MQVersion.cpp b/src/common/MQVersion.cpp
index 498f01b..1d8e481 100644
--- a/src/common/MQVersion.cpp
+++ b/src/common/MQVersion.cpp
@@ -18,8 +18,8 @@
 
 namespace rocketmq {
 
-int MQVersion::s_CurrentVersion = MQVersion::V4_6_0;
-std::string MQVersion::s_CurrentLanguage = "CPP";
+const int MQVersion::s_CurrentVersion = MQVersion::V4_6_0;
+const std::string MQVersion::s_CurrentLanguage = "CPP";
 
 const char* MQVersion::GetVersionDesc(int value) {
   int currentVersion = value;
diff --git a/src/common/MQVersion.h b/src/common/MQVersion.h
index eb68fbc..2760dad 100644
--- a/src/common/MQVersion.h
+++ b/src/common/MQVersion.h
@@ -38,586 +38,304 @@ static const char* RocketMQCPPClientVersion[] = {"V3_0_0_SNAPSHOT",  "V3_0_0_ALP
                                                  "V3_0_7_SNAPSHOT",  "V3_0_7",
                                                  "V3_0_8_SNAPSHOT",  "V3_0_8",
                                                  "V3_0_9_SNAPSHOT",  "V3_0_9",
-
                                                  "V3_0_10_SNAPSHOT", "V3_0_10",
-
                                                  "V3_0_11_SNAPSHOT", "V3_0_11",
-
                                                  "V3_0_12_SNAPSHOT", "V3_0_12",
-
                                                  "V3_0_13_SNAPSHOT", "V3_0_13",
-
                                                  "V3_0_14_SNAPSHOT", "V3_0_14",
-
                                                  "V3_0_15_SNAPSHOT", "V3_0_15",
-
                                                  "V3_1_0_SNAPSHOT",  "V3_1_0",
-
                                                  "V3_1_1_SNAPSHOT",  "V3_1_1",
-
                                                  "V3_1_2_SNAPSHOT",  "V3_1_2",
-
                                                  "V3_1_3_SNAPSHOT",  "V3_1_3",
-
                                                  "V3_1_4_SNAPSHOT",  "V3_1_4",
-
                                                  "V3_1_5_SNAPSHOT",  "V3_1_5",
-
                                                  "V3_1_6_SNAPSHOT",  "V3_1_6",
-
                                                  "V3_1_7_SNAPSHOT",  "V3_1_7",
-
                                                  "V3_1_8_SNAPSHOT",  "V3_1_8",
-
                                                  "V3_1_9_SNAPSHOT",  "V3_1_9",
-
                                                  "V3_2_0_SNAPSHOT",  "V3_2_0",
-
                                                  "V3_2_1_SNAPSHOT",  "V3_2_1",
-
                                                  "V3_2_2_SNAPSHOT",  "V3_2_2",
-
                                                  "V3_2_3_SNAPSHOT",  "V3_2_3",
-
                                                  "V3_2_4_SNAPSHOT",  "V3_2_4",
-
                                                  "V3_2_5_SNAPSHOT",  "V3_2_5",
-
                                                  "V3_2_6_SNAPSHOT",  "V3_2_6",
-
                                                  "V3_2_7_SNAPSHOT",  "V3_2_7",
-
                                                  "V3_2_8_SNAPSHOT",  "V3_2_8",
-
                                                  "V3_2_9_SNAPSHOT",  "V3_2_9",
-
+                                                 "V3_3_0_SNAPSHOT",  "V3_3_0",
                                                  "V3_3_1_SNAPSHOT",  "V3_3_1",
-
                                                  "V3_3_2_SNAPSHOT",  "V3_3_2",
-
                                                  "V3_3_3_SNAPSHOT",  "V3_3_3",
-
                                                  "V3_3_4_SNAPSHOT",  "V3_3_4",
-
                                                  "V3_3_5_SNAPSHOT",  "V3_3_5",
-
                                                  "V3_3_6_SNAPSHOT",  "V3_3_6",
-
                                                  "V3_3_7_SNAPSHOT",  "V3_3_7",
-
                                                  "V3_3_8_SNAPSHOT",  "V3_3_8",
-
                                                  "V3_3_9_SNAPSHOT",  "V3_3_9",
-
+                                                 "V3_4_0_SNAPSHOT",  "V3_4_0",
                                                  "V3_4_1_SNAPSHOT",  "V3_4_1",
-
                                                  "V3_4_2_SNAPSHOT",  "V3_4_2",
-
                                                  "V3_4_3_SNAPSHOT",  "V3_4_3",
-
                                                  "V3_4_4_SNAPSHOT",  "V3_4_4",
-
                                                  "V3_4_5_SNAPSHOT",  "V3_4_5",
-
                                                  "V3_4_6_SNAPSHOT",  "V3_4_6",
-
                                                  "V3_4_7_SNAPSHOT",  "V3_4_7",
-
                                                  "V3_4_8_SNAPSHOT",  "V3_4_8",
-
                                                  "V3_4_9_SNAPSHOT",  "V3_4_9",
+                                                 "V3_5_0_SNAPSHOT",  "V3_5_0",
                                                  "V3_5_1_SNAPSHOT",  "V3_5_1",
-
                                                  "V3_5_2_SNAPSHOT",  "V3_5_2",
-
                                                  "V3_5_3_SNAPSHOT",  "V3_5_3",
-
                                                  "V3_5_4_SNAPSHOT",  "V3_5_4",
-
                                                  "V3_5_5_SNAPSHOT",  "V3_5_5",
-
                                                  "V3_5_6_SNAPSHOT",  "V3_5_6",
-
                                                  "V3_5_7_SNAPSHOT",  "V3_5_7",
-
                                                  "V3_5_8_SNAPSHOT",  "V3_5_8",
-
                                                  "V3_5_9_SNAPSHOT",  "V3_5_9",
-
+                                                 "V3_6_0_SNAPSHOT",  "V3_6_0",
                                                  "V3_6_1_SNAPSHOT",  "V3_6_1",
-
                                                  "V3_6_2_SNAPSHOT",  "V3_6_2",
-
                                                  "V3_6_3_SNAPSHOT",  "V3_6_3",
-
                                                  "V3_6_4_SNAPSHOT",  "V3_6_4",
-
                                                  "V3_6_5_SNAPSHOT",  "V3_6_5",
-
                                                  "V3_6_6_SNAPSHOT",  "V3_6_6",
-
                                                  "V3_6_7_SNAPSHOT",  "V3_6_7",
-
                                                  "V3_6_8_SNAPSHOT",  "V3_6_8",
-
                                                  "V3_6_9_SNAPSHOT",  "V3_6_9",
-
+                                                 "V3_7_0_SNAPSHOT",  "V3_7_0",
                                                  "V3_7_1_SNAPSHOT",  "V3_7_1",
-
                                                  "V3_7_2_SNAPSHOT",  "V3_7_2",
-
                                                  "V3_7_3_SNAPSHOT",  "V3_7_3",
-
                                                  "V3_7_4_SNAPSHOT",  "V3_7_4",
-
                                                  "V3_7_5_SNAPSHOT",  "V3_7_5",
-
                                                  "V3_7_6_SNAPSHOT",  "V3_7_6",
-
                                                  "V3_7_7_SNAPSHOT",  "V3_7_7",
-
                                                  "V3_7_8_SNAPSHOT",  "V3_7_8",
-
                                                  "V3_7_9_SNAPSHOT",  "V3_7_9",
-
+                                                 "V3_8_0_SNAPSHOT",  "V3_8_0",
                                                  "V3_8_1_SNAPSHOT",  "V3_8_1",
-
                                                  "V3_8_2_SNAPSHOT",  "V3_8_2",
-
                                                  "V3_8_3_SNAPSHOT",  "V3_8_3",
-
                                                  "V3_8_4_SNAPSHOT",  "V3_8_4",
-
                                                  "V3_8_5_SNAPSHOT",  "V3_8_5",
-
                                                  "V3_8_6_SNAPSHOT",  "V3_8_6",
-
                                                  "V3_8_7_SNAPSHOT",  "V3_8_7",
-
                                                  "V3_8_8_SNAPSHOT",  "V3_8_8",
-
                                                  "V3_8_9_SNAPSHOT",  "V3_8_9",
-
                                                  "V3_9_1_SNAPSHOT",  "V3_9_1",
-
+                                                 "V3_9_0_SNAPSHOT",  "V3_9_0",
                                                  "V3_9_2_SNAPSHOT",  "V3_9_2",
-
                                                  "V3_9_3_SNAPSHOT",  "V3_9_3",
-
                                                  "V3_9_4_SNAPSHOT",  "V3_9_4",
-
                                                  "V3_9_5_SNAPSHOT",  "V3_9_5",
-
                                                  "V3_9_6_SNAPSHOT",  "V3_9_6",
-
                                                  "V3_9_7_SNAPSHOT",  "V3_9_7",
-
                                                  "V3_9_8_SNAPSHOT",  "V3_9_8",
-
                                                  "V3_9_9_SNAPSHOT",  "V3_9_9",
-
                                                  "V4_0_0_SNAPSHOT",  "V4_0_0",
-
                                                  "V4_0_1_SNAPSHOT",  "V4_0_1",
-
                                                  "V4_0_2_SNAPSHOT",  "V4_0_2",
-
                                                  "V4_0_3_SNAPSHOT",  "V4_0_3",
-
                                                  "V4_0_4_SNAPSHOT",  "V4_0_4",
-
                                                  "V4_0_5_SNAPSHOT",  "V4_0_5",
-
                                                  "V4_0_6_SNAPSHOT",  "V4_0_6",
-
                                                  "V4_0_7_SNAPSHOT",  "V4_0_7",
-
                                                  "V4_0_8_SNAPSHOT",  "V4_0_8",
-
                                                  "V4_0_9_SNAPSHOT",  "V4_0_9",
-
                                                  "V4_1_0_SNAPSHOT",  "V4_1_0",
-
                                                  "V4_1_1_SNAPSHOT",  "V4_1_1",
-
                                                  "V4_1_2_SNAPSHOT",  "V4_1_2",
-
                                                  "V4_1_3_SNAPSHOT",  "V4_1_3",
-
                                                  "V4_1_4_SNAPSHOT",  "V4_1_4",
-
                                                  "V4_1_5_SNAPSHOT",  "V4_1_5",
-
                                                  "V4_1_6_SNAPSHOT",  "V4_1_6",
-
                                                  "V4_1_7_SNAPSHOT",  "V4_1_7",
-
                                                  "V4_1_8_SNAPSHOT",  "V4_1_8",
-
                                                  "V4_1_9_SNAPSHOT",  "V4_1_9",
-
                                                  "V4_2_0_SNAPSHOT",  "V4_2_0",
-
                                                  "V4_2_1_SNAPSHOT",  "V4_2_1",
-
                                                  "V4_2_2_SNAPSHOT",  "V4_2_2",
-
                                                  "V4_2_3_SNAPSHOT",  "V4_2_3",
-
                                                  "V4_2_4_SNAPSHOT",  "V4_2_4",
-
                                                  "V4_2_5_SNAPSHOT",  "V4_2_5",
-
                                                  "V4_2_6_SNAPSHOT",  "V4_2_6",
-
                                                  "V4_2_7_SNAPSHOT",  "V4_2_7",
-
                                                  "V4_2_8_SNAPSHOT",  "V4_2_8",
-
                                                  "V4_2_9_SNAPSHOT",  "V4_2_9",
-
                                                  "V4_3_0_SNAPSHOT",  "V4_3_0",
-
                                                  "V4_3_1_SNAPSHOT",  "V4_3_1",
-
                                                  "V4_3_2_SNAPSHOT",  "V4_3_2",
-
                                                  "V4_3_3_SNAPSHOT",  "V4_3_3",
-
                                                  "V4_3_4_SNAPSHOT",  "V4_3_4",
-
                                                  "V4_3_5_SNAPSHOT",  "V4_3_5",
-
                                                  "V4_3_6_SNAPSHOT",  "V4_3_6",
-
                                                  "V4_3_7_SNAPSHOT",  "V4_3_7",
-
                                                  "V4_3_8_SNAPSHOT",  "V4_3_8",
-
                                                  "V4_3_9_SNAPSHOT",  "V4_3_9",
-
                                                  "V4_4_0_SNAPSHOT",  "V4_4_0",
-
                                                  "V4_4_1_SNAPSHOT",  "V4_4_1",
-
                                                  "V4_4_2_SNAPSHOT",  "V4_4_2",
-
                                                  "V4_4_3_SNAPSHOT",  "V4_4_3",
-
                                                  "V4_4_4_SNAPSHOT",  "V4_4_4",
-
                                                  "V4_4_5_SNAPSHOT",  "V4_4_5",
-
                                                  "V4_4_6_SNAPSHOT",  "V4_4_6",
-
                                                  "V4_4_7_SNAPSHOT",  "V4_4_7",
-
                                                  "V4_4_8_SNAPSHOT",  "V4_4_8",
-
                                                  "V4_4_9_SNAPSHOT",  "V4_4_9",
-
                                                  "V4_5_0_SNAPSHOT",  "V4_5_0",
-
                                                  "V4_5_1_SNAPSHOT",  "V4_5_1",
-
                                                  "V4_5_2_SNAPSHOT",  "V4_5_2",
-
                                                  "V4_5_3_SNAPSHOT",  "V4_5_3",
-
                                                  "V4_5_4_SNAPSHOT",  "V4_5_4",
-
                                                  "V4_5_5_SNAPSHOT",  "V4_5_5",
-
                                                  "V4_5_6_SNAPSHOT",  "V4_5_6",
-
                                                  "V4_5_7_SNAPSHOT",  "V4_5_7",
-
                                                  "V4_5_8_SNAPSHOT",  "V4_5_8",
-
                                                  "V4_5_9_SNAPSHOT",  "V4_5_9",
-
                                                  "V4_6_0_SNAPSHOT",  "V4_6_0",
-
                                                  "V4_6_1_SNAPSHOT",  "V4_6_1",
-
                                                  "V4_6_2_SNAPSHOT",  "V4_6_2",
-
                                                  "V4_6_3_SNAPSHOT",  "V4_6_3",
-
                                                  "V4_6_4_SNAPSHOT",  "V4_6_4",
-
                                                  "V4_6_5_SNAPSHOT",  "V4_6_5",
-
                                                  "V4_6_6_SNAPSHOT",  "V4_6_6",
-
                                                  "V4_6_7_SNAPSHOT",  "V4_6_7",
-
                                                  "V4_6_8_SNAPSHOT",  "V4_6_8",
-
                                                  "V4_6_9_SNAPSHOT",  "V4_6_9",
-
                                                  "V4_7_0_SNAPSHOT",  "V4_7_0",
-
                                                  "V4_7_1_SNAPSHOT",  "V4_7_1",
-
                                                  "V4_7_2_SNAPSHOT",  "V4_7_2",
-
                                                  "V4_7_3_SNAPSHOT",  "V4_7_3",
-
                                                  "V4_7_4_SNAPSHOT",  "V4_7_4",
-
                                                  "V4_7_5_SNAPSHOT",  "V4_7_5",
-
                                                  "V4_7_6_SNAPSHOT",  "V4_7_6",
-
                                                  "V4_7_7_SNAPSHOT",  "V4_7_7",
-
                                                  "V4_7_8_SNAPSHOT",  "V4_7_8",
-
                                                  "V4_7_9_SNAPSHOT",  "V4_7_9",
-
                                                  "V4_8_0_SNAPSHOT",  "V4_8_0",
-
                                                  "V4_8_1_SNAPSHOT",  "V4_8_1",
-
                                                  "V4_8_2_SNAPSHOT",  "V4_8_2",
-
                                                  "V4_8_3_SNAPSHOT",  "V4_8_3",
-
                                                  "V4_8_4_SNAPSHOT",  "V4_8_4",
-
                                                  "V4_8_5_SNAPSHOT",  "V4_8_5",
-
                                                  "V4_8_6_SNAPSHOT",  "V4_8_6",
-
                                                  "V4_8_7_SNAPSHOT",  "V4_8_7",
-
                                                  "V4_8_8_SNAPSHOT",  "V4_8_8",
-
                                                  "V4_8_9_SNAPSHOT",  "V4_8_9",
-
                                                  "V4_9_0_SNAPSHOT",  "V4_9_0",
-
                                                  "V4_9_1_SNAPSHOT",  "V4_9_1",
-
                                                  "V4_9_2_SNAPSHOT",  "V4_9_2",
-
                                                  "V4_9_3_SNAPSHOT",  "V4_9_3",
-
                                                  "V4_9_4_SNAPSHOT",  "V4_9_4",
-
                                                  "V4_9_5_SNAPSHOT",  "V4_9_5",
-
                                                  "V4_9_6_SNAPSHOT",  "V4_9_6",
-
                                                  "V4_9_7_SNAPSHOT",  "V4_9_7",
-
                                                  "V4_9_8_SNAPSHOT",  "V4_9_8",
-
                                                  "V4_9_9_SNAPSHOT",  "V4_9_9",
-
                                                  "V5_0_0_SNAPSHOT",  "V5_0_0",
-
                                                  "V5_0_1_SNAPSHOT",  "V5_0_1",
-
                                                  "V5_0_2_SNAPSHOT",  "V5_0_2",
-
                                                  "V5_0_3_SNAPSHOT",  "V5_0_3",
-
                                                  "V5_0_4_SNAPSHOT",  "V5_0_4",
-
                                                  "V5_0_5_SNAPSHOT",  "V5_0_5",
-
                                                  "V5_0_6_SNAPSHOT",  "V5_0_6",
-
                                                  "V5_0_7_SNAPSHOT",  "V5_0_7",
-
                                                  "V5_0_8_SNAPSHOT",  "V5_0_8",
-
                                                  "V5_0_9_SNAPSHOT",  "V5_0_9",
-
                                                  "V5_1_0_SNAPSHOT",  "V5_1_0",
-
                                                  "V5_1_1_SNAPSHOT",  "V5_1_1",
-
                                                  "V5_1_2_SNAPSHOT",  "V5_1_2",
-
                                                  "V5_1_3_SNAPSHOT",  "V5_1_3",
-
                                                  "V5_1_4_SNAPSHOT",  "V5_1_4",
-
                                                  "V5_1_5_SNAPSHOT",  "V5_1_5",
-
                                                  "V5_1_6_SNAPSHOT",  "V5_1_6",
-
                                                  "V5_1_7_SNAPSHOT",  "V5_1_7",
-
                                                  "V5_1_8_SNAPSHOT",  "V5_1_8",
-
                                                  "V5_1_9_SNAPSHOT",  "V5_1_9",
-
                                                  "V5_2_0_SNAPSHOT",  "V5_2_0",
-
                                                  "V5_2_1_SNAPSHOT",  "V5_2_1",
-
                                                  "V5_2_2_SNAPSHOT",  "V5_2_2",
-
                                                  "V5_2_3_SNAPSHOT",  "V5_2_3",
-
                                                  "V5_2_4_SNAPSHOT",  "V5_2_4",
-
                                                  "V5_2_5_SNAPSHOT",  "V5_2_5",
-
                                                  "V5_2_6_SNAPSHOT",  "V5_2_6",
-
                                                  "V5_2_7_SNAPSHOT",  "V5_2_7",
-
                                                  "V5_2_8_SNAPSHOT",  "V5_2_8",
-
                                                  "V5_2_9_SNAPSHOT",  "V5_2_9",
-
                                                  "V5_3_0_SNAPSHOT",  "V5_3_0",
-
                                                  "V5_3_1_SNAPSHOT",  "V5_3_1",
-
                                                  "V5_3_2_SNAPSHOT",  "V5_3_2",
-
                                                  "V5_3_3_SNAPSHOT",  "V5_3_3",
-
                                                  "V5_3_4_SNAPSHOT",  "V5_3_4",
-
                                                  "V5_3_5_SNAPSHOT",  "V5_3_5",
-
                                                  "V5_3_6_SNAPSHOT",  "V5_3_6",
-
                                                  "V5_3_7_SNAPSHOT",  "V5_3_7",
-
                                                  "V5_3_8_SNAPSHOT",  "V5_3_8",
-
                                                  "V5_3_9_SNAPSHOT",  "V5_3_9",
-
                                                  "V5_4_0_SNAPSHOT",  "V5_4_0",
-
                                                  "V5_4_1_SNAPSHOT",  "V5_4_1",
-
                                                  "V5_4_2_SNAPSHOT",  "V5_4_2",
-
                                                  "V5_4_3_SNAPSHOT",  "V5_4_3",
-
                                                  "V5_4_4_SNAPSHOT",  "V5_4_4",
-
                                                  "V5_4_5_SNAPSHOT",  "V5_4_5",
-
                                                  "V5_4_6_SNAPSHOT",  "V5_4_6",
-
                                                  "V5_4_7_SNAPSHOT",  "V5_4_7",
-
                                                  "V5_4_8_SNAPSHOT",  "V5_4_8",
-
                                                  "V5_4_9_SNAPSHOT",  "V5_4_9",
-
                                                  "V5_5_0_SNAPSHOT",  "V5_5_0",
-
                                                  "V5_5_1_SNAPSHOT",  "V5_5_1",
-
                                                  "V5_5_2_SNAPSHOT",  "V5_5_2",
-
                                                  "V5_5_3_SNAPSHOT",  "V5_5_3",
-
                                                  "V5_5_4_SNAPSHOT",  "V5_5_4",
-
                                                  "V5_5_5_SNAPSHOT",  "V5_5_5",
-
                                                  "V5_5_6_SNAPSHOT",  "V5_5_6",
-
                                                  "V5_5_7_SNAPSHOT",  "V5_5_7",
-
                                                  "V5_5_8_SNAPSHOT",  "V5_5_8",
-
                                                  "V5_5_9_SNAPSHOT",  "V5_5_9",
-
                                                  "V5_6_0_SNAPSHOT",  "V5_6_0",
-
                                                  "V5_6_1_SNAPSHOT",  "V5_6_1",
-
                                                  "V5_6_2_SNAPSHOT",  "V5_6_2",
-
                                                  "V5_6_3_SNAPSHOT",  "V5_6_3",
-
                                                  "V5_6_4_SNAPSHOT",  "V5_6_4",
-
                                                  "V5_6_5_SNAPSHOT",  "V5_6_5",
-
                                                  "V5_6_6_SNAPSHOT",  "V5_6_6",
-
                                                  "V5_6_7_SNAPSHOT",  "V5_6_7",
-
                                                  "V5_6_8_SNAPSHOT",  "V5_6_8",
-
                                                  "V5_6_9_SNAPSHOT",  "V5_6_9",
-
                                                  "V5_7_0_SNAPSHOT",  "V5_7_0",
-
                                                  "V5_7_1_SNAPSHOT",  "V5_7_1",
-
                                                  "V5_7_2_SNAPSHOT",  "V5_7_2",
-
                                                  "V5_7_3_SNAPSHOT",  "V5_7_3",
-
                                                  "V5_7_4_SNAPSHOT",  "V5_7_4",
-
                                                  "V5_7_5_SNAPSHOT",  "V5_7_5",
-
                                                  "V5_7_6_SNAPSHOT",  "V5_7_6",
-
                                                  "V5_7_7_SNAPSHOT",  "V5_7_7",
-
                                                  "V5_7_8_SNAPSHOT",  "V5_7_8",
-
                                                  "V5_7_9_SNAPSHOT",  "V5_7_9",
-
                                                  "V5_8_0_SNAPSHOT",  "V5_8_0",
-
                                                  "V5_8_1_SNAPSHOT",  "V5_8_1",
-
                                                  "V5_8_2_SNAPSHOT",  "V5_8_2",
-
                                                  "V5_8_3_SNAPSHOT",  "V5_8_3",
-
                                                  "V5_8_4_SNAPSHOT",  "V5_8_4",
-
                                                  "V5_8_5_SNAPSHOT",  "V5_8_5",
-
                                                  "V5_8_6_SNAPSHOT",  "V5_8_6",
-
                                                  "V5_8_7_SNAPSHOT",  "V5_8_7",
-
                                                  "V5_8_8_SNAPSHOT",  "V5_8_8",
-
                                                  "V5_8_9_SNAPSHOT",  "V5_8_9",
-
                                                  "V5_9_0_SNAPSHOT",  "V5_9_0",
-
                                                  "V5_9_1_SNAPSHOT",  "V5_9_1",
-
                                                  "V5_9_2_SNAPSHOT",  "V5_9_2",
-
                                                  "V5_9_3_SNAPSHOT",  "V5_9_3",
-
                                                  "V5_9_4_SNAPSHOT",  "V5_9_4",
-
                                                  "V5_9_5_SNAPSHOT",  "V5_9_5",
-
                                                  "V5_9_6_SNAPSHOT",  "V5_9_6",
-
                                                  "V5_9_7_SNAPSHOT",  "V5_9_7",
-
                                                  "V5_9_8_SNAPSHOT",  "V5_9_8",
-
                                                  "V5_9_9_SNAPSHOT",  "V5_9_9",
-                                                 "HIGHER_VERSION"
+                                                 "HIGHER_VERSION"};
 
-};
 class MQVersion {
  public:
   enum Version {
@@ -655,879 +373,605 @@ class MQVersion {
     V3_0_8,
     V3_0_9_SNAPSHOT,
     V3_0_9,
-
     V3_0_10_SNAPSHOT,
     V3_0_10,
-
     V3_0_11_SNAPSHOT,
     V3_0_11,
-
     V3_0_12_SNAPSHOT,
     V3_0_12,
-
     V3_0_13_SNAPSHOT,
     V3_0_13,
-
     V3_0_14_SNAPSHOT,
     V3_0_14,
-
     V3_0_15_SNAPSHOT,
     V3_0_15,
-
     V3_1_0_SNAPSHOT,
     V3_1_0,
-
     V3_1_1_SNAPSHOT,
     V3_1_1,
-
     V3_1_2_SNAPSHOT,
     V3_1_2,
-
     V3_1_3_SNAPSHOT,
     V3_1_3,
-
     V3_1_4_SNAPSHOT,
     V3_1_4,
-
     V3_1_5_SNAPSHOT,
     V3_1_5,
-
     V3_1_6_SNAPSHOT,
     V3_1_6,
-
     V3_1_7_SNAPSHOT,
     V3_1_7,
-
     V3_1_8_SNAPSHOT,
     V3_1_8,
-
     V3_1_9_SNAPSHOT,
     V3_1_9,
-
     V3_2_0_SNAPSHOT,
     V3_2_0,
-
     V3_2_1_SNAPSHOT,
     V3_2_1,
-
     V3_2_2_SNAPSHOT,
     V3_2_2,
-
     V3_2_3_SNAPSHOT,
     V3_2_3,
-
     V3_2_4_SNAPSHOT,
     V3_2_4,
-
     V3_2_5_SNAPSHOT,
     V3_2_5,
-
     V3_2_6_SNAPSHOT,
     V3_2_6,
-
     V3_2_7_SNAPSHOT,
     V3_2_7,
-
     V3_2_8_SNAPSHOT,
     V3_2_8,
-
     V3_2_9_SNAPSHOT,
     V3_2_9,
-
+    V3_3_0_SNAPSHOT,
+    V3_3_0,
     V3_3_1_SNAPSHOT,
     V3_3_1,
-
     V3_3_2_SNAPSHOT,
     V3_3_2,
-
     V3_3_3_SNAPSHOT,
     V3_3_3,
-
     V3_3_4_SNAPSHOT,
     V3_3_4,
-
     V3_3_5_SNAPSHOT,
     V3_3_5,
-
     V3_3_6_SNAPSHOT,
     V3_3_6,
-
     V3_3_7_SNAPSHOT,
     V3_3_7,
-
     V3_3_8_SNAPSHOT,
     V3_3_8,
-
     V3_3_9_SNAPSHOT,
     V3_3_9,
-
+    V3_4_0_SNAPSHOT,
+    V3_4_0,
     V3_4_1_SNAPSHOT,
     V3_4_1,
-
     V3_4_2_SNAPSHOT,
     V3_4_2,
-
     V3_4_3_SNAPSHOT,
     V3_4_3,
-
     V3_4_4_SNAPSHOT,
     V3_4_4,
-
     V3_4_5_SNAPSHOT,
     V3_4_5,
-
     V3_4_6_SNAPSHOT,
     V3_4_6,
-
     V3_4_7_SNAPSHOT,
     V3_4_7,
-
     V3_4_8_SNAPSHOT,
     V3_4_8,
-
     V3_4_9_SNAPSHOT,
     V3_4_9,
+    V3_5_0_SNAPSHOT,
+    V3_5_0,
     V3_5_1_SNAPSHOT,
     V3_5_1,
-
     V3_5_2_SNAPSHOT,
     V3_5_2,
-
     V3_5_3_SNAPSHOT,
     V3_5_3,
-
     V3_5_4_SNAPSHOT,
     V3_5_4,
-
     V3_5_5_SNAPSHOT,
     V3_5_5,
-
     V3_5_6_SNAPSHOT,
     V3_5_6,
-
     V3_5_7_SNAPSHOT,
     V3_5_7,
-
     V3_5_8_SNAPSHOT,
     V3_5_8,
-
     V3_5_9_SNAPSHOT,
     V3_5_9,
-
+    V3_6_0_SNAPSHOT,
+    V3_6_0,
     V3_6_1_SNAPSHOT,
     V3_6_1,
-
     V3_6_2_SNAPSHOT,
     V3_6_2,
-
     V3_6_3_SNAPSHOT,
     V3_6_3,
-
     V3_6_4_SNAPSHOT,
     V3_6_4,
-
     V3_6_5_SNAPSHOT,
     V3_6_5,
-
     V3_6_6_SNAPSHOT,
     V3_6_6,
-
     V3_6_7_SNAPSHOT,
     V3_6_7,
-
     V3_6_8_SNAPSHOT,
     V3_6_8,
-
     V3_6_9_SNAPSHOT,
     V3_6_9,
-
+    V3_7_0_SNAPSHOT,
+    V3_7_0,
     V3_7_1_SNAPSHOT,
     V3_7_1,
-
     V3_7_2_SNAPSHOT,
     V3_7_2,
-
     V3_7_3_SNAPSHOT,
     V3_7_3,
-
     V3_7_4_SNAPSHOT,
     V3_7_4,
-
     V3_7_5_SNAPSHOT,
     V3_7_5,
-
     V3_7_6_SNAPSHOT,
     V3_7_6,
-
     V3_7_7_SNAPSHOT,
     V3_7_7,
-
     V3_7_8_SNAPSHOT,
     V3_7_8,
-
     V3_7_9_SNAPSHOT,
     V3_7_9,
-
+    V3_8_0_SNAPSHOT,
+    V3_8_0,
     V3_8_1_SNAPSHOT,
     V3_8_1,
-
     V3_8_2_SNAPSHOT,
     V3_8_2,
-
     V3_8_3_SNAPSHOT,
     V3_8_3,
-
     V3_8_4_SNAPSHOT,
     V3_8_4,
-
     V3_8_5_SNAPSHOT,
     V3_8_5,
-
     V3_8_6_SNAPSHOT,
     V3_8_6,
-
     V3_8_7_SNAPSHOT,
     V3_8_7,
-
     V3_8_8_SNAPSHOT,
     V3_8_8,
-
     V3_8_9_SNAPSHOT,
     V3_8_9,
-
+    V3_9_0_SNAPSHOT,
+    V3_9_0,
     V3_9_1_SNAPSHOT,
     V3_9_1,
-
     V3_9_2_SNAPSHOT,
     V3_9_2,
-
     V3_9_3_SNAPSHOT,
     V3_9_3,
-
     V3_9_4_SNAPSHOT,
     V3_9_4,
-
     V3_9_5_SNAPSHOT,
     V3_9_5,
-
     V3_9_6_SNAPSHOT,
     V3_9_6,
-
     V3_9_7_SNAPSHOT,
     V3_9_7,
-
     V3_9_8_SNAPSHOT,
     V3_9_8,
-
     V3_9_9_SNAPSHOT,
     V3_9_9,
-
     V4_0_0_SNAPSHOT,
     V4_0_0,
-
     V4_0_1_SNAPSHOT,
     V4_0_1,
-
     V4_0_2_SNAPSHOT,
     V4_0_2,
-
     V4_0_3_SNAPSHOT,
     V4_0_3,
-
     V4_0_4_SNAPSHOT,
     V4_0_4,
-
     V4_0_5_SNAPSHOT,
     V4_0_5,
-
     V4_0_6_SNAPSHOT,
     V4_0_6,
-
     V4_0_7_SNAPSHOT,
     V4_0_7,
-
     V4_0_8_SNAPSHOT,
     V4_0_8,
-
     V4_0_9_SNAPSHOT,
     V4_0_9,
-
     V4_1_0_SNAPSHOT,
     V4_1_0,
-
     V4_1_1_SNAPSHOT,
     V4_1_1,
-
     V4_1_2_SNAPSHOT,
     V4_1_2,
-
     V4_1_3_SNAPSHOT,
     V4_1_3,
-
     V4_1_4_SNAPSHOT,
     V4_1_4,
-
     V4_1_5_SNAPSHOT,
     V4_1_5,
-
     V4_1_6_SNAPSHOT,
     V4_1_6,
-
     V4_1_7_SNAPSHOT,
     V4_1_7,
-
     V4_1_8_SNAPSHOT,
     V4_1_8,
-
     V4_1_9_SNAPSHOT,
     V4_1_9,
-
     V4_2_0_SNAPSHOT,
     V4_2_0,
-
     V4_2_1_SNAPSHOT,
     V4_2_1,
-
     V4_2_2_SNAPSHOT,
     V4_2_2,
-
     V4_2_3_SNAPSHOT,
     V4_2_3,
-
     V4_2_4_SNAPSHOT,
     V4_2_4,
-
     V4_2_5_SNAPSHOT,
     V4_2_5,
-
     V4_2_6_SNAPSHOT,
     V4_2_6,
-
     V4_2_7_SNAPSHOT,
     V4_2_7,
-
     V4_2_8_SNAPSHOT,
     V4_2_8,
-
     V4_2_9_SNAPSHOT,
     V4_2_9,
-
     V4_3_0_SNAPSHOT,
     V4_3_0,
-
     V4_3_1_SNAPSHOT,
     V4_3_1,
-
     V4_3_2_SNAPSHOT,
     V4_3_2,
-
     V4_3_3_SNAPSHOT,
     V4_3_3,
-
     V4_3_4_SNAPSHOT,
     V4_3_4,
-
     V4_3_5_SNAPSHOT,
     V4_3_5,
-
     V4_3_6_SNAPSHOT,
     V4_3_6,
-
     V4_3_7_SNAPSHOT,
     V4_3_7,
-
     V4_3_8_SNAPSHOT,
     V4_3_8,
-
     V4_3_9_SNAPSHOT,
     V4_3_9,
-
     V4_4_0_SNAPSHOT,
     V4_4_0,
-
     V4_4_1_SNAPSHOT,
     V4_4_1,
-
     V4_4_2_SNAPSHOT,
     V4_4_2,
-
     V4_4_3_SNAPSHOT,
     V4_4_3,
-
     V4_4_4_SNAPSHOT,
     V4_4_4,
-
     V4_4_5_SNAPSHOT,
     V4_4_5,
-
     V4_4_6_SNAPSHOT,
     V4_4_6,
-
     V4_4_7_SNAPSHOT,
     V4_4_7,
-
     V4_4_8_SNAPSHOT,
     V4_4_8,
-
     V4_4_9_SNAPSHOT,
     V4_4_9,
-
     V4_5_0_SNAPSHOT,
     V4_5_0,
-
     V4_5_1_SNAPSHOT,
     V4_5_1,
-
     V4_5_2_SNAPSHOT,
     V4_5_2,
-
     V4_5_3_SNAPSHOT,
     V4_5_3,
-
     V4_5_4_SNAPSHOT,
     V4_5_4,
-
     V4_5_5_SNAPSHOT,
     V4_5_5,
-
     V4_5_6_SNAPSHOT,
     V4_5_6,
-
     V4_5_7_SNAPSHOT,
     V4_5_7,
-
     V4_5_8_SNAPSHOT,
     V4_5_8,
-
     V4_5_9_SNAPSHOT,
     V4_5_9,
-
     V4_6_0_SNAPSHOT,
     V4_6_0,
-
     V4_6_1_SNAPSHOT,
     V4_6_1,
-
     V4_6_2_SNAPSHOT,
     V4_6_2,
-
     V4_6_3_SNAPSHOT,
     V4_6_3,
-
     V4_6_4_SNAPSHOT,
     V4_6_4,
-
     V4_6_5_SNAPSHOT,
     V4_6_5,
-
     V4_6_6_SNAPSHOT,
     V4_6_6,
-
     V4_6_7_SNAPSHOT,
     V4_6_7,
-
     V4_6_8_SNAPSHOT,
     V4_6_8,
-
     V4_6_9_SNAPSHOT,
     V4_6_9,
-
     V4_7_0_SNAPSHOT,
     V4_7_0,
-
     V4_7_1_SNAPSHOT,
     V4_7_1,
-
     V4_7_2_SNAPSHOT,
     V4_7_2,
-
     V4_7_3_SNAPSHOT,
     V4_7_3,
-
     V4_7_4_SNAPSHOT,
     V4_7_4,
-
     V4_7_5_SNAPSHOT,
     V4_7_5,
-
     V4_7_6_SNAPSHOT,
     V4_7_6,
-
     V4_7_7_SNAPSHOT,
     V4_7_7,
-
     V4_7_8_SNAPSHOT,
     V4_7_8,
-
     V4_7_9_SNAPSHOT,
     V4_7_9,
-
     V4_8_0_SNAPSHOT,
     V4_8_0,
-
     V4_8_1_SNAPSHOT,
     V4_8_1,
-
     V4_8_2_SNAPSHOT,
     V4_8_2,
-
     V4_8_3_SNAPSHOT,
     V4_8_3,
-
     V4_8_4_SNAPSHOT,
     V4_8_4,
-
     V4_8_5_SNAPSHOT,
     V4_8_5,
-
     V4_8_6_SNAPSHOT,
     V4_8_6,
-
     V4_8_7_SNAPSHOT,
     V4_8_7,
-
     V4_8_8_SNAPSHOT,
     V4_8_8,
-
     V4_8_9_SNAPSHOT,
     V4_8_9,
-
     V4_9_0_SNAPSHOT,
     V4_9_0,
-
     V4_9_1_SNAPSHOT,
     V4_9_1,
-
     V4_9_2_SNAPSHOT,
     V4_9_2,
-
     V4_9_3_SNAPSHOT,
     V4_9_3,
-
     V4_9_4_SNAPSHOT,
     V4_9_4,
-
     V4_9_5_SNAPSHOT,
     V4_9_5,
-
     V4_9_6_SNAPSHOT,
     V4_9_6,
-
     V4_9_7_SNAPSHOT,
     V4_9_7,
-
     V4_9_8_SNAPSHOT,
     V4_9_8,
-
     V4_9_9_SNAPSHOT,
     V4_9_9,
-
     V5_0_0_SNAPSHOT,
     V5_0_0,
-
     V5_0_1_SNAPSHOT,
     V5_0_1,
-
     V5_0_2_SNAPSHOT,
     V5_0_2,
-
     V5_0_3_SNAPSHOT,
     V5_0_3,
-
     V5_0_4_SNAPSHOT,
     V5_0_4,
-
     V5_0_5_SNAPSHOT,
     V5_0_5,
-
     V5_0_6_SNAPSHOT,
     V5_0_6,
-
     V5_0_7_SNAPSHOT,
     V5_0_7,
-
     V5_0_8_SNAPSHOT,
     V5_0_8,
-
     V5_0_9_SNAPSHOT,
     V5_0_9,
-
     V5_1_0_SNAPSHOT,
     V5_1_0,
-
     V5_1_1_SNAPSHOT,
     V5_1_1,
-
     V5_1_2_SNAPSHOT,
     V5_1_2,
-
     V5_1_3_SNAPSHOT,
     V5_1_3,
-
     V5_1_4_SNAPSHOT,
     V5_1_4,
-
     V5_1_5_SNAPSHOT,
     V5_1_5,
-
     V5_1_6_SNAPSHOT,
     V5_1_6,
-
     V5_1_7_SNAPSHOT,
     V5_1_7,
-
     V5_1_8_SNAPSHOT,
     V5_1_8,
-
     V5_1_9_SNAPSHOT,
     V5_1_9,
-
     V5_2_0_SNAPSHOT,
     V5_2_0,
-
     V5_2_1_SNAPSHOT,
     V5_2_1,
-
     V5_2_2_SNAPSHOT,
     V5_2_2,
-
     V5_2_3_SNAPSHOT,
     V5_2_3,
-
     V5_2_4_SNAPSHOT,
     V5_2_4,
-
     V5_2_5_SNAPSHOT,
     V5_2_5,
-
     V5_2_6_SNAPSHOT,
     V5_2_6,
-
     V5_2_7_SNAPSHOT,
     V5_2_7,
-
     V5_2_8_SNAPSHOT,
     V5_2_8,
-
     V5_2_9_SNAPSHOT,
     V5_2_9,
-
     V5_3_0_SNAPSHOT,
     V5_3_0,
-
     V5_3_1_SNAPSHOT,
     V5_3_1,
-
     V5_3_2_SNAPSHOT,
     V5_3_2,
-
     V5_3_3_SNAPSHOT,
     V5_3_3,
-
     V5_3_4_SNAPSHOT,
     V5_3_4,
-
     V5_3_5_SNAPSHOT,
     V5_3_5,
-
     V5_3_6_SNAPSHOT,
     V5_3_6,
-
     V5_3_7_SNAPSHOT,
     V5_3_7,
-
     V5_3_8_SNAPSHOT,
     V5_3_8,
-
     V5_3_9_SNAPSHOT,
     V5_3_9,
-
     V5_4_0_SNAPSHOT,
     V5_4_0,
-
     V5_4_1_SNAPSHOT,
     V5_4_1,
-
     V5_4_2_SNAPSHOT,
     V5_4_2,
-
     V5_4_3_SNAPSHOT,
     V5_4_3,
-
     V5_4_4_SNAPSHOT,
     V5_4_4,
-
     V5_4_5_SNAPSHOT,
     V5_4_5,
-
     V5_4_6_SNAPSHOT,
     V5_4_6,
-
     V5_4_7_SNAPSHOT,
     V5_4_7,
-
     V5_4_8_SNAPSHOT,
     V5_4_8,
-
     V5_4_9_SNAPSHOT,
     V5_4_9,
-
     V5_5_0_SNAPSHOT,
     V5_5_0,
-
     V5_5_1_SNAPSHOT,
     V5_5_1,
-
     V5_5_2_SNAPSHOT,
     V5_5_2,
-
     V5_5_3_SNAPSHOT,
     V5_5_3,
-
     V5_5_4_SNAPSHOT,
     V5_5_4,
-
     V5_5_5_SNAPSHOT,
     V5_5_5,
-
     V5_5_6_SNAPSHOT,
     V5_5_6,
-
     V5_5_7_SNAPSHOT,
     V5_5_7,
-
     V5_5_8_SNAPSHOT,
     V5_5_8,
-
     V5_5_9_SNAPSHOT,
     V5_5_9,
-
     V5_6_0_SNAPSHOT,
     V5_6_0,
-
     V5_6_1_SNAPSHOT,
     V5_6_1,
-
     V5_6_2_SNAPSHOT,
     V5_6_2,
-
     V5_6_3_SNAPSHOT,
     V5_6_3,
-
     V5_6_4_SNAPSHOT,
     V5_6_4,
-
     V5_6_5_SNAPSHOT,
     V5_6_5,
-
     V5_6_6_SNAPSHOT,
     V5_6_6,
-
     V5_6_7_SNAPSHOT,
     V5_6_7,
-
     V5_6_8_SNAPSHOT,
     V5_6_8,
-
     V5_6_9_SNAPSHOT,
     V5_6_9,
-
     V5_7_0_SNAPSHOT,
     V5_7_0,
-
     V5_7_1_SNAPSHOT,
     V5_7_1,
-
     V5_7_2_SNAPSHOT,
     V5_7_2,
-
     V5_7_3_SNAPSHOT,
     V5_7_3,
-
     V5_7_4_SNAPSHOT,
     V5_7_4,
-
     V5_7_5_SNAPSHOT,
     V5_7_5,
-
     V5_7_6_SNAPSHOT,
     V5_7_6,
-
     V5_7_7_SNAPSHOT,
     V5_7_7,
-
     V5_7_8_SNAPSHOT,
     V5_7_8,
-
     V5_7_9_SNAPSHOT,
     V5_7_9,
-
     V5_8_0_SNAPSHOT,
     V5_8_0,
-
     V5_8_1_SNAPSHOT,
     V5_8_1,
-
     V5_8_2_SNAPSHOT,
     V5_8_2,
-
     V5_8_3_SNAPSHOT,
     V5_8_3,
-
     V5_8_4_SNAPSHOT,
     V5_8_4,
-
     V5_8_5_SNAPSHOT,
     V5_8_5,
-
     V5_8_6_SNAPSHOT,
     V5_8_6,
-
     V5_8_7_SNAPSHOT,
     V5_8_7,
-
     V5_8_8_SNAPSHOT,
     V5_8_8,
-
     V5_8_9_SNAPSHOT,
     V5_8_9,
-
     V5_9_0_SNAPSHOT,
     V5_9_0,
-
     V5_9_1_SNAPSHOT,
     V5_9_1,
-
     V5_9_2_SNAPSHOT,
     V5_9_2,
-
     V5_9_3_SNAPSHOT,
     V5_9_3,
-
     V5_9_4_SNAPSHOT,
     V5_9_4,
-
     V5_9_5_SNAPSHOT,
     V5_9_5,
-
     V5_9_6_SNAPSHOT,
     V5_9_6,
-
     V5_9_7_SNAPSHOT,
     V5_9_7,
-
     V5_9_8_SNAPSHOT,
     V5_9_8,
-
     V5_9_9_SNAPSHOT,
     V5_9_9,
-
     HIGHER_VERSION
   };
 
+  static const int s_CurrentVersion;
+  static const std::string s_CurrentLanguage;
+
   static const char* GetVersionDesc(int value);
-  static int s_CurrentVersion;
-  static std::string s_CurrentLanguage;
 };
 
 }  // namespace rocketmq
diff --git a/src/common/MemoryInputStream.h b/src/common/MemoryInputStream.h
index c6f94e4..2097ec6 100644
--- a/src/common/MemoryInputStream.h
+++ b/src/common/MemoryInputStream.h
@@ -14,12 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef MEMORYINPUTSTREAM_H_INCLUDED
-#define MEMORYINPUTSTREAM_H_INCLUDED
+#ifndef __MEMORY_INTPUT_STREAM_H__
+#define __MEMORY_INTPUT_STREAM_H__
 
 #include "InputStream.h"
 
 namespace rocketmq {
+
 //==============================================================================
 /**
     Allows a block of data to be accessed as a stream.
@@ -91,5 +92,7 @@ class ROCKETMQCLIENT_API MemoryInputStream : public InputStream {
 
   void createInternalCopy();
 };
+
 }  // namespace rocketmq
-#endif
+
+#endif  // __MEMORY_INTPUT_STREAM_H__
diff --git a/src/common/MemoryOutputStream.cpp b/src/common/MemoryOutputStream.cpp
index f51444d..1c4f4da 100644
--- a/src/common/MemoryOutputStream.cpp
+++ b/src/common/MemoryOutputStream.cpp
@@ -99,7 +99,7 @@ bool MemoryOutputStream::write(const void* const buffer, size_t howMany) {
   return false;
 }
 
-bool MemoryOutputStream::writeRepeatedByte(uint8 byte, size_t howMany) {
+bool MemoryOutputStream::writeRepeatedByte(uint8_t byte, size_t howMany) {
   if (howMany == 0) {
     return true;
   }
@@ -121,8 +121,8 @@ const void* MemoryOutputStream::getData() const {
     return externalData;
   }
 
-  if ((unsigned int)poolToUse->getSize() > size) {
-    static_cast<char*>(poolToUse->getData())[size] = 0;
+  if (poolToUse->getSize() > size) {
+    poolToUse->getData()[size] = 0;
   }
 
   return poolToUse->getData();
diff --git a/src/common/MemoryOutputStream.h b/src/common/MemoryOutputStream.h
index 6b24e30..ece1a19 100644
--- a/src/common/MemoryOutputStream.h
+++ b/src/common/MemoryOutputStream.h
@@ -14,12 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef MEMORYOUTPUTSTREAM_H_INCLUDED
-#define MEMORYOUTPUTSTREAM_H_INCLUDED
+#ifndef __MEMORY_OUTPUT_STREAM_H__
+#define __MEMORY_OUTPUT_STREAM_H__
 
 #include "OutputStream.h"
 
 namespace rocketmq {
+
 //==============================================================================
 /**
     Writes data to an internal memory buffer, which grows as required.
@@ -109,7 +110,7 @@ class ROCKETMQCLIENT_API MemoryOutputStream : public OutputStream {
   int64_t getPosition() { return (int64_t)position; }
   bool setPosition(int64_t);
   int64_t writeFromInputStream(InputStream&, int64_t maxNumBytesToWrite);
-  bool writeRepeatedByte(uint8 byte, size_t numTimesToRepeat);
+  bool writeRepeatedByte(uint8_t byte, size_t numTimesToRepeat);
 
  private:
   //==============================================================================
@@ -125,5 +126,7 @@ class ROCKETMQCLIENT_API MemoryOutputStream : public OutputStream {
 /** Copies all the data that has been written to a MemoryOutputStream into
  * another stream. */
 OutputStream& operator<<(OutputStream& stream, const MemoryOutputStream& streamToRead);
+
 }  // namespace rocketmq
-#endif  // MEMORYOUTPUTSTREAM_H_INCLUDED
+
+#endif  // __MEMORY_OUTPUT_STREAM_H__
diff --git a/src/common/NamesrvConfig.h b/src/common/NamesrvConfig.h
index 0276f53..e74a6b3 100644
--- a/src/common/NamesrvConfig.h
+++ b/src/common/NamesrvConfig.h
@@ -17,8 +17,8 @@
 #ifndef __NAMESRV_CONFIG_H__
 #define __NAMESRV_CONFIG_H__
 
-#include <stdlib.h>
 #include <string>
+
 #include "UtilAll.h"
 
 namespace rocketmq {
@@ -32,17 +32,17 @@ class NamesrvConfig {
     }
   }
 
-  const string& getRocketmqHome() const { return m_rocketmqHome; }
+  const std::string& getRocketmqHome() const { return m_rocketmqHome; }
 
-  void setRocketmqHome(const string& rocketmqHome) { m_rocketmqHome = rocketmqHome; }
+  void setRocketmqHome(const std::string& rocketmqHome) { m_rocketmqHome = rocketmqHome; }
 
-  const string& getKvConfigPath() const { return m_kvConfigPath; }
+  const std::string& getKvConfigPath() const { return m_kvConfigPath; }
 
-  void setKvConfigPath(const string& kvConfigPath) { m_kvConfigPath = kvConfigPath; }
+  void setKvConfigPath(const std::string& kvConfigPath) { m_kvConfigPath = kvConfigPath; }
 
  private:
-  string m_rocketmqHome;
-  string m_kvConfigPath;
+  std::string m_rocketmqHome;
+  std::string m_kvConfigPath;
 };
 
 }  // namespace rocketmq
diff --git a/src/common/OutputStream.cpp b/src/common/OutputStream.cpp
index 49162ce..4a95013 100644
--- a/src/common/OutputStream.cpp
+++ b/src/common/OutputStream.cpp
@@ -36,7 +36,7 @@ bool OutputStream::writeByte(char byte) {
   return write(&byte, 1);
 }
 
-bool OutputStream::writeRepeatedByte(uint8 byte, size_t numTimesToRepeat) {
+bool OutputStream::writeRepeatedByte(uint8_t byte, size_t numTimesToRepeat) {
   for (size_t i = 0; i < numTimesToRepeat; ++i)
     if (!writeByte((char)byte))
       return false;
diff --git a/src/common/OutputStream.h b/src/common/OutputStream.h
index a6b2c26..46378a2 100644
--- a/src/common/OutputStream.h
+++ b/src/common/OutputStream.h
@@ -14,11 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef OUTPUTSTREAM_H_INCLUDED
-#define OUTPUTSTREAM_H_INCLUDED
+#ifndef __OUTPUT_STREAM_H__
+#define __OUTPUT_STREAM_H__
 
 #include "InputStream.h"
+
 namespace rocketmq {
+
 //==============================================================================
 /**
     The base class for streams that write data to some kind of destination.
@@ -128,7 +130,7 @@ class ROCKETMQCLIENT_API OutputStream {
   /** Writes a byte to the output stream a given number of times.
       @returns false if the write operation fails for some reason
   */
-  virtual bool writeRepeatedByte(uint8 byte, size_t numTimesToRepeat);
+  virtual bool writeRepeatedByte(uint8_t byte, size_t numTimesToRepeat);
 
   /** Reads data from an input stream and writes it to this stream.
 
@@ -142,6 +144,7 @@ class ROCKETMQCLIENT_API OutputStream {
   */
   virtual int64_t writeFromInputStream(InputStream& source, int64_t maxNumBytesToWrite);
 };
+
 }  // namespace rocketmq
 
-#endif  // OUTPUTSTREAM_H_INCLUDED
+#endif  // __OUTPUT_STREAM_H__
diff --git a/src/common/SendCallbackWrap.cpp b/src/common/SendCallbackWrap.cpp
index 66bf51a..4df8883 100755
--- a/src/common/SendCallbackWrap.cpp
+++ b/src/common/SendCallbackWrap.cpp
@@ -18,7 +18,6 @@
 
 #include <typeindex>
 
-#include "CommandHeader.h"
 #include "DefaultMQProducer.h"
 #include "Logging.h"
 #include "MQClientAPIImpl.h"
@@ -29,6 +28,7 @@
 #include "PullAPIWrapper.h"
 #include "PullResultExt.h"
 #include "TopicPublishInfo.h"
+#include "protocol/header/CommandHeader.h"
 
 namespace rocketmq {
 
@@ -60,7 +60,7 @@ void SendCallbackWrap::operationComplete(ResponseFuture* responseFuture) noexcep
     m_sendCallback->onException(exception);
 
     // auto delete callback
-    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(m_sendCallback);
     }
     return;
@@ -107,7 +107,7 @@ void SendCallbackWrap::operationComplete(ResponseFuture* responseFuture) noexcep
                                 false);
 
       // auto delete callback
-      if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+      if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
         deleteAndZero(m_sendCallback);
       }
     } catch (MQException& e) {
@@ -140,7 +140,7 @@ void SendCallbackWrap::onExceptionImpl(ResponseFuture* responseFuture,
     m_sendCallback->onException(exception);
 
     // auto delete callback
-    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(m_sendCallback);
     }
     return;
@@ -184,7 +184,7 @@ void SendCallbackWrap::onExceptionImpl(ResponseFuture* responseFuture,
     m_sendCallback->onException(e);
 
     // auto delete callback
-    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (m_sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(m_sendCallback);
     }
   }
diff --git a/src/common/SubscriptionData.h b/src/common/SubscriptionData.h
index 85ba261..9db58d9 100644
--- a/src/common/SubscriptionData.h
+++ b/src/common/SubscriptionData.h
@@ -17,11 +17,11 @@
 #ifndef __SUBSCRIPTION_DATA_H__
 #define __SUBSCRIPTION_DATA_H__
 
+#include <json/json.h>
+
 #include <string>
 #include <vector>
 
-#include <json/json.h>
-
 #include "RocketMQClient.h"
 
 namespace rocketmq {
@@ -51,9 +51,11 @@ class ROCKETMQCLIENT_API SubscriptionData {
   bool containTag(const std::string& tag);
   std::vector<std::string>& getTagsSet();
 
-  void putCodeSet(const int32 code);
+  void putCodeSet(int32_t code);
 
   bool operator==(const SubscriptionData& other) const;
+  bool operator!=(const SubscriptionData& other) const { return !operator==(other); }
+
   bool operator<(const SubscriptionData& other) const;
 
   Json::Value toJson() const;
diff --git a/src/common/TopicConfig.cpp b/src/common/TopicConfig.cpp
index a08659b..3a7a196 100644
--- a/src/common/TopicConfig.cpp
+++ b/src/common/TopicConfig.cpp
@@ -16,7 +16,6 @@
  */
 #include "TopicConfig.h"
 
-#include <stdlib.h>
 #include <sstream>
 
 #include "PermName.h"
@@ -52,6 +51,7 @@ TopicConfig::~TopicConfig() {}
 
 std::string TopicConfig::encode() {
   std::stringstream ss;
+
   ss << m_topicName << SEPARATOR << m_readQueueNums << SEPARATOR << m_writeQueueNums << SEPARATOR << m_perm << SEPARATOR
      << m_topicFilterType;
 
diff --git a/src/common/UtilAll.cpp b/src/common/UtilAll.cpp
index 74a769c..4333ecd 100644
--- a/src/common/UtilAll.cpp
+++ b/src/common/UtilAll.cpp
@@ -59,7 +59,7 @@ bool UtilAll::try_lock_for(std::timed_mutex& mutex, long timeout) {
 
 int32_t UtilAll::HashCode(const std::string& str) {
   // FIXME: don't equal to String#hashCode in Java
-  int32 h = 0;
+  int32_t h = 0;
   if (!str.empty()) {
     for (const auto& c : str) {
       h = 31 * h + c;
@@ -114,6 +114,10 @@ std::string UtilAll::getRetryTopic(const std::string& consumerGroup) {
   return RETRY_GROUP_TOPIC_PREFIX + consumerGroup;
 }
 
+std::string UtilAll::getReplyTopic(const std::string& clusterName) {
+  return clusterName + "_" + REPLY_TOPIC_POSTFIX;
+}
+
 void UtilAll::Trim(std::string& str) {
   str.erase(0, str.find_first_not_of(' '));  // prefixing spaces
   str.erase(str.find_last_not_of(' ') + 1);  // surfixing spaces
@@ -221,7 +225,7 @@ std::string UtilAll::getLocalAddress() {
     auto hostname = getLocalHostName();
     if (!hostname.empty()) {
       try {
-        s_localIpAddress = lookupNameServers(hostname);
+        s_localIpAddress = socketAddress2String(lookupNameServers(hostname));
       } catch (std::exception& e) {
         LOG_WARN(e.what());
         s_localIpAddress = "127.0.0.1";
diff --git a/src/common/UtilAll.h b/src/common/UtilAll.h
index 63042a9..2e2c34f 100644
--- a/src/common/UtilAll.h
+++ b/src/common/UtilAll.h
@@ -17,6 +17,7 @@
 #ifndef __UTIL_ALL_H__
 #define __UTIL_ALL_H__
 
+#include <exception>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -39,6 +40,8 @@ const std::string CLIENT_INNER_PRODUCER_GROUP = "CLIENT_INNER_PRODUCER";
 const std::string SELF_TEST_TOPIC = "SELF_TEST_TOPIC";
 const std::string RETRY_GROUP_TOPIC_PREFIX = "%RETRY%";
 const std::string DLQ_GROUP_TOPIC_PREFIX = "%DLQ%";
+const std::string REPLY_TOPIC_POSTFIX = "REPLY_TOPIC";
+const std::string REPLY_MESSAGE_FLAG = "reply";
 
 const std::string ROCKETMQ_HOME_PROPERTY = "rocketmq.home.dir";
 const std::string MESSAGE_COMPRESS_LEVEL = "rocketmq.message.compressLevel";
@@ -96,6 +99,7 @@ class UtilAll {
 
   static bool isRetryTopic(const std::string& topic);
   static std::string getRetryTopic(const std::string& consumerGroup);
+  static std::string getReplyTopic(const std::string& clusterName);
 
   static void Trim(std::string& str);
   static bool isBlank(const std::string& str);
diff --git a/src/common/Validators.cpp b/src/common/Validators.cpp
index 1384172..c293aa4 100644
--- a/src/common/Validators.cpp
+++ b/src/common/Validators.cpp
@@ -16,8 +16,7 @@
  */
 #include "Validators.h"
 
-#include <stdio.h>
-#include <stdlib.h>
+#include <regex>
 
 #include "MQProtos.h"
 #include "UtilAll.h"
@@ -36,19 +35,30 @@ bool Validators::regularExpressionMatcher(const std::string& origin, const std::
     return true;
   }
 
-  // Pattern pattern = Pattern.compile(patternStr);
-  // Matcher matcher = pattern.matcher(origin);
-
-  // return matcher.matches();
+#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
   return true;
+#else
+  const std::regex regex(patternStr, std::regex::extended);
+  return std::regex_match(origin, regex);
+#endif
 }
 
 std::string Validators::getGroupWithRegularExpression(const std::string& origin, const std::string& patternStr) {
-  /*Pattern pattern = Pattern.compile(patternStr);
-  Matcher matcher = pattern.matcher(origin);
-  while (matcher.find()) {
-  return matcher.group(0);
-  }*/
+  if (!UtilAll::isBlank(patternStr)) {
+#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)
+    const std::regex regex(patternStr, std::regex::extended);
+    std::smatch match;
+
+    if (std::regex_match(origin, match, regex)) {
+      // The first sub_match is the whole string; the next
+      // sub_match is the first parenthesized expression.
+      if (match.size() == 2) {
+        std::ssub_match base_sub_match = match[1];
+        return base_sub_match.str();
+      }
+    }
+#endif
+  }
   return "";
 }
 
diff --git a/src/concurrent/concurrent_queue.hpp b/src/concurrent/concurrent_queue.hpp
index 1a844e8..5a67e8f 100644
--- a/src/concurrent/concurrent_queue.hpp
+++ b/src/concurrent/concurrent_queue.hpp
@@ -56,9 +56,19 @@ class concurrent_queue {
   typedef T value_type;
   typedef concurrent_queue_node<value_type> node_type;
 
-  ~concurrent_queue() { delete[](char*) sentinel; }
+  ~concurrent_queue() {
+    // clear this queue
+    while (_clear_when_destruct) {
+      if (nullptr == pop_front()) {
+        break;
+      }
+    }
+
+    delete[](char*) sentinel;
+  }
 
-  concurrent_queue() : sentinel((node_type*)new char[sizeof(node_type)]) {
+  concurrent_queue(bool clear_when_destruct = true)
+      : sentinel((node_type*)new char[sizeof(node_type)]), _clear_when_destruct(clear_when_destruct) {
     sentinel->next_ = sentinel;
     head_ = tail_ = sentinel;
   }
@@ -136,6 +146,7 @@ class concurrent_queue {
 
   std::atomic<node_type*> head_, tail_;
   node_type* const sentinel;
+  bool _clear_when_destruct;
 };
 
 }  // namespace rocketmq
diff --git a/src/concurrent/executor.hpp b/src/concurrent/executor.hpp
index 06c62b5..3ed5ad5 100644
--- a/src/concurrent/executor.hpp
+++ b/src/concurrent/executor.hpp
@@ -69,7 +69,7 @@ class executor {
 
 class executor_service : virtual public executor {
  public:
-  virtual void shutdown() = 0;
+  virtual void shutdown(bool immediately) = 0;
   virtual bool is_shutdown() = 0;
   virtual std::future<void> submit(const handler_type& task) = 0;
 };
diff --git a/src/concurrent/executor_impl.hpp b/src/concurrent/executor_impl.hpp
index b4b9472..0c0a0cb 100644
--- a/src/concurrent/executor_impl.hpp
+++ b/src/concurrent/executor_impl.hpp
@@ -61,11 +61,12 @@ class thread_pool_executor : public abstract_executor_service {
     }
   }
 
-  void shutdown() override {
+  void shutdown(bool immediately = true) override {
     if (state_ == RUNNING) {
-      state_ = STOP;
+      state_ = immediately ? STOP : SHUTDOWN;
       wakeup_event_.notify_all();
       thread_group_.join();
+      state_ = STOP;
     }
   }
 
@@ -206,7 +207,7 @@ class scheduled_thread_pool_executor : public thread_pool_executor, virtual publ
     }
   }
 
-  void shutdown() override {
+  void shutdown(bool immediately = true) override {
     if (!stopped_) {
       stopped_ = true;
 
@@ -214,7 +215,7 @@ class scheduled_thread_pool_executor : public thread_pool_executor, virtual publ
       timer_thread_.join();
 
       if (!single_thread_) {
-        thread_pool_executor::shutdown();
+        thread_pool_executor::shutdown(immediately);
       }
     }
   }
diff --git a/src/consumer/AllocateMQAveragely.h b/src/consumer/AllocateMQAveragely.h
index 6fe0ff7..d0acc20 100644
--- a/src/consumer/AllocateMQAveragely.h
+++ b/src/consumer/AllocateMQAveragely.h
@@ -21,18 +21,19 @@
 
 #include "AllocateMQStrategy.h"
 #include "Logging.h"
+#include "MQClientException.h"
 
 namespace rocketmq {
 
 class AllocateMQAveragely : public AllocateMQStrategy {
  public:
-  void allocate(const std::string& currentCID,
+  void allocate(const std::string& currentCid,
                 std::vector<MQMessageQueue>& mqAll,
                 std::vector<std::string>& cidAll,
                 std::vector<MQMessageQueue>& outReuslt) override {
     outReuslt.clear();
 
-    if (currentCID.empty()) {
+    if (currentCid.empty()) {
       THROW_MQEXCEPTION(MQClientException, "currentCID is empty", -1);
     }
 
@@ -47,7 +48,7 @@ class AllocateMQAveragely : public AllocateMQStrategy {
     int index = -1;
     int cidAllSize = cidAll.size();
     for (int i = 0; i < cidAllSize; i++) {
-      if (cidAll[i] == currentCID) {
+      if (cidAll[i] == currentCid) {
         index = i;
         break;
       }
diff --git a/src/consumer/ConsumeMessageConcurrentlyService.cpp b/src/consumer/ConsumeMessageConcurrentlyService.cpp
index 5f7d7e8..26063e5 100755
--- a/src/consumer/ConsumeMessageConcurrentlyService.cpp
+++ b/src/consumer/ConsumeMessageConcurrentlyService.cpp
@@ -35,9 +35,11 @@ ConsumeMessageConcurrentlyService::~ConsumeMessageConcurrentlyService() = defaul
 void ConsumeMessageConcurrentlyService::start() {
   // start callback threadpool
   m_consumeExecutor.startup();
+  m_scheduledExecutorService.startup();
 }
 
 void ConsumeMessageConcurrentlyService::shutdown() {
+  m_scheduledExecutorService.shutdown();
   m_consumeExecutor.shutdown();
 }
 
@@ -86,64 +88,69 @@ void ConsumeMessageConcurrentlyService::ConsumeRequest(std::vector<MQMessageExtP
       }
     }
     status = m_messageListener->consumeMessage(msgs);
-  } catch (std::exception& e) {
-    // ...
+  } catch (const std::exception& e) {
+    LOG_WARN_NEW("encounter unexpected exception when consume messages.\n{}", e.what());
   }
 
+  if (processQueue->isDropped()) {
+    LOG_WARN_NEW("processQueue is dropped without process consume result. messageQueue={}", messageQueue.toString());
+    return;
+  }
+
+  //
   // processConsumeResult
-  if (!processQueue->isDropped()) {
-    int ackIndex = -1;
-    switch (status) {
-      case CONSUME_SUCCESS:
-        ackIndex = msgs.size() - 1;
-        break;
-      case RECONSUME_LATER:
-        ackIndex = -1;
-        break;
-      default:
-        break;
-    }
 
-    switch (m_consumer->messageModel()) {
-      case BROADCASTING:
-        // Note: broadcasting reconsume should do by application, as it has big affect to broker cluster
-        for (size_t i = ackIndex + 1; i < msgs.size(); i++) {
-          const auto& msg = msgs[i];
-          LOG_WARN_NEW("BROADCASTING, the message consume failed, drop it, {}", msg->toString());
-        }
-        break;
-      case CLUSTERING: {
-        // send back msg to broker
-        std::vector<MQMessageExtPtr2> msgBackFailed;
-        int idx = ackIndex + 1;
-        for (auto iter = msgs.begin() + idx; iter != msgs.end(); idx++) {
-          LOG_WARN_NEW("consume fail, MQ is:{}, its msgId is:{}, index is:{}, reconsume times is:{}",
-                       messageQueue.toString(), (*iter)->getMsgId(), idx, (*iter)->getReconsumeTimes());
-          auto& msg = (*iter);
-          bool result = m_consumer->sendMessageBack(*msg, 0, messageQueue.getBrokerName());
-          if (!result) {
-            msg->setReconsumeTimes(msg->getReconsumeTimes() + 1);
-            msgBackFailed.push_back(msg);
-            iter = msgs.erase(iter);
-          } else {
-            iter++;
-          }
-        }
+  int ackIndex = -1;
+  switch (status) {
+    case CONSUME_SUCCESS:
+      ackIndex = msgs.size() - 1;
+      break;
+    case RECONSUME_LATER:
+      ackIndex = -1;
+      break;
+    default:
+      break;
+  }
 
-        if (!msgBackFailed.empty()) {
-          // send back failed, reconsume later
-          submitConsumeRequestLater(msgBackFailed, processQueue, messageQueue);
+  switch (m_consumer->messageModel()) {
+    case BROADCASTING:
+      // Note: broadcasting reconsume should do by application, as it has big affect to broker cluster
+      for (size_t i = ackIndex + 1; i < msgs.size(); i++) {
+        const auto& msg = msgs[i];
+        LOG_WARN_NEW("BROADCASTING, the message consume failed, drop it, {}", msg->toString());
+      }
+      break;
+    case CLUSTERING: {
+      // send back msg to broker
+      std::vector<MQMessageExtPtr2> msgBackFailed;
+      int idx = ackIndex + 1;
+      for (auto iter = msgs.begin() + idx; iter != msgs.end(); idx++) {
+        LOG_WARN_NEW("consume fail, MQ is:{}, its msgId is:{}, index is:{}, reconsume times is:{}",
+                     messageQueue.toString(), (*iter)->getMsgId(), idx, (*iter)->getReconsumeTimes());
+        auto& msg = (*iter);
+        bool result = m_consumer->sendMessageBack(*msg, 0, messageQueue.getBrokerName());
+        if (!result) {
+          msg->setReconsumeTimes(msg->getReconsumeTimes() + 1);
+          msgBackFailed.push_back(msg);
+          iter = msgs.erase(iter);
+        } else {
+          iter++;
         }
-      } break;
-      default:
-        break;
-    }
+      }
 
-    // update offset
-    int64_t offset = processQueue->removeMessage(msgs);
-    if (offset >= 0 && !processQueue->isDropped()) {
-      m_consumer->getOffsetStore()->updateOffset(messageQueue, offset, true);
-    }
+      if (!msgBackFailed.empty()) {
+        // send back failed, reconsume later
+        submitConsumeRequestLater(msgBackFailed, processQueue, messageQueue);
+      }
+    } break;
+    default:
+      break;
+  }
+
+  // update offset
+  int64_t offset = processQueue->removeMessage(msgs);
+  if (offset >= 0 && !processQueue->isDropped()) {
+    m_consumer->getOffsetStore()->updateOffset(messageQueue, offset, true);
   }
 }
 
diff --git a/src/consumer/ConsumeMessageOrderlyService.cpp b/src/consumer/ConsumeMessageOrderlyService.cpp
index 449281b..9411666 100755
--- a/src/consumer/ConsumeMessageOrderlyService.cpp
+++ b/src/consumer/ConsumeMessageOrderlyService.cpp
@@ -159,8 +159,8 @@ void ConsumeMessageOrderlyService::ConsumeRequest(ProcessQueuePtr processQueue,
           }
 
           status = m_messageListener->consumeMessage(msgs);
-        } catch (std::exception& e) {
-          // ...
+        } catch (const std::exception& e) {
+          LOG_WARN_NEW("encounter unexpected exception when consume messages.\n{}", e.what());
         }
 
         // processConsumeResult
diff --git a/src/consumer/DefaultMQPullConsumer.cpp b/src/consumer/DefaultMQPullConsumer.cpp
index 295e73d..4512a38 100644
--- a/src/consumer/DefaultMQPullConsumer.cpp
+++ b/src/consumer/DefaultMQPullConsumer.cpp
@@ -16,17 +16,15 @@
  */
 #include "DefaultMQPullConsumer.h"
 
-#include "AllocateMQAveragely.h"
 #include "UtilAll.h"
 
 namespace rocketmq {
 
-DefaultMQPullConsumerConfig::DefaultMQPullConsumerConfig() : m_allocateMQStrategy(new AllocateMQAveragely()) {}
-
 DefaultMQPullConsumer::DefaultMQPullConsumer(const std::string& groupname)
     : DefaultMQPullConsumer(groupname, nullptr) {}
 
-DefaultMQPullConsumer::DefaultMQPullConsumer(const std::string& groupname, std::shared_ptr<RPCHook> rpcHook) {
+DefaultMQPullConsumer::DefaultMQPullConsumer(const std::string& groupname, RPCHookPtr rpcHook)
+    : DefaultMQPullConsumerConfigProxy(nullptr), m_pullConsumerDelegate(nullptr) {
   // set default group name
   if (groupname.empty()) {
     setGroupName(DEFAULT_CONSUMER_GROUP);
@@ -105,7 +103,7 @@ void DefaultMQPullConsumer::fetchMessageQueuesInBalance(const std::string& topic
   m_pullConsumerDelegate->fetchMessageQueuesInBalance(topic, mqs);
 }
 
-void DefaultMQPullConsumer::setRPCHook(std::shared_ptr<RPCHook> rpcHook) {
+void DefaultMQPullConsumer::setRPCHook(RPCHookPtr rpcHook) {
   // dynamic_cast<DefaultMQPullConsumerImpl*>(m_pullConsumerDelegate.get())->setRPCHook(rpcHook);
 }
 
diff --git a/src/consumer/DefaultMQPullConsumerImpl.cpp b/src/consumer/DefaultMQPullConsumerImpl.cpp
index c9eea38..e72defd 100644
--- a/src/consumer/DefaultMQPullConsumerImpl.cpp
+++ b/src/consumer/DefaultMQPullConsumerImpl.cpp
@@ -39,7 +39,7 @@
 
 // DefaultMQPullConsumer::DefaultMQPullConsumer(const string& groupname) : DefaultMQPullConsumer(groupname, nullptr) {}
 
-// DefaultMQPullConsumer::DefaultMQPullConsumer(const string& groupname, std::shared_ptr<RPCHook> rpcHook)
+// DefaultMQPullConsumer::DefaultMQPullConsumer(const string& groupname, RPCHookPtr rpcHook)
 //     : MQClient(rpcHook),
 //       m_rebalanceImpl(new RebalancePullImpl(this)),
 //       m_pullAPIWrapper(nullptr),
@@ -318,7 +318,8 @@
 //   }
 // }
 
-// void DefaultMQPullConsumer::fetchMessageQueuesInBalance(const std::string& topic, std::vector<MQMessageQueue>& mqs) {}
+// void DefaultMQPullConsumer::fetchMessageQueuesInBalance(const std::string& topic, std::vector<MQMessageQueue>& mqs)
+// {}
 
 // void DefaultMQPullConsumer::checkConfig() {
 //   string groupname = getGroupName();
diff --git a/src/consumer/DefaultMQPushConsumer.cpp b/src/consumer/DefaultMQPushConsumer.cpp
index 4116b41..0d717fd 100644
--- a/src/consumer/DefaultMQPushConsumer.cpp
+++ b/src/consumer/DefaultMQPushConsumer.cpp
@@ -16,27 +16,18 @@
  */
 #include "DefaultMQPushConsumer.h"
 
-#include "AllocateMQAveragely.h"
+#include "DefaultMQPushConsumerConfigImpl.h"
 #include "DefaultMQPushConsumerImpl.h"
 #include "UtilAll.h"
 
 namespace rocketmq {
 
-DefaultMQPushConsumerConfig::DefaultMQPushConsumerConfig()
-    : m_consumeFromWhere(CONSUME_FROM_LAST_OFFSET),
-      m_consumeTimestamp("0"),
-      m_consumeThreadNum(std::min(8, (int)std::thread::hardware_concurrency())),
-      m_consumeMessageBatchMaxSize(1),
-      m_maxMsgCacheSize(1000),
-      m_asyncPullTimeout(30 * 1000),
-      m_maxReconsumeTimes(-1),
-      m_allocateMQStrategy(new AllocateMQAveragely()) {}
-
 DefaultMQPushConsumer::DefaultMQPushConsumer(const std::string& groupname)
     : DefaultMQPushConsumer(groupname, nullptr) {}
 
-DefaultMQPushConsumer::DefaultMQPushConsumer(const std::string& groupname, std::shared_ptr<RPCHook> rpcHook)
-    : m_pushConsumerDelegate(nullptr) {
+DefaultMQPushConsumer::DefaultMQPushConsumer(const std::string& groupname, RPCHookPtr rpcHook)
+    : DefaultMQPushConsumerConfigProxy(std::make_shared<DefaultMQPushConsumerConfigImpl>()),
+      m_pushConsumerDelegate(nullptr) {
   // set default group name
   if (groupname.empty()) {
     setGroupName(DEFAULT_CONSUMER_GROUP);
@@ -44,7 +35,7 @@ DefaultMQPushConsumer::DefaultMQPushConsumer(const std::string& groupname, std::
     setGroupName(groupname);
   }
 
-  m_pushConsumerDelegate = DefaultMQPushConsumerImpl::create(this, rpcHook);
+  m_pushConsumerDelegate = DefaultMQPushConsumerImpl::create(getRealConfig(), rpcHook);
 }
 
 DefaultMQPushConsumer::~DefaultMQPushConsumer() = default;
@@ -81,6 +72,10 @@ void DefaultMQPushConsumer::registerMessageListener(MessageListenerOrderly* mess
   m_pushConsumerDelegate->registerMessageListener(messageListener);
 }
 
+MQMessageListener* DefaultMQPushConsumer::getMessageListener() const {
+  return m_pushConsumerDelegate->getMessageListener();
+}
+
 void DefaultMQPushConsumer::subscribe(const std::string& topic, const std::string& subExpression) {
   m_pushConsumerDelegate->subscribe(topic, subExpression);
 }
@@ -93,8 +88,8 @@ void DefaultMQPushConsumer::resume() {
   m_pushConsumerDelegate->resume();
 }
 
-void DefaultMQPushConsumer::setRPCHook(std::shared_ptr<RPCHook> rpcHook) {
-  dynamic_cast<DefaultMQPushConsumerImpl*>(m_pushConsumerDelegate.get())->setRPCHook(rpcHook);
+void DefaultMQPushConsumer::setRPCHook(RPCHookPtr rpcHook) {
+  std::dynamic_pointer_cast<DefaultMQPushConsumerImpl>(m_pushConsumerDelegate)->setRPCHook(rpcHook);
 }
 
 }  // namespace rocketmq
diff --git a/src/consumer/DefaultMQPushConsumerConfigImpl.cpp b/src/consumer/DefaultMQPushConsumerConfigImpl.cpp
new file mode 100644
index 0000000..560a6be
--- /dev/null
+++ b/src/consumer/DefaultMQPushConsumerConfigImpl.cpp
@@ -0,0 +1,125 @@
+
+/*
+ * 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.
+ */
+#include "DefaultMQPushConsumerConfigImpl.h"
+
+#include <algorithm>
+#include <thread>
+
+#include "AllocateMQAveragely.h"
+
+namespace rocketmq {
+
+DefaultMQPushConsumerConfigImpl::DefaultMQPushConsumerConfigImpl()
+    : m_messageModel(CLUSTERING),
+      m_consumeFromWhere(CONSUME_FROM_LAST_OFFSET),
+      m_consumeTimestamp("0"),
+      m_consumeThreadNum(std::min(8, (int)std::thread::hardware_concurrency())),
+      m_consumeMessageBatchMaxSize(1),
+      m_maxMsgCacheSize(1000),
+      m_asyncPullTimeout(30 * 1000),
+      m_maxReconsumeTimes(-1),
+      m_pullTimeDelayMillsWhenException(3000),
+      m_allocateMQStrategy(new AllocateMQAveragely()) {}
+
+MessageModel DefaultMQPushConsumerConfigImpl::getMessageModel() const {
+  return m_messageModel;
+}
+
+void DefaultMQPushConsumerConfigImpl::setMessageModel(MessageModel messageModel) {
+  m_messageModel = messageModel;
+}
+
+ConsumeFromWhere DefaultMQPushConsumerConfigImpl::getConsumeFromWhere() const {
+  return m_consumeFromWhere;
+}
+
+void DefaultMQPushConsumerConfigImpl::setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) {
+  m_consumeFromWhere = consumeFromWhere;
+}
+
+std::string DefaultMQPushConsumerConfigImpl::getConsumeTimestamp() {
+  return m_consumeTimestamp;
+}
+
+void DefaultMQPushConsumerConfigImpl::setConsumeTimestamp(std::string consumeTimestamp) {
+  m_consumeTimestamp = consumeTimestamp;
+}
+
+int DefaultMQPushConsumerConfigImpl::getConsumeThreadNum() const {
+  return m_consumeThreadNum;
+}
+
+void DefaultMQPushConsumerConfigImpl::setConsumeThreadNum(int threadNum) {
+  if (threadNum > 0) {
+    m_consumeThreadNum = threadNum;
+  }
+}
+
+int DefaultMQPushConsumerConfigImpl::getConsumeMessageBatchMaxSize() const {
+  return m_consumeMessageBatchMaxSize;
+}
+
+void DefaultMQPushConsumerConfigImpl::setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) {
+  if (consumeMessageBatchMaxSize >= 1) {
+    m_consumeMessageBatchMaxSize = consumeMessageBatchMaxSize;
+  }
+}
+
+int DefaultMQPushConsumerConfigImpl::getMaxCacheMsgSizePerQueue() const {
+  return m_maxMsgCacheSize;
+}
+
+void DefaultMQPushConsumerConfigImpl::setMaxCacheMsgSizePerQueue(int maxCacheSize) {
+  if (maxCacheSize > 0 && maxCacheSize < 65535) {
+    m_maxMsgCacheSize = maxCacheSize;
+  }
+}
+
+int DefaultMQPushConsumerConfigImpl::getAsyncPullTimeout() const {
+  return m_asyncPullTimeout;
+}
+
+void DefaultMQPushConsumerConfigImpl::setAsyncPullTimeout(int asyncPullTimeout) {
+  m_asyncPullTimeout = asyncPullTimeout;
+}
+
+int DefaultMQPushConsumerConfigImpl::getMaxReconsumeTimes() const {
+  return m_maxReconsumeTimes;
+}
+
+void DefaultMQPushConsumerConfigImpl::setMaxReconsumeTimes(int maxReconsumeTimes) {
+  m_maxReconsumeTimes = maxReconsumeTimes;
+}
+
+long DefaultMQPushConsumerConfigImpl::getPullTimeDelayMillsWhenException() const {
+  return m_pullTimeDelayMillsWhenException;
+}
+
+void DefaultMQPushConsumerConfigImpl::setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) {
+  m_pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
+}
+
+AllocateMQStrategy* DefaultMQPushConsumerConfigImpl::getAllocateMQStrategy() const {
+  return m_allocateMQStrategy.get();
+}
+
+void DefaultMQPushConsumerConfigImpl::setAllocateMQStrategy(AllocateMQStrategy* strategy) {
+  m_allocateMQStrategy.reset(strategy);
+}
+
+}  // namespace rocketmq
diff --git a/src/consumer/DefaultMQPushConsumerConfigImpl.h b/src/consumer/DefaultMQPushConsumerConfigImpl.h
new file mode 100644
index 0000000..1ca6013
--- /dev/null
+++ b/src/consumer/DefaultMQPushConsumerConfigImpl.h
@@ -0,0 +1,81 @@
+
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_IMPL_H__
+#define __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_IMPL_H__
+
+#include "DefaultMQPushConsumerConfig.h"
+#include "MQClientConfigImpl.h"
+
+namespace rocketmq {
+
+class DefaultMQPushConsumerConfigImpl : virtual public DefaultMQPushConsumerConfig, public MQClientConfigImpl {
+ public:
+  DefaultMQPushConsumerConfigImpl();
+  virtual ~DefaultMQPushConsumerConfigImpl() = default;
+
+  MessageModel getMessageModel() const override;
+  void setMessageModel(MessageModel messageModel) override;
+
+  ConsumeFromWhere getConsumeFromWhere() const override;
+  void setConsumeFromWhere(ConsumeFromWhere consumeFromWhere) override;
+
+  std::string getConsumeTimestamp() override;
+  void setConsumeTimestamp(std::string consumeTimestamp) override;
+
+  int getConsumeThreadNum() const override;
+  void setConsumeThreadNum(int threadNum) override;
+
+  int getConsumeMessageBatchMaxSize() const override;
+  void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) override;
+
+  int getMaxCacheMsgSizePerQueue() const override;
+  void setMaxCacheMsgSizePerQueue(int maxCacheSize) override;
+
+  int getAsyncPullTimeout() const override;
+  void setAsyncPullTimeout(int asyncPullTimeout) override;
+
+  int getMaxReconsumeTimes() const override;
+  void setMaxReconsumeTimes(int maxReconsumeTimes) override;
+
+  long getPullTimeDelayMillsWhenException() const override;
+  void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) override;
+
+  AllocateMQStrategy* getAllocateMQStrategy() const override;
+  void setAllocateMQStrategy(AllocateMQStrategy* strategy) override;
+
+ protected:
+  MessageModel m_messageModel;
+
+  ConsumeFromWhere m_consumeFromWhere;
+  std::string m_consumeTimestamp;
+
+  int m_consumeThreadNum;
+  int m_consumeMessageBatchMaxSize;
+  int m_maxMsgCacheSize;
+
+  int m_asyncPullTimeout;  // 30s
+  int m_maxReconsumeTimes;
+
+  long m_pullTimeDelayMillsWhenException;  // 3000
+
+  std::unique_ptr<AllocateMQStrategy> m_allocateMQStrategy;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PUSH_CONSUMER_CONFIG_IMPL_H__
\ No newline at end of file
diff --git a/src/consumer/DefaultMQPushConsumerImpl.cpp b/src/consumer/DefaultMQPushConsumerImpl.cpp
index 80e214f..40630f3 100644
--- a/src/consumer/DefaultMQPushConsumerImpl.cpp
+++ b/src/consumer/DefaultMQPushConsumerImpl.cpp
@@ -20,7 +20,6 @@
 #include <signal.h>
 #endif
 
-#include "AllocateMQAveragely.h"
 #include "CommunicationMode.h"
 #include "ConsumeMsgService.h"
 #include "ConsumerRunningInfo.h"
@@ -33,7 +32,7 @@
 #include "MQProtos.h"
 #include "OffsetStore.h"
 #include "PullAPIWrapper.h"
-#include "PullMessageService.h"
+#include "PullMessageService.hpp"
 #include "PullSysFlag.h"
 #include "RebalancePushImpl.h"
 #include "SocketUtil.h"
@@ -95,6 +94,13 @@ class AsyncPullCallback : public AutoDeletePullCallback {
         defaultMQPushConsumer->correctTagsOffset(m_pullRequest);
         defaultMQPushConsumer->executePullRequestImmediately(m_pullRequest);
         break;
+      case NO_LATEST_MSG:
+        m_pullRequest->setNextOffset(result.nextBeginOffset);
+        defaultMQPushConsumer->correctTagsOffset(m_pullRequest);
+        defaultMQPushConsumer->executePullRequestLater(
+            m_pullRequest,
+            defaultMQPushConsumer->getDefaultMQPushConsumerConfig()->getPullTimeDelayMillsWhenException());
+        break;
       case OFFSET_ILLEGAL: {
         LOG_WARN_NEW("the pull request offset illegal, {} {}", m_pullRequest->toString(), result.toString());
 
@@ -134,7 +140,9 @@ class AsyncPullCallback : public AutoDeletePullCallback {
       LOG_WARN_NEW("execute the pull request exception: {}", e.what());
     }
 
-    defaultMQPushConsumer->executePullRequestLater(m_pullRequest, 3000);
+    // TODO
+    defaultMQPushConsumer->executePullRequestLater(
+        m_pullRequest, defaultMQPushConsumer->getDefaultMQPushConsumerConfig()->getPullTimeDelayMillsWhenException());
   }
 
  private:
@@ -143,11 +151,10 @@ class AsyncPullCallback : public AutoDeletePullCallback {
   SubscriptionDataPtr m_subscriptionData;
 };
 
-DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfig* config)
+DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config)
     : DefaultMQPushConsumerImpl(config, nullptr) {}
 
-DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfig* config,
-                                                     std::shared_ptr<RPCHook> rpcHook)
+DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config, RPCHookPtr rpcHook)
     : MQClientImpl(config, rpcHook),
       m_pushConsumerConfig(config),
       m_startTime(UtilAll::currentTimeMillis()),
@@ -176,13 +183,13 @@ bool DefaultMQPushConsumerImpl::sendMessageBack(MQMessageExt& msg, int delayLeve
 
 bool DefaultMQPushConsumerImpl::sendMessageBack(MQMessageExt& msg, int delayLevel, const std::string& brokerName) {
   try {
-    std::string brokerAddr = brokerName.empty() ? socketAddress2IPPort(&msg.getStoreHost())
+    std::string brokerAddr = brokerName.empty() ? socketAddress2String(msg.getStoreHost())
                                                 : m_clientInstance->findBrokerAddressInPublish(brokerName);
 
     m_clientInstance->getMQClientAPIImpl()->consumerSendMessageBack(
         brokerAddr, msg, m_pushConsumerConfig->getGroupName(), delayLevel, 5000, getMaxReconsumeTimes());
     return true;
-  } catch (std::exception& e) {
+  } catch (const std::exception& e) {
     LOG_ERROR_NEW("sendMessageBack exception, group: {}, msg: {}. {}", m_pushConsumerConfig->getGroupName(),
                   msg.toString(), e.what());
   }
@@ -243,14 +250,14 @@ void DefaultMQPushConsumerImpl::start() {
         m_pushConsumerConfig->changeInstanceNameToPID();
       }
 
-      // ensure m_clientFactory
+      // ensure m_clientInstance
       MQClientImpl::start();
 
       // reset rebalance
       m_rebalanceImpl->setConsumerGroup(m_pushConsumerConfig->getGroupName());
       m_rebalanceImpl->setMessageModel(m_pushConsumerConfig->getMessageModel());
       m_rebalanceImpl->setAllocateMQStrategy(m_pushConsumerConfig->getAllocateMQStrategy());
-      m_rebalanceImpl->setMQClientFactory(m_clientInstance.get());
+      m_rebalanceImpl->setClientInstance(m_clientInstance.get());
 
       m_pullAPIWrapper.reset(new PullAPIWrapper(m_clientInstance.get(), m_pushConsumerConfig->getGroupName()));
 
@@ -337,11 +344,15 @@ void DefaultMQPushConsumerImpl::registerMessageListener(MQMessageListener* messa
 }
 
 void DefaultMQPushConsumerImpl::registerMessageListener(MessageListenerConcurrently* messageListener) {
-  registerMessageListener((MQMessageListener*)messageListener);
+  registerMessageListener(static_cast<MQMessageListener*>(messageListener));
 }
 
 void DefaultMQPushConsumerImpl::registerMessageListener(MessageListenerOrderly* messageListener) {
-  registerMessageListener((MQMessageListener*)messageListener);
+  registerMessageListener(static_cast<MQMessageListener*>(messageListener));
+}
+
+MQMessageListener* DefaultMQPushConsumerImpl::getMessageListener() const {
+  return m_messageListener;
 }
 
 void DefaultMQPushConsumerImpl::subscribe(const std::string& topic, const std::string& subExpression) {
@@ -515,7 +526,7 @@ void DefaultMQPushConsumerImpl::pullMessage(PullRequestPtr pullRequest) {
         pullRequest->setNextOffset(offset);
       }
     } else {
-      executePullRequestLater(pullRequest, 3000);
+      executePullRequestLater(pullRequest, m_pushConsumerConfig->getPullTimeDelayMillsWhenException());
       LOG_INFO_NEW("pull message later because not locked in broker, {}", pullRequest->toString());
       return;
     }
@@ -524,7 +535,7 @@ void DefaultMQPushConsumerImpl::pullMessage(PullRequestPtr pullRequest) {
   const auto& messageQueue = pullRequest->getMessageQueue();
   SubscriptionDataPtr subscriptionData = m_rebalanceImpl->getSubscriptionData(messageQueue.getTopic());
   if (nullptr == subscriptionData) {
-    executePullRequestLater(pullRequest, 3000);
+    executePullRequestLater(pullRequest, m_pushConsumerConfig->getPullTimeDelayMillsWhenException());
     LOG_WARN_NEW("find the consumer's subscription failed, {}", pullRequest->toString());
     return;
   }
@@ -560,7 +571,7 @@ void DefaultMQPushConsumerImpl::pullMessage(PullRequestPtr pullRequest) {
                                      callback);                                    // 11
   } catch (MQException& e) {
     LOG_ERROR_NEW("pullKernelImpl exception: {}", e.what());
-    executePullRequestLater(pullRequest, 3000);
+    executePullRequestLater(pullRequest, m_pushConsumerConfig->getPullTimeDelayMillsWhenException());
   }
 }
 
diff --git a/src/consumer/DefaultMQPushConsumerImpl.h b/src/consumer/DefaultMQPushConsumerImpl.h
index bd3a590..67f03ef 100755
--- a/src/consumer/DefaultMQPushConsumerImpl.h
+++ b/src/consumer/DefaultMQPushConsumerImpl.h
@@ -44,7 +44,7 @@ class DefaultMQPushConsumerImpl : public std::enable_shared_from_this<DefaultMQP
                                   public MQClientImpl,
                                   public MQConsumerInner {
  public:
-  static DefaultMQPushConsumerImplPtr create(DefaultMQPushConsumerConfig* config, RPCHookPtr rpcHook = nullptr) {
+  static DefaultMQPushConsumerImplPtr create(DefaultMQPushConsumerConfigPtr config, RPCHookPtr rpcHook = nullptr) {
     if (nullptr == rpcHook) {
       return DefaultMQPushConsumerImplPtr(new DefaultMQPushConsumerImpl(config));
     } else {
@@ -53,8 +53,8 @@ class DefaultMQPushConsumerImpl : public std::enable_shared_from_this<DefaultMQP
   }
 
  private:
-  DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfig* config);
-  DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfig* config, RPCHookPtr rpcHook);
+  DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config);
+  DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config, RPCHookPtr rpcHook);
 
  public:
   virtual ~DefaultMQPushConsumerImpl();
@@ -73,6 +73,8 @@ class DefaultMQPushConsumerImpl : public std::enable_shared_from_this<DefaultMQP
   void registerMessageListener(MessageListenerConcurrently* messageListener) override;
   void registerMessageListener(MessageListenerOrderly* messageListener) override;
 
+  MQMessageListener* getMessageListener() const override;
+
   void subscribe(const std::string& topic, const std::string& subExpression) override;
 
   void suspend() override;
@@ -123,7 +125,7 @@ class DefaultMQPushConsumerImpl : public std::enable_shared_from_this<DefaultMQP
     return messageListenerDefaultly;
   }
 
-  DefaultMQPushConsumerConfig* getDefaultMQPushConsumerConfig() { return m_pushConsumerConfig; }
+  DefaultMQPushConsumerConfig* getDefaultMQPushConsumerConfig() { return m_pushConsumerConfig.get(); }
 
  private:
   void checkConfig();
@@ -133,7 +135,7 @@ class DefaultMQPushConsumerImpl : public std::enable_shared_from_this<DefaultMQP
   int getMaxReconsumeTimes();
 
  private:
-  DefaultMQPushConsumerConfig* m_pushConsumerConfig;
+  DefaultMQPushConsumerConfigPtr m_pushConsumerConfig;
 
   uint64_t m_startTime;
 
diff --git a/src/consumer/MessageQueueLock.hpp b/src/consumer/MessageQueueLock.hpp
index 3579c28..e43fab7 100644
--- a/src/consumer/MessageQueueLock.hpp
+++ b/src/consumer/MessageQueueLock.hpp
@@ -32,10 +32,12 @@ class MessageQueueLock {
  public:
   std::shared_ptr<std::mutex> fetchLockObject(const MQMessageQueue& mq) {
     std::lock_guard<std::mutex> lock(m_mqLockTableMutex);
-    if (m_mqLockTable.find(mq) == m_mqLockTable.end()) {
-      m_mqLockTable.emplace(mq, std::shared_ptr<std::mutex>(new std::mutex()));
+    const auto& it = m_mqLockTable.find(mq);
+    if (it != m_mqLockTable.end()) {
+      return it->second;
+    } else {
+      return m_mqLockTable[mq] = std::make_shared<std::mutex>();
     }
-    return m_mqLockTable[mq];
   }
 
  private:
diff --git a/src/consumer/OffsetStore.cpp b/src/consumer/OffsetStore.cpp
index d68cf2c..55305cf 100644
--- a/src/consumer/OffsetStore.cpp
+++ b/src/consumer/OffsetStore.cpp
@@ -83,7 +83,7 @@ int64_t LocalFileOffsetStore::readOffset(const MQMessageQueue& mq, ReadOffsetTyp
     case MEMORY_FIRST_THEN_STORE:
     case READ_FROM_MEMORY: {
       std::lock_guard<std::mutex> lock(m_lock);
-      auto it = m_offsetTable.find(mq);
+      const auto& it = m_offsetTable.find(mq);
       if (it != m_offsetTable.end()) {
         return it->second;
       } else if (READ_FROM_MEMORY == type) {
@@ -93,7 +93,7 @@ int64_t LocalFileOffsetStore::readOffset(const MQMessageQueue& mq, ReadOffsetTyp
     case READ_FROM_STORE: {
       auto offsetTable = readLocalOffset();
       if (!offsetTable.empty()) {
-        auto it = offsetTable.find(mq);
+        const auto& it = offsetTable.find(mq);
         if (it != offsetTable.end()) {
           auto offset = it->second;
           updateOffset(mq, offset, false);
@@ -124,7 +124,7 @@ void LocalFileOffsetStore::persistAll(const std::vector<MQMessageQueue>& mqs) {
   Json::Value root(Json::objectValue);
   Json::Value jOffsetTable(Json::objectValue);
   for (const auto& mq : mqs) {
-    auto it = offsetTable.find(mq);
+    const auto& it = offsetTable.find(mq);
     if (it != offsetTable.end()) {
       std::string strMQ = RemotingSerializable::toJson(toJson(mq));
       jOffsetTable[strMQ] = Json::Value((Json::Int64)it->second);
@@ -184,7 +184,7 @@ std::map<MQMessageQueue, int64_t> LocalFileOffsetStore::readLocalOffsetBak() {
           auto& offset = jOffsetTable[strMQ];
           Json::Value jMQ = RemotingSerializable::fromJson(strMQ);
           MQMessageQueue mq(jMQ["topic"].asString(), jMQ["brokerName"].asString(), jMQ["queueId"].asInt());
-          offsetTable.emplace(mq, offset.asInt64());
+          offsetTable.emplace(std::move(mq), offset.asInt64());
         }
       } catch (const std::exception& e) {
         LOG_WARN_NEW("readLocalOffset Exception {}", e.what());
@@ -211,12 +211,8 @@ void RemoteBrokerOffsetStore::load() {}
 
 void RemoteBrokerOffsetStore::updateOffset(const MQMessageQueue& mq, int64_t offset, bool increaseOnly) {
   std::lock_guard<std::mutex> lock(m_lock);
-  auto it = m_offsetTable.find(mq);
-  if (it != m_offsetTable.end()) {
-    if (!increaseOnly || offset > it->second) {
-      it->second = offset;
-    }
-  } else {
+  const auto& it = m_offsetTable.find(mq);
+  if (it == m_offsetTable.end() || !increaseOnly || offset > it->second) {
     m_offsetTable[mq] = offset;
   }
 }
@@ -227,7 +223,7 @@ int64_t RemoteBrokerOffsetStore::readOffset(const MQMessageQueue& mq, ReadOffset
     case READ_FROM_MEMORY: {
       std::lock_guard<std::mutex> lock(m_lock);
 
-      auto it = m_offsetTable.find(mq);
+      const auto& it = m_offsetTable.find(mq);
       if (it != m_offsetTable.end()) {
         return it->second;
       } else if (READ_FROM_MEMORY == type) {
@@ -261,7 +257,7 @@ void RemoteBrokerOffsetStore::persist(const MQMessageQueue& mq) {
     offsetTable = m_offsetTable;
   }
 
-  auto it = offsetTable.find(mq);
+  const auto& it = offsetTable.find(mq);
   if (it != offsetTable.end()) {
     try {
       updateConsumeOffsetToBroker(mq, it->second);
@@ -275,8 +271,9 @@ void RemoteBrokerOffsetStore::persistAll(const std::vector<MQMessageQueue>& mq)
 
 void RemoteBrokerOffsetStore::removeOffset(const MQMessageQueue& mq) {
   std::lock_guard<std::mutex> lock(m_lock);
-  if (m_offsetTable.find(mq) != m_offsetTable.end()) {
-    m_offsetTable.erase(mq);
+  const auto& it = m_offsetTable.find(mq);
+  if (it != m_offsetTable.end()) {
+    m_offsetTable.erase(it);
   }
 }
 
diff --git a/src/consumer/ProcessQueue.cpp b/src/consumer/ProcessQueue.cpp
index 79425d1..5355448 100644
--- a/src/consumer/ProcessQueue.cpp
+++ b/src/consumer/ProcessQueue.cpp
@@ -58,7 +58,7 @@ void ProcessQueue::putMessage(std::vector<MQMessageExtPtr2>& msgs) {
     }
   }
 
-  LOG_DEBUG("ProcessQueue: putMessage m_queueOffsetMax:%lld ", m_queueOffsetMax);
+  LOG_DEBUG_NEW("ProcessQueue: putMessage m_queueOffsetMax:{}", m_queueOffsetMax);
 }
 
 int64_t ProcessQueue::removeMessage(std::vector<MQMessageExtPtr2>& msgs) {
@@ -70,11 +70,10 @@ int64_t ProcessQueue::removeMessage(std::vector<MQMessageExtPtr2>& msgs) {
 
   if (!m_msgTreeMap.empty()) {
     result = m_queueOffsetMax + 1;
-    LOG_DEBUG("offset result is:%lld, m_queueOffsetMax is:%lld, msgs size:" SIZET_FMT "", result, m_queueOffsetMax,
-              msgs.size());
+    LOG_DEBUG_NEW("offset result is:{}, m_queueOffsetMax is:{}, msgs size:{}", result, m_queueOffsetMax, msgs.size());
 
     for (auto& msg : msgs) {
-      LOG_DEBUG("remove these msg from m_msgTreeMap, its offset:%lld", msg->getQueueOffset());
+      LOG_DEBUG_NEW("remove these msg from m_msgTreeMap, its offset:{}", msg->getQueueOffset());
       m_msgTreeMap.erase(msg->getQueueOffset());
     }
 
@@ -156,7 +155,7 @@ void ProcessQueue::clearAllMsgs() {
   std::lock_guard<std::mutex> lock(m_lockTreeMap);
 
   if (isDropped()) {
-    LOG_DEBUG("clear m_msgTreeMap as PullRequest had been dropped.");
+    LOG_DEBUG_NEW("clear m_msgTreeMap as PullRequest had been dropped.");
     m_msgTreeMap.clear();
     m_consumingMsgOrderlyTreeMap.clear();
     m_queueOffsetMax = 0;
diff --git a/src/consumer/PullAPIWrapper.cpp b/src/consumer/PullAPIWrapper.cpp
index cd1b49d..7af5f8e 100644
--- a/src/consumer/PullAPIWrapper.cpp
+++ b/src/consumer/PullAPIWrapper.cpp
@@ -42,8 +42,9 @@ void PullAPIWrapper::updatePullFromWhichNode(const MQMessageQueue& mq, int broke
 
 int PullAPIWrapper::recalculatePullFromWhichNode(const MQMessageQueue& mq) {
   std::lock_guard<std::mutex> lock(m_lock);
-  if (m_pullFromWhichNodeTable.find(mq) != m_pullFromWhichNodeTable.end()) {
-    return m_pullFromWhichNodeTable[mq];
+  const auto& it = m_pullFromWhichNodeTable.find(mq);
+  if (it != m_pullFromWhichNodeTable.end()) {
+    return it->second;
   }
   return MASTER_ID;
 }
@@ -76,8 +77,8 @@ PullResult PullAPIWrapper::processPullResult(const MQMessageQueue& mq,
     }
 
     for (auto& msg : msgListFilterAgain) {
-      const auto& traFlag = msg->getProperty(MQMessageConst::PROPERTY_TRANSACTION_PREPARED);
-      if (UtilAll::stob(traFlag)) {
+      const auto& tranMsg = msg->getProperty(MQMessageConst::PROPERTY_TRANSACTION_PREPARED);
+      if (UtilAll::stob(tranMsg)) {
         msg->setTransactionId(msg->getProperty(MQMessageConst::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX));
       }
       MessageAccessor::putProperty(*msg, MQMessageConst::PROPERTY_MIN_OFFSET, UtilAll::to_string(pullResult.minOffset));
diff --git a/src/consumer/PullMessageService.h b/src/consumer/PullMessageService.hpp
similarity index 91%
rename from src/consumer/PullMessageService.h
rename to src/consumer/PullMessageService.hpp
index 7c7b11a..8f6a6d5 100644
--- a/src/consumer/PullMessageService.h
+++ b/src/consumer/PullMessageService.hpp
@@ -14,8 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __PULL_MESSAGE_SERVICE_H__
-#define __PULL_MESSAGE_SERVICE_H__
+#ifndef __PULL_MESSAGE_SERVICE_HPP__
+#define __PULL_MESSAGE_SERVICE_HPP__
 
 #include "DefaultMQPushConsumerImpl.h"
 #include "Logging.h"
@@ -57,7 +57,8 @@ class PullMessageService {
  private:
   void pullMessage(PullRequestPtr pullRequest) {
     MQConsumerInner* consumer = m_clientInstance->selectConsumer(pullRequest->getConsumerGroup());
-    if (consumer != nullptr && std::type_index(typeid(*consumer)) == std::type_index(typeid(DefaultMQPushConsumerImpl))) {
+    if (consumer != nullptr &&
+        std::type_index(typeid(*consumer)) == std::type_index(typeid(DefaultMQPushConsumerImpl))) {
       auto* impl = static_cast<DefaultMQPushConsumerImpl*>(consumer);
       impl->pullMessage(pullRequest);
     } else {
@@ -72,4 +73,4 @@ class PullMessageService {
 
 }  // namespace rocketmq
 
-#endif  // __PULL_MESSAGE_SERVICE_H__
+#endif  // __PULL_MESSAGE_SERVICE_HPP__
diff --git a/src/consumer/PullResult.cpp b/src/consumer/PullResult.cpp
index ec9f4d6..8fe82f2 100644
--- a/src/consumer/PullResult.cpp
+++ b/src/consumer/PullResult.cpp
@@ -20,6 +20,11 @@
 
 namespace rocketmq {
 
+static const char* EnumStrings[] = {"FOUND", "NO_NEW_MSG", "NO_MATCHED_MSG",
+                                    "NO_LATEST_MSG"
+                                    "OFFSET_ILLEGAL",
+                                    "BROKER_TIMEOUT"};
+
 PullResult::PullResult() : pullStatus(NO_MATCHED_MSG), nextBeginOffset(0), minOffset(0), maxOffset(0) {}
 
 PullResult::PullResult(PullStatus status) : pullStatus(status), nextBeginOffset(0), minOffset(0), maxOffset(0) {}
@@ -51,4 +56,11 @@ PullResult::PullResult(PullStatus pullStatus,
 
 PullResult::~PullResult() = default;
 
+std::string PullResult::toString() const {
+  std::stringstream ss;
+  ss << "PullResult [ pullStatus=" << EnumStrings[pullStatus] << ", nextBeginOffset=" << nextBeginOffset
+     << ", minOffset=" << minOffset << ", maxOffset=" << maxOffset << ", msgFoundList=" << msgFoundList.size() << " ]";
+  return ss.str();
+}
+
 }  // namespace rocketmq
diff --git a/src/consumer/PullResultExt.h b/src/consumer/PullResultExt.h
index 5a3c614..420419c 100644
--- a/src/consumer/PullResultExt.h
+++ b/src/consumer/PullResultExt.h
@@ -38,7 +38,7 @@ class PullResultExt : public PullResult {
                 int64_t minOffset,
                 int64_t maxOffset,
                 int suggestWhichBrokerId,
-                const MemoryBlockPtr2& messageBinary)
+                MemoryBlockPtr2 messageBinary)
       : PullResult(pullStatus, nextBeginOffset, minOffset, maxOffset),
         suggestWhichBrokerId(suggestWhichBrokerId),
         msgMemBlock(messageBinary) {}
diff --git a/src/consumer/RebalanceImpl.cpp b/src/consumer/RebalanceImpl.cpp
index 2eec0ee..d3b8e78 100644
--- a/src/consumer/RebalanceImpl.cpp
+++ b/src/consumer/RebalanceImpl.cpp
@@ -16,9 +16,9 @@
  */
 #include "RebalanceImpl.h"
 
-#include "LockBatchBody.h"
 #include "MQClientAPIImpl.h"
 #include "MQClientInstance.h"
+#include "protocol/body/LockBatchBody.h"
 
 namespace rocketmq {
 
@@ -107,8 +107,8 @@ void RebalanceImpl::unlockAll(const bool oneway) {
 }
 
 std::shared_ptr<BROKER2MQS> RebalanceImpl::buildProcessQueueTableByBrokerName() {
-  std::shared_ptr<BROKER2MQS> brokerMqs = std::make_shared<BROKER2MQS>();
-  MQ2PQ processQueueTable = getProcessQueueTable();
+  auto brokerMqs = std::make_shared<BROKER2MQS>();
+  auto processQueueTable = getProcessQueueTable();
   for (const auto& it : processQueueTable) {
     const auto& mq = it.first;
     std::string brokerName = mq.getBrokerName();
@@ -404,9 +404,9 @@ bool RebalanceImpl::updateProcessQueueTableInRebalance(const std::string& topic,
 
 void RebalanceImpl::removeProcessQueue(const MQMessageQueue& mq) {
   std::lock_guard<std::mutex> lock(m_processQueueTableMutex);
-  auto it = m_processQueueTable.find(mq);
+  const auto& it = m_processQueueTable.find(mq);
   if (it != m_processQueueTable.end()) {
-    ProcessQueuePtr prev = it->second;
+    auto prev = it->second;
     m_processQueueTable.erase(it);
 
     bool dropped = prev->isDropped();
@@ -419,33 +419,33 @@ void RebalanceImpl::removeProcessQueue(const MQMessageQueue& mq) {
 
 ProcessQueuePtr RebalanceImpl::removeProcessQueueDirectly(const MQMessageQueue& mq) {
   std::lock_guard<std::mutex> lock(m_processQueueTableMutex);
-  auto it = m_processQueueTable.find(mq);
+  const auto& it = m_processQueueTable.find(mq);
   if (it != m_processQueueTable.end()) {
-    ProcessQueuePtr old = it->second;
+    auto old = it->second;
     m_processQueueTable.erase(it);
     return old;
   }
-  return ProcessQueuePtr();
+  return nullptr;
 }
 
 ProcessQueuePtr RebalanceImpl::putProcessQueueIfAbsent(const MQMessageQueue& mq, ProcessQueuePtr pq) {
   std::lock_guard<std::mutex> lock(m_processQueueTableMutex);
-  auto it = m_processQueueTable.find(mq);
+  const auto& it = m_processQueueTable.find(mq);
   if (it != m_processQueueTable.end()) {
     return it->second;
   } else {
     m_processQueueTable[mq] = pq;
-    return ProcessQueuePtr();
+    return nullptr;
   }
 }
 
 ProcessQueuePtr RebalanceImpl::getProcessQueue(const MQMessageQueue& mq) {
   std::lock_guard<std::mutex> lock(m_processQueueTableMutex);
-  if (m_processQueueTable.find(mq) != m_processQueueTable.end()) {
-    return m_processQueueTable[mq];
+  const auto& it = m_processQueueTable.find(mq);
+  if (it != m_processQueueTable.end()) {
+    return it->second;
   } else {
-    ProcessQueuePtr ptr;
-    return ptr;
+    return nullptr;
   }
 }
 
@@ -477,7 +477,7 @@ TOPIC2SD& RebalanceImpl::getSubscriptionInner() {
 }
 
 SubscriptionDataPtr RebalanceImpl::getSubscriptionData(const std::string& topic) {
-  auto it = m_subscriptionInner.find(topic);
+  const auto& it = m_subscriptionInner.find(topic);
   if (it != m_subscriptionInner.end()) {
     return it->second;
   }
@@ -486,7 +486,7 @@ SubscriptionDataPtr RebalanceImpl::getSubscriptionData(const std::string& topic)
 
 void RebalanceImpl::setSubscriptionData(const std::string& topic, SubscriptionDataPtr subscriptionData) noexcept {
   if (subscriptionData != nullptr) {
-    auto it = m_subscriptionInner.find(topic);
+    const auto& it = m_subscriptionInner.find(topic);
     if (it != m_subscriptionInner.end()) {
       deleteAndZero(it->second);
     }
@@ -496,8 +496,9 @@ void RebalanceImpl::setSubscriptionData(const std::string& topic, SubscriptionDa
 
 bool RebalanceImpl::getTopicSubscribeInfo(const std::string& topic, std::vector<MQMessageQueue>& mqs) {
   std::lock_guard<std::mutex> lock(m_topicSubscribeInfoTableMutex);
-  if (m_topicSubscribeInfoTable.find(topic) != m_topicSubscribeInfoTable.end()) {
-    mqs = m_topicSubscribeInfoTable[topic];
+  const auto& it = m_topicSubscribeInfoTable.find(topic);
+  if (it != m_topicSubscribeInfoTable.end()) {
+    mqs = it->second;  // mqs will out
     return true;
   }
   return false;
@@ -510,8 +511,6 @@ void RebalanceImpl::setTopicSubscribeInfo(const std::string& topic, std::vector<
 
   {
     std::lock_guard<std::mutex> lock(m_topicSubscribeInfoTableMutex);
-    if (m_topicSubscribeInfoTable.find(topic) != m_topicSubscribeInfoTable.end())
-      m_topicSubscribeInfoTable.erase(topic);
     m_topicSubscribeInfoTable[topic] = mqs;
   }
 
diff --git a/src/consumer/RebalanceImpl.h b/src/consumer/RebalanceImpl.h
index 69d2b3d..0a62f49 100755
--- a/src/consumer/RebalanceImpl.h
+++ b/src/consumer/RebalanceImpl.h
@@ -40,7 +40,7 @@ class RebalanceImpl {
   RebalanceImpl(const std::string& consumerGroup,
                 MessageModel messageModel,
                 AllocateMQStrategy* allocateMqStrategy,
-                MQClientInstance* mqClientFactory);
+                MQClientInstance* clientInstance);
   virtual ~RebalanceImpl();
 
   void unlock(MQMessageQueue mq, const bool oneway = false);
@@ -91,7 +91,7 @@ class RebalanceImpl {
   void setConsumerGroup(const std::string& groupname) { m_consumerGroup = groupname; }
   void setMessageModel(MessageModel messageModel) { m_messageModel = messageModel; }
   void setAllocateMQStrategy(AllocateMQStrategy* allocateMqStrategy) { m_allocateMQStrategy = allocateMqStrategy; }
-  void setMQClientFactory(MQClientInstance* instance) { m_clientInstance = instance; }
+  void setClientInstance(MQClientInstance* instance) { m_clientInstance = instance; }
 
  protected:
   MQ2PQ m_processQueueTable;
diff --git a/src/consumer/RebalancePushImpl.cpp b/src/consumer/RebalancePushImpl.cpp
index ef8c1b8..7ba0a53 100644
--- a/src/consumer/RebalancePushImpl.cpp
+++ b/src/consumer/RebalancePushImpl.cpp
@@ -116,7 +116,7 @@ int64_t RebalancePushImpl::computePullFromWhere(const MQMessageQueue& mq) {
           }
         } else {
           try {
-            // TODO: parseDate by YYYYMMDDHHMMSS
+            // FIXME: parseDate by YYYYMMDDHHMMSS
             auto timestamp =
                 std::stoull(m_defaultMQPushConsumer->getDefaultMQPushConsumerConfig()->getConsumeTimestamp());
             result = m_defaultMQPushConsumer->searchOffset(mq, timestamp);
diff --git a/src/consumer/SubscriptionData.cpp b/src/consumer/SubscriptionData.cpp
index 455b1cb..e67a5b8 100644
--- a/src/consumer/SubscriptionData.cpp
+++ b/src/consumer/SubscriptionData.cpp
@@ -70,7 +70,7 @@ std::vector<std::string>& SubscriptionData::getTagsSet() {
   return m_tagSet;
 }
 
-void SubscriptionData::putCodeSet(const int32 code) {
+void SubscriptionData::putCodeSet(int32_t code) {
   m_codeSet.push_back(code);
 }
 
diff --git a/src/extern/CBatchMessage.cpp b/src/extern/CBatchMessage.cpp
index f92125d..2ea6ece 100644
--- a/src/extern/CBatchMessage.cpp
+++ b/src/extern/CBatchMessage.cpp
@@ -20,12 +20,11 @@
 
 #include "MQMessage.h"
 
-using std::vector;
 using namespace rocketmq;
 
 CBatchMessage* CreateBatchMessage() {
-  vector<MQMessage*>* msgs = new vector<MQMessage*>();
-  return (CBatchMessage*)msgs;
+  auto* msgs = new std::vector<MQMessage*>();
+  return reinterpret_cast<CBatchMessage*>(msgs);
 }
 
 int AddMessage(CBatchMessage* batchMsg, CMessage* msg) {
@@ -35,8 +34,8 @@ int AddMessage(CBatchMessage* batchMsg, CMessage* msg) {
   if (batchMsg == NULL) {
     return NULL_POINTER;
   }
-  MQMessage* message = (MQMessage*)msg;
-  ((vector<MQMessage*>*)batchMsg)->push_back(message);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
+  reinterpret_cast<std::vector<MQMessage*>*>(batchMsg)->push_back(message);
   return OK;
 }
 
@@ -44,9 +43,10 @@ int DestroyBatchMessage(CBatchMessage* batchMsg) {
   if (batchMsg == NULL) {
     return NULL_POINTER;
   }
-  for (auto* msg : *(vector<MQMessage*>*)batchMsg) {
+  auto* msgs = reinterpret_cast<std::vector<MQMessage*>*>(batchMsg);
+  for (auto* msg : *msgs) {
     delete msg;
   }
-  delete (vector<MQMessage*>*)batchMsg;
+  delete msgs;
   return OK;
 }
diff --git a/src/extern/CMessage.cpp b/src/extern/CMessage.cpp
index 4a28260..588668d 100644
--- a/src/extern/CMessage.cpp
+++ b/src/extern/CMessage.cpp
@@ -21,18 +21,18 @@
 using namespace rocketmq;
 
 CMessage* CreateMessage(const char* topic) {
-  MQMessage* mqMessage = new MQMessage();
+  auto* msg = new MQMessage();
   if (topic != NULL) {
-    mqMessage->setTopic(topic);
+    msg->setTopic(topic);
   }
-  return (CMessage*)mqMessage;
+  return reinterpret_cast<CMessage*>(msg);
 }
 
 int DestroyMessage(CMessage* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  delete (MQMessage*)msg;
+  delete reinterpret_cast<MQMessage*>(msg);
   return OK;
 }
 
@@ -40,7 +40,7 @@ int SetMessageTopic(CMessage* msg, const char* topic) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setTopic(topic);
+  reinterpret_cast<MQMessage*>(msg)->setTopic(topic);
   return OK;
 }
 
@@ -48,7 +48,7 @@ int SetMessageTags(CMessage* msg, const char* tags) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setTags(tags);
+  reinterpret_cast<MQMessage*>(msg)->setTags(tags);
   return OK;
 }
 
@@ -56,7 +56,7 @@ int SetMessageKeys(CMessage* msg, const char* keys) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setKeys(keys);
+  reinterpret_cast<MQMessage*>(msg)->setKeys(keys);
   return OK;
 }
 
@@ -64,7 +64,7 @@ int SetMessageBody(CMessage* msg, const char* body) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setBody(body);
+  reinterpret_cast<MQMessage*>(msg)->setBody(body);
   return OK;
 }
 
@@ -72,7 +72,7 @@ int SetByteMessageBody(CMessage* msg, const char* body, int len) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setBody(body, len);
+  reinterpret_cast<MQMessage*>(msg)->setBody(body, len);
   return OK;
 }
 
@@ -80,7 +80,7 @@ int SetMessageProperty(CMessage* msg, const char* key, const char* value) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->putProperty(key, value);
+  reinterpret_cast<MQMessage*>(msg)->putProperty(key, value);
   return OK;
 }
 
@@ -88,6 +88,48 @@ int SetDelayTimeLevel(CMessage* msg, int level) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  ((MQMessage*)msg)->setDelayTimeLevel(level);
+  reinterpret_cast<MQMessage*>(msg)->setDelayTimeLevel(level);
   return OK;
 }
+
+const char* GetOriginMessageTopic(CMessage* msg) {
+  if (msg == NULL) {
+    return NULL;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getTopic().c_str();
+}
+
+const char* GetOriginMessageTags(CMessage* msg) {
+  if (msg == NULL) {
+    return NULL;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getTags().c_str();
+}
+
+const char* GetOriginMessageKeys(CMessage* msg) {
+  if (msg == NULL) {
+    return NULL;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getKeys().c_str();
+}
+
+const char* GetOriginMessageBody(CMessage* msg) {
+  if (msg == NULL) {
+    return NULL;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getBody().c_str();
+}
+
+const char* GetOriginMessageProperty(CMessage* msg, const char* key) {
+  if (msg == NULL) {
+    return NULL;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getProperty(key).c_str();
+}
+
+int GetOriginDelayTimeLevel(CMessage* msg) {
+  if (msg == NULL) {
+    return -1;
+  }
+  return reinterpret_cast<MQMessage*>(msg)->getDelayTimeLevel();
+}
diff --git a/src/extern/CMessageExt.cpp b/src/extern/CMessageExt.cpp
index 35dc281..247ba5b 100644
--- a/src/extern/CMessageExt.cpp
+++ b/src/extern/CMessageExt.cpp
@@ -24,103 +24,103 @@ const char* GetMessageTopic(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getTopic().c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getTopic().c_str();
 }
 
 const char* GetMessageTags(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getTags().c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getTags().c_str();
 }
 
 const char* GetMessageKeys(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getKeys().c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getKeys().c_str();
 }
 
 const char* GetMessageBody(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getBody().c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getBody().c_str();
 }
 
 const char* GetMessageProperty(CMessageExt* msg, const char* key) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getProperty(key).c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getProperty(key).c_str();
 }
 
 const char* GetMessageId(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL;
   }
-  return ((MQMessageExt*)msg)->getMsgId().c_str();
+  return reinterpret_cast<MQMessageExt*>(msg)->getMsgId().c_str();
 }
 
 int GetMessageDelayTimeLevel(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getDelayTimeLevel();
+  return reinterpret_cast<MQMessageExt*>(msg)->getDelayTimeLevel();
 }
 
 int GetMessageQueueId(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getQueueId();
+  return reinterpret_cast<MQMessageExt*>(msg)->getQueueId();
 }
 
 int GetMessageReconsumeTimes(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getReconsumeTimes();
+  return reinterpret_cast<MQMessageExt*>(msg)->getReconsumeTimes();
 }
 
 int GetMessageStoreSize(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getStoreSize();
+  return reinterpret_cast<MQMessageExt*>(msg)->getStoreSize();
 }
 
 long long GetMessageBornTimestamp(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getBornTimestamp();
+  return reinterpret_cast<MQMessageExt*>(msg)->getBornTimestamp();
 }
 
 long long GetMessageStoreTimestamp(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getStoreTimestamp();
+  return reinterpret_cast<MQMessageExt*>(msg)->getStoreTimestamp();
 }
 
 long long GetMessageQueueOffset(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getQueueOffset();
+  return reinterpret_cast<MQMessageExt*>(msg)->getQueueOffset();
 }
 
 long long GetMessageCommitLogOffset(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getCommitLogOffset();
+  return reinterpret_cast<MQMessageExt*>(msg)->getCommitLogOffset();
 }
 
 long long GetMessagePreparedTransactionOffset(CMessageExt* msg) {
   if (msg == NULL) {
     return NULL_POINTER;
   }
-  return ((MQMessageExt*)msg)->getPreparedTransactionOffset();
+  return reinterpret_cast<MQMessageExt*>(msg)->getPreparedTransactionOffset();
 }
diff --git a/src/extern/CProducer.cpp b/src/extern/CProducer.cpp
index 3a4029f..60502c2 100644
--- a/src/extern/CProducer.cpp
+++ b/src/extern/CProducer.cpp
@@ -24,47 +24,104 @@
 #include "DefaultMQProducer.h"
 #include "Logging.h"
 #include "MQClientErrorContainer.h"
+#include "TransactionMQProducer.h"
 #include "UtilAll.h"
 
 using namespace rocketmq;
 
+class LocalTransactionExecutorInner {
+ public:
+  LocalTransactionExecutorInner(CLocalTransactionExecutorCallback callback, CMessage* message, void* userData)
+      : m_excutorCallback(callback), m_message(message), m_userData(userData) {}
+
+  ~LocalTransactionExecutorInner() = default;
+
+ public:
+  CLocalTransactionExecutorCallback m_excutorCallback;
+  CMessage* m_message;
+  void* m_userData;
+};
+
+class LocalTransactionListenerInner : public TransactionListener {
+ public:
+  LocalTransactionListenerInner(CProducer* producer, CLocalTransactionCheckerCallback callback, void* userData)
+      : m_producer(producer), m_checkerCallback(callback), m_userData(userData) {}
+
+  ~LocalTransactionListenerInner() = default;
+
+  LocalTransactionState executeLocalTransaction(const MQMessage& message, void* arg) override {
+    if (m_checkerCallback == nullptr) {
+      return LocalTransactionState::UNKNOWN;
+    }
+    auto* msg = reinterpret_cast<CMessage*>(const_cast<MQMessage*>(&message));
+    auto* executorInner = reinterpret_cast<LocalTransactionExecutorInner*>(arg);
+    auto status = executorInner->m_excutorCallback(m_producer, msg, executorInner->m_userData);
+    switch (status) {
+      case E_COMMIT_TRANSACTION:
+        return LocalTransactionState::COMMIT_MESSAGE;
+      case E_ROLLBACK_TRANSACTION:
+        return LocalTransactionState::ROLLBACK_MESSAGE;
+      default:
+        return LocalTransactionState::UNKNOWN;
+    }
+  }
+
+  LocalTransactionState checkLocalTransaction(const MQMessageExt& message) override {
+    if (m_checkerCallback == NULL) {
+      return LocalTransactionState::UNKNOWN;
+    }
+    auto* msgExt = reinterpret_cast<CMessageExt*>(const_cast<MQMessageExt*>(&message));
+    auto status = m_checkerCallback(m_producer, msgExt, m_userData);
+    switch (status) {
+      case E_COMMIT_TRANSACTION:
+        return LocalTransactionState::COMMIT_MESSAGE;
+      case E_ROLLBACK_TRANSACTION:
+        return LocalTransactionState::ROLLBACK_MESSAGE;
+      default:
+        return LocalTransactionState::UNKNOWN;
+    }
+  }
+
+ private:
+  CProducer* m_producer;
+  CLocalTransactionCheckerCallback m_checkerCallback;
+  void* m_userData;
+};
+
 class SelectMessageQueueInner : public MessageQueueSelector {
  public:
-  MQMessageQueue select(const std::vector<MQMessageQueue>& mqs, const MQMessage& msg, void* arg) {
-    int index = 0;
+  MQMessageQueue select(const std::vector<MQMessageQueue>& mqs, const MQMessage& msg, void* arg) override {
     std::string shardingKey = UtilAll::to_string((char*)arg);
-
-    index = std::hash<std::string>{}(shardingKey) % mqs.size();
+    auto index = std::hash<std::string>{}(shardingKey) % mqs.size();
     return mqs[index % mqs.size()];
   }
 };
 
 class SelectMessageQueue : public MessageQueueSelector {
  public:
-  SelectMessageQueue(QueueSelectorCallback callback) { m_pCallback = callback; }
+  SelectMessageQueue(QueueSelectorCallback callback) { m_callback = callback; }
 
-  MQMessageQueue select(const std::vector<MQMessageQueue>& mqs, const MQMessage& msg, void* arg) {
-    CMessage* message = (CMessage*)&msg;
+  MQMessageQueue select(const std::vector<MQMessageQueue>& mqs, const MQMessage& msg, void* arg) override {
+    auto* message = reinterpret_cast<CMessage*>(const_cast<MQMessage*>(&msg));
     // Get the index of sending MQMessageQueue through callback function.
-    int index = m_pCallback(mqs.size(), message, arg);
+    auto index = m_callback(mqs.size(), message, arg);
     return mqs[index];
   }
 
  private:
-  QueueSelectorCallback m_pCallback;
+  QueueSelectorCallback m_callback;
 };
 
 class COnSendCallback : public AutoDeleteSendCallback {
  public:
-  COnSendCallback(COnSendSuccessCallback cSendSuccessCallback,
-                  COnSendExceptionCallback cSendExceptionCallback,
-                  void* message,
-                  void* userData) {
-    m_cSendSuccessCallback = cSendSuccessCallback;
-    m_cSendExceptionCallback = cSendExceptionCallback;
-    m_message = message;
-    m_userData = userData;
-  }
+  COnSendCallback(COnSendSuccessCallback sendSuccessCallback,
+                  COnSendExceptionCallback sendExceptionCallback,
+                  CMessage* message,
+                  void* userData)
+      : m_sendSuccessCallback(sendSuccessCallback),
+        m_sendExceptionCallback(sendExceptionCallback),
+        m_message(message),
+        m_userData(userData) {}
 
   virtual ~COnSendCallback() = default;
 
@@ -74,7 +131,7 @@ class COnSendCallback : public AutoDeleteSendCallback {
     result.offset = sendResult.getQueueOffset();
     strncpy(result.msgId, sendResult.getMsgId().c_str(), MAX_MESSAGE_ID_LENGTH - 1);
     result.msgId[MAX_MESSAGE_ID_LENGTH - 1] = 0;
-    m_cSendSuccessCallback(result, (CMessage*)m_message, m_userData);
+    m_sendSuccessCallback(result, m_message, m_userData);
   }
 
   void onException(MQException& e) noexcept override {
@@ -83,22 +140,20 @@ class COnSendCallback : public AutoDeleteSendCallback {
     exception.line = e.GetLine();
     strncpy(exception.msg, e.what(), MAX_EXEPTION_MSG_LENGTH - 1);
     strncpy(exception.file, e.GetFile(), MAX_EXEPTION_FILE_LENGTH - 1);
-    m_cSendExceptionCallback(exception, (CMessage*)m_message, m_userData);
+    m_sendExceptionCallback(exception, m_message, m_userData);
   }
 
  private:
-  COnSendSuccessCallback m_cSendSuccessCallback;
-  COnSendExceptionCallback m_cSendExceptionCallback;
-  void* m_message;
+  COnSendSuccessCallback m_sendSuccessCallback;
+  COnSendExceptionCallback m_sendExceptionCallback;
+  CMessage* m_message;
   void* m_userData;
 };
 
 class CSendCallback : public AutoDeleteSendCallback {
  public:
-  CSendCallback(CSendSuccessCallback cSendSuccessCallback, CSendExceptionCallback cSendExceptionCallback) {
-    m_cSendSuccessCallback = cSendSuccessCallback;
-    m_cSendExceptionCallback = cSendExceptionCallback;
-  }
+  CSendCallback(CSendSuccessCallback sendSuccessCallback, CSendExceptionCallback sendExceptionCallback)
+      : m_sendSuccessCallback(sendSuccessCallback), m_sendExceptionCallback(sendExceptionCallback) {}
 
   virtual ~CSendCallback() = default;
 
@@ -108,7 +163,7 @@ class CSendCallback : public AutoDeleteSendCallback {
     result.offset = sendResult.getQueueOffset();
     strncpy(result.msgId, sendResult.getMsgId().c_str(), MAX_MESSAGE_ID_LENGTH - 1);
     result.msgId[MAX_MESSAGE_ID_LENGTH - 1] = 0;
-    m_cSendSuccessCallback(result);
+    m_sendSuccessCallback(result);
   }
 
   void onException(MQException& e) noexcept override {
@@ -117,12 +172,12 @@ class CSendCallback : public AutoDeleteSendCallback {
     exception.line = e.GetLine();
     strncpy(exception.msg, e.what(), MAX_EXEPTION_MSG_LENGTH - 1);
     strncpy(exception.file, e.GetFile(), MAX_EXEPTION_FILE_LENGTH - 1);
-    m_cSendExceptionCallback(exception);
+    m_sendExceptionCallback(exception);
   }
 
  private:
-  CSendSuccessCallback m_cSendSuccessCallback;
-  CSendExceptionCallback m_cSendExceptionCallback;
+  CSendSuccessCallback m_sendSuccessCallback;
+  CSendExceptionCallback m_sendExceptionCallback;
 };
 
 CProducer* CreateProducer(const char* groupId) {
@@ -130,13 +185,24 @@ CProducer* CreateProducer(const char* groupId) {
     return NULL;
   }
   auto* defaultMQProducer = new DefaultMQProducer(groupId);
-  return (CProducer*)defaultMQProducer;
+  return reinterpret_cast<CProducer*>(defaultMQProducer);
 }
 
 CProducer* CreateOrderlyProducer(const char* groupId) {
   return CreateProducer(groupId);
 }
 
+CProducer* CreateTransactionProducer(const char* groupId, CLocalTransactionCheckerCallback callback, void* userData) {
+  if (groupId == NULL) {
+    return NULL;
+  }
+  auto* transactionMQProducer = new TransactionMQProducer(groupId);
+  auto* producer = reinterpret_cast<CProducer*>(static_cast<DefaultMQProducer*>(transactionMQProducer));
+  auto* transcationListener = new LocalTransactionListenerInner(producer, callback, userData);
+  transactionMQProducer->setTransactionListener(transcationListener);
+  return producer;
+}
+
 int DestroyProducer(CProducer* producer) {
   if (producer == nullptr) {
     return NULL_POINTER;
@@ -184,14 +250,13 @@ int SetProducerNameServerDomain(CProducer* producer, const char* domain) {
 }
 
 int SendMessageSync(CProducer* producer, CMessage* msg, CSendResult* result) {
-  // CSendResult sendResult;
   if (producer == NULL || msg == NULL || result == NULL) {
     return NULL_POINTER;
   }
   try {
-    DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-    MQMessage* message = (MQMessage*)msg;
-    SendResult sendResult = defaultMQProducer->send(message);
+    auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+    auto* message = reinterpret_cast<MQMessage*>(msg);
+    auto sendResult = defaultMQProducer->send(message);
     switch (sendResult.getSendStatus()) {
       case SEND_OK:
         result->sendStatus = E_SEND_OK;
@@ -220,14 +285,13 @@ int SendMessageSync(CProducer* producer, CMessage* msg, CSendResult* result) {
 }
 
 int SendBatchMessage(CProducer* producer, CBatchMessage* batcMsg, CSendResult* result) {
-  // CSendResult sendResult;
   if (producer == NULL || batcMsg == NULL || result == NULL) {
     return NULL_POINTER;
   }
   try {
-    DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-    std::vector<MQMessage*>* message = (std::vector<MQMessage*>*)batcMsg;
-    SendResult sendResult = defaultMQProducer->send(*message);
+    auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+    auto* message = reinterpret_cast<std::vector<MQMessage*>*>(batcMsg);
+    auto sendResult = defaultMQProducer->send(*message);
     switch (sendResult.getSendStatus()) {
       case SEND_OK:
         result->sendStatus = E_SEND_OK;
@@ -256,30 +320,30 @@ int SendBatchMessage(CProducer* producer, CBatchMessage* batcMsg, CSendResult* r
 
 int SendMessageAsync(CProducer* producer,
                      CMessage* msg,
-                     CSendSuccessCallback cSendSuccessCallback,
-                     CSendExceptionCallback cSendExceptionCallback) {
-  if (producer == NULL || msg == NULL || cSendSuccessCallback == NULL || cSendExceptionCallback == NULL) {
+                     CSendSuccessCallback sendSuccessCallback,
+                     CSendExceptionCallback sendExceptionCallback) {
+  if (producer == NULL || msg == NULL || sendSuccessCallback == NULL || sendExceptionCallback == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
-  CSendCallback* cSendCallback = new CSendCallback(cSendSuccessCallback, cSendExceptionCallback);
-  defaultMQProducer->send(message, cSendCallback);
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
+  auto* sendCallback = new CSendCallback(sendSuccessCallback, sendExceptionCallback);
+  defaultMQProducer->send(message, sendCallback);
   return OK;
 }
 
 int SendAsync(CProducer* producer,
               CMessage* msg,
-              COnSendSuccessCallback onSuccess,
-              COnSendExceptionCallback onException,
-              void* usrData) {
-  if (producer == NULL || msg == NULL || onSuccess == NULL || onException == NULL) {
+              COnSendSuccessCallback sendSuccessCallback,
+              COnSendExceptionCallback sendExceptionCallback,
+              void* userData) {
+  if (producer == NULL || msg == NULL || sendSuccessCallback == NULL || sendExceptionCallback == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
-  COnSendCallback* cSendCallback = new COnSendCallback(onSuccess, onException, (void*)msg, usrData);
-  defaultMQProducer->send(message, cSendCallback);
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
+  auto* sendCallback = new COnSendCallback(sendSuccessCallback, sendExceptionCallback, msg, userData);
+  defaultMQProducer->send(message, sendCallback);
   return OK;
 }
 
@@ -287,8 +351,8 @@ int SendMessageOneway(CProducer* producer, CMessage* msg) {
   if (producer == NULL || msg == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
   try {
     defaultMQProducer->sendOneway(message);
   } catch (std::exception& e) {
@@ -301,8 +365,8 @@ int SendMessageOnewayOrderly(CProducer* producer, CMessage* msg, QueueSelectorCa
   if (producer == NULL || msg == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
   try {
     SelectMessageQueue selectMessageQueue(selector);
     defaultMQProducer->sendOneway(message, &selectMessageQueue, arg);
@@ -315,37 +379,37 @@ int SendMessageOnewayOrderly(CProducer* producer, CMessage* msg, QueueSelectorCa
 
 int SendMessageOrderlyAsync(CProducer* producer,
                             CMessage* msg,
-                            QueueSelectorCallback callback,
+                            QueueSelectorCallback selectorCallback,
                             void* arg,
-                            CSendSuccessCallback cSendSuccessCallback,
-                            CSendExceptionCallback cSendExceptionCallback) {
-  if (producer == NULL || msg == NULL || callback == NULL || cSendSuccessCallback == NULL ||
-      cSendExceptionCallback == NULL) {
+                            CSendSuccessCallback sendSuccessCallback,
+                            CSendExceptionCallback sendExceptionCallback) {
+  if (producer == NULL || msg == NULL || selectorCallback == NULL || sendSuccessCallback == NULL ||
+      sendExceptionCallback == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
-  CSendCallback* cSendCallback = new CSendCallback(cSendSuccessCallback, cSendExceptionCallback);
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
+  auto* cSendCallback = new CSendCallback(sendSuccessCallback, sendExceptionCallback);
   // Constructing SelectMessageQueue objects through function pointer callback
-  SelectMessageQueue selectMessageQueue(callback);
+  SelectMessageQueue selectMessageQueue(selectorCallback);
   defaultMQProducer->send(message, &selectMessageQueue, arg, cSendCallback);
   return OK;
 }
 
 int SendMessageOrderly(CProducer* producer,
                        CMessage* msg,
-                       QueueSelectorCallback callback,
+                       QueueSelectorCallback selectorCallback,
                        void* arg,
                        int autoRetryTimes,
                        CSendResult* result) {
-  if (producer == NULL || msg == NULL || callback == NULL || arg == NULL || result == NULL) {
+  if (producer == NULL || msg == NULL || selectorCallback == NULL || arg == NULL || result == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
   try {
     // Constructing SelectMessageQueue objects through function pointer callback
-    SelectMessageQueue selectMessageQueue(callback);
+    SelectMessageQueue selectMessageQueue(selectorCallback);
     SendResult sendResult = defaultMQProducer->send(message, &selectMessageQueue, arg);
     // Convert SendStatus to CSendStatus
     result->sendStatus = CSendStatus((int)sendResult.getSendStatus());
@@ -363,8 +427,8 @@ int SendMessageOrderlyByShardingKey(CProducer* producer, CMessage* msg, const ch
   if (producer == NULL || msg == NULL || shardingKey == NULL || result == NULL) {
     return NULL_POINTER;
   }
-  DefaultMQProducer* defaultMQProducer = (DefaultMQProducer*)producer;
-  MQMessage* message = (MQMessage*)msg;
+  auto* defaultMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+  auto* message = reinterpret_cast<MQMessage*>(msg);
   try {
     // Constructing SelectMessageQueue objects through function pointer callback
     int retryTimes = 3;
@@ -382,6 +446,30 @@ int SendMessageOrderlyByShardingKey(CProducer* producer, CMessage* msg, const ch
   return OK;
 }
 
+int SendMessageTransaction(CProducer* producer,
+                           CMessage* msg,
+                           CLocalTransactionExecutorCallback callback,
+                           void* userData,
+                           CSendResult* result) {
+  if (producer == NULL || msg == NULL || callback == NULL || result == NULL) {
+    return NULL_POINTER;
+  }
+  try {
+    auto* transactionMQProducer = reinterpret_cast<DefaultMQProducer*>(producer);
+    auto* message = reinterpret_cast<MQMessage*>(msg);
+    LocalTransactionExecutorInner executorInner(callback, msg, userData);
+    auto sendResult = transactionMQProducer->sendMessageInTransaction(message, &executorInner);
+    result->sendStatus = CSendStatus((int)sendResult.getSendStatus());
+    result->offset = sendResult.getQueueOffset();
+    strncpy(result->msgId, sendResult.getMsgId().c_str(), MAX_MESSAGE_ID_LENGTH - 1);
+    result->msgId[MAX_MESSAGE_ID_LENGTH - 1] = 0;
+  } catch (std::exception& e) {
+    MQClientErrorContainer::setErr(std::string(e.what()));
+    return PRODUCER_SEND_TRANSACTION_FAILED;
+  }
+  return OK;
+}
+
 int SetProducerGroupName(CProducer* producer, const char* groupName) {
   if (producer == NULL) {
     return NULL_POINTER;
@@ -414,7 +502,7 @@ int SetProducerLogPath(CProducer* producer, const char* logPath) {
   if (producer == NULL) {
     return NULL_POINTER;
   }
-  // Todo, This api should be implemented by core api.
+  // TODO: This api should be implemented by core api.
   // reinterpret_cast<DefaultMQProducer*>(producer)->setLogFileSizeAndNum(3, 102400000);
   return OK;
 }
diff --git a/src/extern/CPullConsumer.cpp b/src/extern/CPullConsumer.cpp
index 497b896..61210a3 100644
--- a/src/extern/CPullConsumer.cpp
+++ b/src/extern/CPullConsumer.cpp
@@ -29,8 +29,8 @@ CPullConsumer* CreatePullConsumer(const char* groupId) {
   if (groupId == NULL) {
     return NULL;
   }
-  DefaultMQPullConsumer* defaultMQPullConsumer = new DefaultMQPullConsumer(groupId);
-  return (CPullConsumer*)defaultMQPullConsumer;
+  auto* defaultMQPullConsumer = new DefaultMQPullConsumer(groupId);
+  return reinterpret_cast<CPullConsumer*>(defaultMQPullConsumer);
 }
 
 int DestroyPullConsumer(CPullConsumer* consumer) {
diff --git a/src/extern/CPushConsumer.cpp b/src/extern/CPushConsumer.cpp
index add5ef3..40fbd2b 100644
--- a/src/extern/CPushConsumer.cpp
+++ b/src/extern/CPushConsumer.cpp
@@ -27,23 +27,19 @@ using namespace rocketmq;
 
 class MessageListenerInner : public MessageListenerConcurrently {
  public:
-  MessageListenerInner() {}
+  MessageListenerInner(CPushConsumer* consumer, MessageCallBack callback)
+      : m_consumer(consumer), m_msgReceivedCallback(callback) {}
 
-  MessageListenerInner(CPushConsumer* consumer, MessageCallBack pCallback) {
-    m_pconsumer = consumer;
-    m_pMsgReceiveCallback = pCallback;
-  }
-
-  ~MessageListenerInner() {}
+  ~MessageListenerInner() = default;
 
-  ConsumeStatus consumeMessage(const std::vector<MQMessageExt*>& msgs) {
+  ConsumeStatus consumeMessage(const std::vector<MQMessageExt*>& msgs) override {
     // to do user call back
-    if (m_pMsgReceiveCallback == nullptr) {
+    if (m_msgReceivedCallback == nullptr) {
       return RECONSUME_LATER;
     }
-    for (size_t i = 0; i < msgs.size(); ++i) {
-      CMessageExt* message = (CMessageExt*)msgs[i];
-      if (m_pMsgReceiveCallback(m_pconsumer, message) != E_CONSUME_SUCCESS) {
+    for (auto msg : msgs) {
+      auto* message = reinterpret_cast<CMessageExt*>(msg);
+      if (m_msgReceivedCallback(m_consumer, message) != E_CONSUME_SUCCESS) {
         return RECONSUME_LATER;
       }
     }
@@ -51,24 +47,22 @@ class MessageListenerInner : public MessageListenerConcurrently {
   }
 
  private:
-  MessageCallBack m_pMsgReceiveCallback;
-  CPushConsumer* m_pconsumer;
+  CPushConsumer* m_consumer;
+  MessageCallBack m_msgReceivedCallback;
 };
 
 class MessageListenerOrderlyInner : public MessageListenerOrderly {
  public:
-  MessageListenerOrderlyInner(CPushConsumer* consumer, MessageCallBack pCallback) {
-    m_pconsumer = consumer;
-    m_pMsgReceiveCallback = pCallback;
-  }
+  MessageListenerOrderlyInner(CPushConsumer* consumer, MessageCallBack callback)
+      : m_consumer(consumer), m_msgReceivedCallback(callback) {}
 
   ConsumeStatus consumeMessage(const std::vector<MQMessageExt*>& msgs) {
-    if (m_pMsgReceiveCallback == nullptr) {
+    if (m_msgReceivedCallback == nullptr) {
       return RECONSUME_LATER;
     }
-    for (size_t i = 0; i < msgs.size(); ++i) {
-      CMessageExt* message = (CMessageExt*)msgs[i];
-      if (m_pMsgReceiveCallback(m_pconsumer, message) != E_CONSUME_SUCCESS) {
+    for (auto msg : msgs) {
+      auto* message = reinterpret_cast<CMessageExt*>(msg);
+      if (m_msgReceivedCallback(m_consumer, message) != E_CONSUME_SUCCESS) {
         return RECONSUME_LATER;
       }
     }
@@ -76,13 +70,10 @@ class MessageListenerOrderlyInner : public MessageListenerOrderly {
   }
 
  private:
-  MessageCallBack m_pMsgReceiveCallback;
-  CPushConsumer* m_pconsumer;
+  CPushConsumer* m_consumer;
+  MessageCallBack m_msgReceivedCallback;
 };
 
-std::map<CPushConsumer*, MessageListenerInner*> g_ListenerMap;
-std::map<CPushConsumer*, MessageListenerOrderlyInner*> g_OrderListenerMap;
-
 CPushConsumer* CreatePushConsumer(const char* groupId) {
   if (groupId == NULL) {
     return NULL;
@@ -160,23 +151,21 @@ int Subscribe(CPushConsumer* consumer, const char* topic, const char* expression
   return OK;
 }
 
-int RegisterMessageCallback(CPushConsumer* consumer, MessageCallBack pCallback) {
-  if (consumer == NULL || pCallback == NULL) {
+int RegisterMessageCallback(CPushConsumer* consumer, MessageCallBack callback) {
+  if (consumer == NULL || callback == NULL) {
     return NULL_POINTER;
   }
-  MessageListenerInner* listenerInner = new MessageListenerInner(consumer, pCallback);
+  auto* listenerInner = new MessageListenerInner(consumer, callback);
   reinterpret_cast<DefaultMQPushConsumer*>(consumer)->registerMessageListener(listenerInner);
-  g_ListenerMap[consumer] = listenerInner;
   return OK;
 }
 
-int RegisterMessageCallbackOrderly(CPushConsumer* consumer, MessageCallBack pCallback) {
-  if (consumer == NULL || pCallback == NULL) {
+int RegisterMessageCallbackOrderly(CPushConsumer* consumer, MessageCallBack callback) {
+  if (consumer == NULL || callback == NULL) {
     return NULL_POINTER;
   }
-  MessageListenerOrderlyInner* messageListenerOrderlyInner = new MessageListenerOrderlyInner(consumer, pCallback);
+  auto* messageListenerOrderlyInner = new MessageListenerOrderlyInner(consumer, callback);
   reinterpret_cast<DefaultMQPushConsumer*>(consumer)->registerMessageListener(messageListenerOrderlyInner);
-  g_OrderListenerMap[consumer] = messageListenerOrderlyInner;
   return OK;
 }
 
@@ -184,15 +173,8 @@ int UnregisterMessageCallbackOrderly(CPushConsumer* consumer) {
   if (consumer == NULL) {
     return NULL_POINTER;
   }
-  std::map<CPushConsumer*, MessageListenerOrderlyInner*>::iterator iter;
-  iter = g_OrderListenerMap.find(consumer);
-  if (iter != g_OrderListenerMap.end()) {
-    MessageListenerOrderlyInner* listenerInner = iter->second;
-    if (listenerInner != NULL) {
-      delete listenerInner;
-    }
-    g_OrderListenerMap.erase(iter);
-  }
+  auto* listenerInner = reinterpret_cast<DefaultMQPushConsumer*>(consumer)->getMessageListener();
+  delete listenerInner;
   return OK;
 }
 
@@ -200,16 +182,8 @@ int UnregisterMessageCallback(CPushConsumer* consumer) {
   if (consumer == NULL) {
     return NULL_POINTER;
   }
-  std::map<CPushConsumer*, MessageListenerInner*>::iterator iter;
-  iter = g_ListenerMap.find(consumer);
-
-  if (iter != g_ListenerMap.end()) {
-    MessageListenerInner* listenerInner = iter->second;
-    if (listenerInner != NULL) {
-      delete listenerInner;
-    }
-    g_ListenerMap.erase(iter);
-  }
+  auto* listenerInner = reinterpret_cast<DefaultMQPushConsumer*>(consumer)->getMessageListener();
+  delete listenerInner;
   return OK;
 }
 
@@ -275,7 +249,7 @@ int SetPushConsumerLogPath(CPushConsumer* consumer, const char* logPath) {
   if (consumer == NULL) {
     return NULL_POINTER;
   }
-  // Todo, This api should be implemented by core api.
+  // TODO: This api should be implemented by core api.
   // reinterpret_cast<DefaultMQPushConsumer*>(consumer)->setInstanceName(instanceName);
   return OK;
 }
diff --git a/src/message/MQDecoder.cpp b/src/message/MQDecoder.cpp
index 9310574..863fa41 100644
--- a/src/message/MQDecoder.cpp
+++ b/src/message/MQDecoder.cpp
@@ -41,13 +41,13 @@ int MQDecoder::MessageFlagPostion = 16;
 int MQDecoder::MessagePhysicOffsetPostion = 28;
 int MQDecoder::MessageStoreTimestampPostion = 56;
 
-std::string MQDecoder::createMessageId(sockaddr addr, int64_t offset) {
-  struct sockaddr_in* sa = (struct sockaddr_in*)&addr;
+std::string MQDecoder::createMessageId(const struct sockaddr* sa, int64_t offset) {
+  const struct sockaddr_in* sin = (struct sockaddr_in*)sa;
 
   MemoryOutputStream outputmen(MSG_ID_LENGTH);
-  outputmen.writeIntBigEndian(sa->sin_addr.s_addr);
+  outputmen.writeIntBigEndian(sin->sin_addr.s_addr);
   outputmen.writeRepeatedByte(0, 2);
-  outputmen.write(&(sa->sin_port), 2);
+  outputmen.write(&(sin->sin_port), 2);
   outputmen.writeInt64BigEndian(offset);
 
   const char* bytes = static_cast<const char*>(outputmen.getData());
@@ -67,12 +67,12 @@ MQMessageId MQDecoder::decodeMessageId(const std::string& msgId) {
 
   uint64_t offset = UtilAll::hexstr2ull(offsetStr.c_str());
 
-  struct sockaddr_in sa;
-  sa.sin_family = AF_INET;
-  sa.sin_port = htons(portInt);
-  sa.sin_addr.s_addr = htonl(ipInt);
+  struct sockaddr_in sin;
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(portInt);
+  sin.sin_addr.s_addr = htonl(ipInt);
 
-  return MQMessageId(*((sockaddr*)&sa), offset);
+  return MQMessageId((struct sockaddr*)&sin, offset);
 }
 
 MQMessageExtPtr MQDecoder::clientDecode(MemoryInputStream& byteBuffer, bool readBody) {
@@ -130,18 +130,16 @@ MQMessageExtPtr MQDecoder::decode(MemoryInputStream& byteBuffer, bool readBody,
   // 10 BORNHOST
   int32_t bornHost = byteBuffer.readIntBigEndian();
   int32_t bornPort = byteBuffer.readIntBigEndian();
-  sockaddr bornAddr = IPPort2socketAddress(bornHost, bornPort);
-  msgExt->setBornHost(bornAddr);
+  msgExt->setBornHost(ipPort2SocketAddress(bornHost, bornPort));
 
   // 11 STORETIMESTAMP
   int64_t storeTimestamp = byteBuffer.readInt64BigEndian();
   msgExt->setStoreTimestamp(storeTimestamp);
 
-  // // 12 STOREHOST
+  // 12 STOREHOST
   int32_t storeHost = byteBuffer.readIntBigEndian();
   int32_t storePort = byteBuffer.readIntBigEndian();
-  sockaddr storeAddr = IPPort2socketAddress(storeHost, storePort);
-  msgExt->setStoreHost(storeAddr);
+  msgExt->setStoreHost(ipPort2SocketAddress(storeHost, storePort));
 
   // 13 RECONSUMETIMES
   int32_t reconsumeTimes = byteBuffer.readIntBigEndian();
diff --git a/src/message/MQDecoder.h b/src/message/MQDecoder.h
index 01b6f84..8b9eea3 100644
--- a/src/message/MQDecoder.h
+++ b/src/message/MQDecoder.h
@@ -25,13 +25,12 @@
 #include "MQMessageExt.h"
 #include "MQMessageId.h"
 #include "MemoryInputStream.h"
-#include "SocketUtil.h"
 
 namespace rocketmq {
 
 class MQDecoder {
  public:
-  static std::string createMessageId(sockaddr addr, int64_t offset);
+  static std::string createMessageId(const struct sockaddr* sa, int64_t offset);
   static MQMessageId decodeMessageId(const std::string& msgId);
 
   static MQMessageExtPtr2 decode(MemoryBlock& mem);
diff --git a/src/message/MQMessage.cpp b/src/message/MQMessage.cpp
index c745a3f..3f2a29c 100644
--- a/src/message/MQMessage.cpp
+++ b/src/message/MQMessage.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 #include "MQMessage.h"
+
 #include "MessageSysFlag.h"
 #include "UtilAll.h"
 
@@ -47,6 +48,13 @@ const std::string MQMessageConst::PROPERTY_TRANSACTION_PREPARED_QUEUE_OFFSET = "
 const std::string MQMessageConst::PROPERTY_TRANSACTION_CHECK_TIMES = "TRANSACTION_CHECK_TIMES";
 const std::string MQMessageConst::PROPERTY_CHECK_IMMUNITY_TIME_IN_SECONDS = "CHECK_IMMUNITY_TIME_IN_SECONDS";
 const std::string MQMessageConst::PROPERTY_INSTANCE_ID = "INSTANCE_ID";
+const std::string MQMessageConst::PROPERTY_CORRELATION_ID = "CORRELATION_ID";
+const std::string MQMessageConst::PROPERTY_MESSAGE_REPLY_TO_CLIENT = "REPLY_TO_CLIENT";
+const std::string MQMessageConst::PROPERTY_MESSAGE_TTL = "TTL";
+const std::string MQMessageConst::PROPERTY_REPLY_MESSAGE_ARRIVE_TIME = "ARRIVE_TIME";
+const std::string MQMessageConst::PROPERTY_PUSH_REPLY_TIME = "PUSH_REPLY_TIME";
+const std::string MQMessageConst::PROPERTY_CLUSTER = "CLUSTER";
+const std::string MQMessageConst::PROPERTY_MESSAGE_TYPE = "MSG_TYPE";
 
 const std::string MQMessageConst::PROPERTY_ALREADY_COMPRESSED_FLAG = "__ALREADY_COMPRESSED__";
 
@@ -54,12 +62,12 @@ const std::string MQMessageConst::KEY_SEPARATOR = " ";
 
 static const std::string EMPTY_STRING = "";
 
-MQMessage::MQMessage() : MQMessage(null, "*", null, 0, null, true) {}
+MQMessage::MQMessage() : MQMessage(null, null) {}
 
-MQMessage::MQMessage(const std::string& topic, const std::string& body) : MQMessage(topic, "*", null, 0, body, true) {}
+MQMessage::MQMessage(const std::string& topic, const std::string& body) : MQMessage(topic, "", body) {}
 
 MQMessage::MQMessage(const std::string& topic, const std::string& tags, const std::string& body)
-    : MQMessage(topic, tags, null, 0, body, true) {}
+    : MQMessage(topic, tags, null, body) {}
 
 MQMessage::MQMessage(const std::string& topic,
                      const std::string& tags,
@@ -105,7 +113,7 @@ MQMessage& MQMessage::operator=(const MQMessage& other) {
 MQMessage::~MQMessage() = default;
 
 const std::string& MQMessage::getProperty(const std::string& name) const {
-  const auto it = m_properties.find(name);
+  const auto& it = m_properties.find(name);
   if (it != m_properties.end()) {
     return it->second;
   }
diff --git a/src/message/MQMessageExt.cpp b/src/message/MQMessageExt.cpp
index 4beef80..e76a844 100644
--- a/src/message/MQMessageExt.cpp
+++ b/src/message/MQMessageExt.cpp
@@ -25,26 +25,13 @@
 
 namespace rocketmq {
 
-MQMessageExt::MQMessageExt()
-    : m_storeSize(0),
-      m_bodyCRC(0),
-      m_queueId(0),
-      m_queueOffset(0),
-      m_commitLogOffset(0),
-      m_sysFlag(0),
-      m_bornTimestamp(0),
-      m_storeTimestamp(0),
-      m_reconsumeTimes(3),
-      m_preparedTransactionOffset(0) {
-  memset(&m_bornHost, 0, sizeof(m_bornHost));
-  memset(&m_storeHost, 0, sizeof(m_storeHost));
-}
+MQMessageExt::MQMessageExt() : MQMessageExt(0, 0, nullptr, 0, nullptr, "") {}
 
 MQMessageExt::MQMessageExt(int queueId,
                            int64_t bornTimestamp,
-                           sockaddr bornHost,
+                           const struct sockaddr* bornHost,
                            int64_t storeTimestamp,
-                           sockaddr storeHost,
+                           const struct sockaddr* storeHost,
                            std::string msgId)
     : m_storeSize(0),
       m_bodyCRC(0),
@@ -53,14 +40,20 @@ MQMessageExt::MQMessageExt(int queueId,
       m_commitLogOffset(0),
       m_sysFlag(0),
       m_bornTimestamp(bornTimestamp),
-      m_bornHost(bornHost),
+      m_bornHost(nullptr),
       m_storeTimestamp(storeTimestamp),
-      m_storeHost(storeHost),
+      m_storeHost(nullptr),
       m_reconsumeTimes(3),
       m_preparedTransactionOffset(0),
-      m_msgId(msgId) {}
+      m_msgId(msgId) {
+  m_bornHost = copySocketAddress(m_bornHost, bornHost);
+  m_storeHost = copySocketAddress(m_storeHost, storeHost);
+}
 
-MQMessageExt::~MQMessageExt() = default;
+MQMessageExt::~MQMessageExt() {
+  free(m_bornHost);
+  free(m_storeHost);
+}
 
 TopicFilterType MQMessageExt::parseTopicFilterType(int32_t sysFlag) {
   if ((sysFlag & MessageSysFlag::MultiTagsFlag) == MessageSysFlag::MultiTagsFlag) {
@@ -125,16 +118,16 @@ void MQMessageExt::setBornTimestamp(int64_t bornTimestamp) {
   m_bornTimestamp = bornTimestamp;
 }
 
-const sockaddr& MQMessageExt::getBornHost() const {
+const struct sockaddr* MQMessageExt::getBornHost() const {
   return m_bornHost;
 }
 
 std::string MQMessageExt::getBornHostString() const {
-  return socketAddress2String(&m_bornHost);
+  return socketAddress2String(m_bornHost);
 }
 
-void MQMessageExt::setBornHost(const sockaddr& bornHost) {
-  m_bornHost = bornHost;
+void MQMessageExt::setBornHost(const struct sockaddr* bornHost) {
+  m_bornHost = copySocketAddress(m_bornHost, bornHost);
 }
 
 int64_t MQMessageExt::getStoreTimestamp() const {
@@ -145,16 +138,16 @@ void MQMessageExt::setStoreTimestamp(int64_t storeTimestamp) {
   m_storeTimestamp = storeTimestamp;
 }
 
-const sockaddr& MQMessageExt::getStoreHost() const {
+const struct sockaddr* MQMessageExt::getStoreHost() const {
   return m_storeHost;
 }
 
 std::string MQMessageExt::getStoreHostString() const {
-  return socketAddress2String(&m_storeHost);
+  return socketAddress2String(m_storeHost);
 }
 
-void MQMessageExt::setStoreHost(const sockaddr& storeHost) {
-  m_storeHost = storeHost;
+void MQMessageExt::setStoreHost(const struct sockaddr* storeHost) {
+  m_storeHost = copySocketAddress(m_storeHost, storeHost);
 }
 
 const std::string& MQMessageExt::getMsgId() const {
diff --git a/src/message/MQMessageId.h b/src/message/MQMessageId.h
index da98e1f..2e31e78 100644
--- a/src/message/MQMessageId.h
+++ b/src/message/MQMessageId.h
@@ -24,27 +24,29 @@ namespace rocketmq {
 
 class MQMessageId {
  public:
-  MQMessageId() {}
-  MQMessageId(sockaddr address, int64_t offset) : m_address(address), m_offset(offset) {}
+  MQMessageId() : MQMessageId(nullptr, 0) {}
+  MQMessageId(struct sockaddr* address, int64_t offset) : m_address(nullptr), m_offset(offset) { setAddress(address); }
+  ~MQMessageId() { free(m_address); }
+
   MQMessageId& operator=(const MQMessageId& id) {
     if (&id == this) {
       return *this;
     }
-    this->m_address = id.m_address;
+    setAddress(id.m_address);
     this->m_offset = id.m_offset;
     return *this;
   }
 
-  const sockaddr& getAddress() const { return m_address; }
+  const struct sockaddr* getAddress() const { return m_address; }
 
-  void setAddress(sockaddr address) { m_address = address; }
+  void setAddress(struct sockaddr* address) { m_address = copySocketAddress(m_address, address); }
 
   int64_t getOffset() const { return m_offset; }
 
   void setOffset(int64_t offset) { m_offset = offset; }
 
  private:
-  sockaddr m_address;  // FIXME: store a pointer for ipv6
+  struct sockaddr* m_address;
   int64_t m_offset;
 };
 
diff --git a/src/message/MessageUtil.cpp b/src/message/MessageUtil.cpp
new file mode 100644
index 0000000..c5d2832
--- /dev/null
+++ b/src/message/MessageUtil.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+#include "MessageUtil.h"
+
+#include <memory>
+
+#include "ClientErrorCode.h"
+#include "MQMessageConst.h"
+#include "MessageAccessor.h"
+#include "UtilAll.h"
+
+namespace rocketmq {
+
+MQMessagePtr MessageUtil::createReplyMessage(const MQMessagePtr requestMessage,
+                                             const std::string& body) throw(MQClientException) {
+  if (requestMessage != nullptr) {
+    std::unique_ptr<MQMessage> replyMessage(new MQMessage());
+    const auto& cluster = requestMessage->getProperty(MQMessageConst::PROPERTY_CLUSTER);
+    const auto& replyTo = requestMessage->getProperty(MQMessageConst::PROPERTY_MESSAGE_REPLY_TO_CLIENT);
+    const auto& correlationId = requestMessage->getProperty(MQMessageConst::PROPERTY_CORRELATION_ID);
+    const auto& ttl = requestMessage->getProperty(MQMessageConst::PROPERTY_MESSAGE_TTL);
+    replyMessage->setBody(body);
+    if (!cluster.empty()) {
+      auto replyTopic = UtilAll::getReplyTopic(cluster);
+      replyMessage->setTopic(replyTopic);
+      MessageAccessor::putProperty(*replyMessage, MQMessageConst::PROPERTY_MESSAGE_TYPE, REPLY_MESSAGE_FLAG);
+      MessageAccessor::putProperty(*replyMessage, MQMessageConst::PROPERTY_CORRELATION_ID, correlationId);
+      MessageAccessor::putProperty(*replyMessage, MQMessageConst::PROPERTY_MESSAGE_REPLY_TO_CLIENT, replyTo);
+      MessageAccessor::putProperty(*replyMessage, MQMessageConst::PROPERTY_MESSAGE_TTL, ttl);
+
+      return replyMessage.release();
+    } else {
+      THROW_MQEXCEPTION(MQClientException, "create reply message fail, requestMessage error, property[" +
+                                               MQMessageConst::PROPERTY_CLUSTER + "] is null.",
+                        ClientErrorCode::CREATE_REPLY_MESSAGE_EXCEPTION);
+    }
+  }
+  THROW_MQEXCEPTION(MQClientException, "create reply message fail, requestMessage cannot be null.",
+                    ClientErrorCode::CREATE_REPLY_MESSAGE_EXCEPTION);
+}
+
+const std::string& MessageUtil::getReplyToClient(const MQMessagePtr msg) {
+  return msg->getProperty(MQMessageConst::PROPERTY_MESSAGE_REPLY_TO_CLIENT);
+}
+
+}  // namespace rocketmq
diff --git a/src/transport/RequestProcessor.h b/src/producer/CorrelationIdUtil.hpp
similarity index 71%
copy from src/transport/RequestProcessor.h
copy to src/producer/CorrelationIdUtil.hpp
index 68e76f3..e34bd11 100644
--- a/src/transport/RequestProcessor.h
+++ b/src/producer/CorrelationIdUtil.hpp
@@ -14,20 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __REQUEST_PROCESSOR_H__
-#define __REQUEST_PROCESSOR_H__
+#ifndef __CORRELATION_ID_UTIL_HPP__
+#define __CORRELATION_ID_UTIL_HPP__
 
-#include "RemotingCommand.h"
+#include <atomic>
+#include <string>
+
+#include "UtilAll.h"
 
 namespace rocketmq {
 
-class RequestProcessor {
+class CorrelationIdUtil {
  public:
-  virtual ~RequestProcessor() = default;
-
-  virtual RemotingCommand* processRequest(const std::string& addr, RemotingCommand* request) = 0;
+  static std::string createCorrelationId() {
+    static std::atomic<uint64_t> seqAllocator;
+    return UtilAll::to_string(seqAllocator.fetch_add(1));
+  }
 };
 
 }  // namespace rocketmq
 
-#endif  // __REQUEST_PROCESSOR_H__
+#endif  // __CORRELATION_ID_UTIL_HPP__
diff --git a/src/producer/DefaultMQProducer.cpp b/src/producer/DefaultMQProducer.cpp
index a7f11ee..ce7e1a5 100644
--- a/src/producer/DefaultMQProducer.cpp
+++ b/src/producer/DefaultMQProducer.cpp
@@ -16,24 +16,21 @@
  */
 #include "DefaultMQProducer.h"
 
+#include "DefaultMQProducerConfigImpl.h"
 #include "DefaultMQProducerImpl.h"
 #include "UtilAll.h"
 
 namespace rocketmq {
 
-DefaultMQProducerConfig::DefaultMQProducerConfig()
-    : m_maxMessageSize(1024 * 1024 * 4),
-      m_compressMsgBodyOverHowmuch(1024 * 4),
-      m_compressLevel(5),
-      m_sendMsgTimeout(3000),
-      m_retryTimes(2),
-      m_retryTimes4Async(2),
-      m_retryAnotherBrokerWhenNotStoreOK(false) {}
-
 DefaultMQProducer::DefaultMQProducer(const std::string& groupname) : DefaultMQProducer(groupname, nullptr) {}
 
-DefaultMQProducer::DefaultMQProducer(const std::string& groupname, std::shared_ptr<RPCHook> rpcHook)
-    : m_producerDelegate(nullptr) {
+DefaultMQProducer::DefaultMQProducer(const std::string& groupname, RPCHookPtr rpcHook)
+    : DefaultMQProducer(groupname, rpcHook, std::make_shared<DefaultMQProducerConfigImpl>()) {}
+
+DefaultMQProducer::DefaultMQProducer(const std::string& groupname,
+                                     RPCHookPtr rpcHook,
+                                     DefaultMQProducerConfigPtr producerConfig)
+    : DefaultMQProducerConfigProxy(producerConfig), m_producerDelegate(nullptr) {
   // set default group name
   if (groupname.empty()) {
     setGroupName(DEFAULT_PRODUCER_GROUP);
@@ -41,7 +38,7 @@ DefaultMQProducer::DefaultMQProducer(const std::string& groupname, std::shared_p
     setGroupName(groupname);
   }
 
-  m_producerDelegate = DefaultMQProducerImpl::create(this, rpcHook);
+  m_producerDelegate = DefaultMQProducerImpl::create(getRealConfig(), rpcHook);
 }
 
 DefaultMQProducer::~DefaultMQProducer() = default;
@@ -145,16 +142,21 @@ SendResult DefaultMQProducer::send(std::vector<MQMessagePtr>& msgs, const MQMess
   return m_producerDelegate->send(msgs, mq, timeout);
 }
 
+MQMessagePtr DefaultMQProducer::request(MQMessagePtr msg, long timeout) {
+  return m_producerDelegate->request(msg, timeout);
+}
+
 bool DefaultMQProducer::isSendLatencyFaultEnable() const {
-  return dynamic_cast<DefaultMQProducerImpl*>(m_producerDelegate.get())->isSendLatencyFaultEnable();
+  return std::dynamic_pointer_cast<DefaultMQProducerImpl>(m_producerDelegate)->isSendLatencyFaultEnable();
 }
 
 void DefaultMQProducer::setSendLatencyFaultEnable(bool sendLatencyFaultEnable) {
-  dynamic_cast<DefaultMQProducerImpl*>(m_producerDelegate.get())->setSendLatencyFaultEnable(sendLatencyFaultEnable);
+  std::dynamic_pointer_cast<DefaultMQProducerImpl>(m_producerDelegate)
+      ->setSendLatencyFaultEnable(sendLatencyFaultEnable);
 }
 
-void DefaultMQProducer::setRPCHook(std::shared_ptr<RPCHook> rpcHook) {
-  dynamic_cast<DefaultMQProducerImpl*>(m_producerDelegate.get())->setRPCHook(rpcHook);
+void DefaultMQProducer::setRPCHook(RPCHookPtr rpcHook) {
+  std::dynamic_pointer_cast<DefaultMQProducerImpl>(m_producerDelegate)->setRPCHook(rpcHook);
 }
 
 }  // namespace rocketmq
diff --git a/src/producer/DefaultMQProducerConfigImpl.cpp b/src/producer/DefaultMQProducerConfigImpl.cpp
new file mode 100644
index 0000000..19545a1
--- /dev/null
+++ b/src/producer/DefaultMQProducerConfigImpl.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+#include "DefaultMQProducerConfigImpl.h"
+
+namespace rocketmq {
+
+DefaultMQProducerConfigImpl::DefaultMQProducerConfigImpl()
+    : m_maxMessageSize(1024 * 1024 * 4),       // 4MB
+      m_compressMsgBodyOverHowmuch(1024 * 4),  // 4KB
+      m_compressLevel(5),
+      m_sendMsgTimeout(3000),
+      m_retryTimes(2),
+      m_retryTimes4Async(2),
+      m_retryAnotherBrokerWhenNotStoreOK(false) {}
+
+int DefaultMQProducerConfigImpl::getMaxMessageSize() const {
+  return m_maxMessageSize;
+}
+
+void DefaultMQProducerConfigImpl::setMaxMessageSize(int maxMessageSize) {
+  m_maxMessageSize = maxMessageSize;
+}
+
+int DefaultMQProducerConfigImpl::getCompressMsgBodyOverHowmuch() const {
+  return m_compressMsgBodyOverHowmuch;
+}
+
+void DefaultMQProducerConfigImpl::setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) {
+  m_compressMsgBodyOverHowmuch = compressMsgBodyOverHowmuch;
+}
+
+int DefaultMQProducerConfigImpl::getCompressLevel() const {
+  return m_compressLevel;
+}
+
+void DefaultMQProducerConfigImpl::setCompressLevel(int compressLevel) {
+  if ((compressLevel >= 0 && compressLevel <= 9) || compressLevel == -1) {
+    m_compressLevel = compressLevel;
+  }
+}
+
+int DefaultMQProducerConfigImpl::getSendMsgTimeout() const {
+  return m_sendMsgTimeout;
+}
+
+void DefaultMQProducerConfigImpl::setSendMsgTimeout(int sendMsgTimeout) {
+  m_sendMsgTimeout = sendMsgTimeout;
+}
+
+int DefaultMQProducerConfigImpl::getRetryTimes() const {
+  return m_retryTimes;
+}
+
+void DefaultMQProducerConfigImpl::setRetryTimes(int times) {
+  m_retryTimes = std::min(std::max(0, times), 15);
+}
+
+int DefaultMQProducerConfigImpl::getRetryTimes4Async() const {
+  return m_retryTimes4Async;
+}
+
+void DefaultMQProducerConfigImpl::setRetryTimes4Async(int times) {
+  m_retryTimes4Async = std::min(std::max(0, times), 15);
+}
+
+bool DefaultMQProducerConfigImpl::isRetryAnotherBrokerWhenNotStoreOK() const {
+  return m_retryAnotherBrokerWhenNotStoreOK;
+}
+
+void DefaultMQProducerConfigImpl::setRetryAnotherBrokerWhenNotStoreOK(bool retryAnotherBrokerWhenNotStoreOK) {
+  m_retryAnotherBrokerWhenNotStoreOK = retryAnotherBrokerWhenNotStoreOK;
+}
+
+}  // namespace rocketmq
diff --git a/src/producer/DefaultMQProducerConfigImpl.h b/src/producer/DefaultMQProducerConfigImpl.h
new file mode 100644
index 0000000..3ae0530
--- /dev/null
+++ b/src/producer/DefaultMQProducerConfigImpl.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+#ifndef __DEFAULT_MQ_PRODUCER_CONFIG_IMPL_H__
+#define __DEFAULT_MQ_PRODUCER_CONFIG_IMPL_H__
+
+#include "DefaultMQProducerConfig.h"
+#include "MQClientConfigImpl.h"
+
+namespace rocketmq {
+
+class DefaultMQProducerConfigImpl : virtual public DefaultMQProducerConfig, public MQClientConfigImpl {
+ public:
+  DefaultMQProducerConfigImpl();
+  virtual ~DefaultMQProducerConfigImpl() = default;
+
+  int getMaxMessageSize() const override;
+  void setMaxMessageSize(int maxMessageSize) override;
+
+  int getCompressMsgBodyOverHowmuch() const override;
+  void setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) override;
+
+  int getCompressLevel() const override;
+  void setCompressLevel(int compressLevel) override;
+
+  int getSendMsgTimeout() const override;
+  void setSendMsgTimeout(int sendMsgTimeout) override;
+
+  int getRetryTimes() const override;
+  void setRetryTimes(int times) override;
+
+  int getRetryTimes4Async() const override;
+  void setRetryTimes4Async(int times) override;
+
+  bool isRetryAnotherBrokerWhenNotStoreOK() const override;
+  void setRetryAnotherBrokerWhenNotStoreOK(bool retryAnotherBrokerWhenNotStoreOK) override;
+
+ protected:
+  int m_maxMessageSize;              // default: 4 MB
+  int m_compressMsgBodyOverHowmuch;  // default: 4 KB
+  int m_compressLevel;
+  int m_sendMsgTimeout;
+  int m_retryTimes;
+  int m_retryTimes4Async;
+  bool m_retryAnotherBrokerWhenNotStoreOK;
+};
+
+}  // namespace rocketmq
+
+#endif  // __DEFAULT_MQ_PRODUCER_CONFIG_IMPL_H__
diff --git a/src/producer/DefaultMQProducerImpl.cpp b/src/producer/DefaultMQProducerImpl.cpp
index c79b236..3baa276 100644
--- a/src/producer/DefaultMQProducerImpl.cpp
+++ b/src/producer/DefaultMQProducerImpl.cpp
@@ -23,8 +23,9 @@
 #include <signal.h>
 #endif
 
-#include "CommandHeader.h"
+#include "ClientErrorCode.h"
 #include "CommunicationMode.h"
+#include "CorrelationIdUtil.hpp"
 #include "Logging.h"
 #include "MQClientAPIImpl.h"
 #include "MQClientException.h"
@@ -36,16 +37,18 @@
 #include "MessageBatch.h"
 #include "MessageClientIDSetter.h"
 #include "MessageSysFlag.h"
+#include "RequestFutureTable.h"
 #include "TopicPublishInfo.h"
 #include "TransactionMQProducer.h"
 #include "Validators.h"
+#include "protocol/header/CommandHeader.h"
 
 namespace rocketmq {
 
-DefaultMQProducerImpl::DefaultMQProducerImpl(DefaultMQProducerConfig* config)
+DefaultMQProducerImpl::DefaultMQProducerImpl(DefaultMQProducerConfigPtr config)
     : DefaultMQProducerImpl(config, nullptr) {}
 
-DefaultMQProducerImpl::DefaultMQProducerImpl(DefaultMQProducerConfig* config, std::shared_ptr<RPCHook> rpcHook)
+DefaultMQProducerImpl::DefaultMQProducerImpl(DefaultMQProducerConfigPtr config, RPCHookPtr rpcHook)
     : MQClientImpl(config, rpcHook),
       m_producerConfig(config),
       m_mqFaultStrategy(new MQFaultStrategy()),
@@ -69,7 +72,7 @@ void DefaultMQProducerImpl::start() {
 
       m_producerConfig->changeInstanceNameToPID();
 
-      LOG_INFO_NEW("DefaultMQProducerImpl:{} start", m_producerConfig->getGroupName());
+      LOG_INFO_NEW("DefaultMQProducerImpl: {} start", m_producerConfig->getGroupName());
 
       MQClientImpl::start();
 
@@ -136,7 +139,7 @@ SendResult DefaultMQProducerImpl::send(MQMessagePtr msg, long timeout) {
     std::unique_ptr<SendResult> sendResult(sendDefaultImpl(msg, ComMode_SYNC, nullptr, timeout));
     return *sendResult;
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     throw e;
   }
 }
@@ -156,7 +159,7 @@ SendResult DefaultMQProducerImpl::send(MQMessagePtr msg, const MQMessageQueue& m
     std::unique_ptr<SendResult> sendResult(sendKernelImpl(msg, mq, ComMode_SYNC, nullptr, nullptr, timeout));
     return *sendResult;
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     throw e;
   }
 }
@@ -169,9 +172,9 @@ void DefaultMQProducerImpl::send(MQMessagePtr msg, SendCallback* sendCallback, l
   try {
     (void)sendDefaultImpl(msg, ComMode_ASYNC, sendCallback, timeout);
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     sendCallback->onException(e);
-    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(sendCallback);
     }
   } catch (std::exception& e) {
@@ -202,9 +205,9 @@ void DefaultMQProducerImpl::send(MQMessagePtr msg,
       THROW_MQEXCEPTION(MQClientException, info, e.GetError());
     }
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     sendCallback->onException(e);
-    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(sendCallback);
     }
   } catch (std::exception& e) {
@@ -246,7 +249,7 @@ SendResult DefaultMQProducerImpl::send(MQMessagePtr msg, MessageQueueSelector* s
     std::unique_ptr<SendResult> result(sendSelectImpl(msg, selector, arg, ComMode_SYNC, nullptr, timeout));
     return *result.get();
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     throw e;
   }
 }
@@ -271,9 +274,9 @@ void DefaultMQProducerImpl::send(MQMessagePtr msg,
       THROW_MQEXCEPTION(MQClientException, info, e.GetError());
     }
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("send failed, exception:{}", e.what());
     sendCallback->onException(e);
-    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_ATUO_DELETE) {
+    if (sendCallback->getSendCallbackType() == SEND_CALLBACK_TYPE_AUTO_DELETE) {
       deleteAndZero(sendCallback);
     }
   } catch (std::exception& e) {
@@ -297,7 +300,7 @@ TransactionSendResult DefaultMQProducerImpl::sendMessageInTransaction(MQMessageP
         sendMessageInTransactionImpl(msg, arg, m_producerConfig->getSendMsgTimeout()));
     return *sendResult;
   } catch (MQException& e) {
-    LOG_ERROR(e.what());
+    LOG_ERROR_NEW("sendMessageInTransaction failed, exception:{}", e.what());
     throw e;
   }
 }
@@ -328,19 +331,94 @@ MessageBatch* DefaultMQProducerImpl::batch(std::vector<MQMessagePtr>& msgs) {
   }
 
   try {
-    MessageBatch* msgBatch = MessageBatch::generateFromList(msgs);
+    std::unique_ptr<MessageBatch> msgBatch(MessageBatch::generateFromList(msgs));
     for (auto& message : msgBatch->getMessages()) {
       Validators::checkMessage(*message, m_producerConfig->getMaxMessageSize());
       MessageClientIDSetter::setUniqID(*message);
     }
     msgBatch->setBody(msgBatch->encode());
-    return msgBatch;
+    return msgBatch.release();
   } catch (std::exception& e) {
     THROW_MQEXCEPTION(MQClientException, "Failed to initiate the MessageBatch", -1);
   }
 }
 
-const MQMessageQueue& DefaultMQProducerImpl::selectOneMessageQueue(TopicPublishInfo* tpInfo,
+class RequestSendCallback : public AutoDeleteSendCallback {
+ public:
+  RequestSendCallback(std::shared_ptr<RequestResponseFuture> requestFuture) : m_requestFuture(requestFuture) {}
+
+  void onSuccess(SendResult& sendResult) override { m_requestFuture->setSendRequestOk(true); }
+
+  void onException(MQException& e) noexcept override {
+    m_requestFuture->setSendRequestOk(false);
+    m_requestFuture->putResponseMessage(nullptr);
+    m_requestFuture->setCause(std::make_exception_ptr(e));
+  }
+
+ private:
+  std::shared_ptr<RequestResponseFuture> m_requestFuture;
... 8313 lines suppressed ...