You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by yu...@apache.org on 2019/06/28 11:19:36 UTC

[rocketmq-remoting] 01/39: Import remoting module from apache/rocketmq/rocketmq5

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

yukon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-remoting.git

commit 548934acca5eaaea54402b4919d0bc86f056416a
Author: yukon <yu...@apache.org>
AuthorDate: Mon May 13 15:51:32 2019 +0800

    Import remoting module from apache/rocketmq/rocketmq5
---
 .gitignore                                         |  15 +
 README.md                                          |   3 +
 pom.xml                                            |  99 ++++
 remoting-core/remoting-api/pom.xml                 |  30 +
 .../apache/rocketmq/remoting/api/AsyncHandler.java |  34 ++
 .../rocketmq/remoting/api/ConnectionService.java   |  24 +
 .../rocketmq/remoting/api/ObjectLifecycle.java     |  29 +
 .../rocketmq/remoting/api/RemotingClient.java      |  28 +
 .../rocketmq/remoting/api/RemotingEndPoint.java    |  23 +
 .../rocketmq/remoting/api/RemotingMarshaller.java  |  27 +
 .../rocketmq/remoting/api/RemotingServer.java      |  32 +
 .../rocketmq/remoting/api/RemotingService.java     |  40 ++
 .../rocketmq/remoting/api/RequestProcessor.java    |  25 +
 .../remoting/api/buffer/ByteBufferWrapper.java     |  56 ++
 .../remoting/api/channel/ChannelEventListener.java |  28 +
 .../api/channel/ChannelHandlerContextWrapper.java  |  21 +
 .../rocketmq/remoting/api/channel/ChunkRegion.java |  54 ++
 .../remoting/api/channel/RemotingChannel.java      |  78 +++
 .../remoting/api/command/RemotingCommand.java      |  90 +++
 .../api/command/RemotingCommandFactory.java        |  24 +
 .../rocketmq/remoting/api/command/TrafficType.java |  40 ++
 .../remoting/api/compressable/Compressor.java      |  28 +
 .../api/compressable/CompressorFactory.java        |  28 +
 .../api/exception/NestedRuntimeException.java      |  97 ++++
 .../api/exception/RemoteAccessException.java       |  57 ++
 .../api/exception/RemoteCodecException.java        |  33 ++
 .../exception/RemoteConnectFailureException.java   |  49 ++
 .../api/exception/RemoteTimeoutException.java      |  70 +++
 .../remoting/api/interceptor/ExceptionContext.java |  76 +++
 .../remoting/api/interceptor/Interceptor.java      |  26 +
 .../remoting/api/interceptor/InterceptorGroup.java |  49 ++
 .../remoting/api/interceptor/RequestContext.java   |  65 +++
 .../remoting/api/interceptor/ResponseContext.java  |  73 +++
 .../rocketmq/remoting/api/protocol/Protocol.java   |  39 ++
 .../remoting/api/protocol/ProtocolFactory.java     |  30 +
 .../remoting/api/serializable/Serializer.java      |  36 ++
 .../api/serializable/SerializerFactory.java        |  28 +
 .../org/apache/rocketmq/remoting/common/Pair.java  |  44 ++
 .../rocketmq/remoting/common/TypePresentation.java |  73 +++
 remoting-core/remoting-impl/pom.xml                |  52 ++
 .../remoting/common/ChannelEventListenerGroup.java |  61 ++
 .../common/RemotingCommandFactoryMeta.java         |  49 ++
 .../rocketmq/remoting/common/ResponseResult.java   | 190 ++++++
 .../remoting/common/SemaphoreReleaseOnlyOnce.java  |  40 ++
 .../remoting/common/metrics/ChannelMetrics.java    |  27 +
 .../rocketmq/remoting/config/RemotingConfig.java   | 375 ++++++++++++
 .../rocketmq/remoting/config/TcpSocketConfig.java  |  98 ++++
 .../rocketmq/remoting/external/ThreadUtils.java    | 185 ++++++
 .../impl/buffer/NettyByteBufferWrapper.java        | 117 ++++
 .../channel/ChannelHandlerContextWrapperImpl.java  |  33 ++
 .../remoting/impl/channel/FileRegionImpl.java      |  85 +++
 .../remoting/impl/channel/NettyChannelImpl.java    |  94 +++
 .../remoting/impl/command/CodecHelper.java         | 180 ++++++
 .../impl/command/RemotingCommandFactoryImpl.java   |  53 ++
 .../remoting/impl/command/RemotingCommandImpl.java | 210 +++++++
 .../remoting/impl/command/RequestIdGenerator.java  |  34 ++
 .../remoting/impl/netty/NettyChannelEvent.java     |  55 ++
 .../remoting/impl/netty/NettyChannelEventType.java |  25 +
 .../remoting/impl/netty/NettyRemotingAbstract.java | 642 +++++++++++++++++++++
 .../remoting/impl/netty/NettyRemotingClient.java   | 499 ++++++++++++++++
 .../remoting/impl/netty/NettyRemotingServer.java   | 286 +++++++++
 .../impl/netty/RemotingBootstrapFactory.java       |  60 ++
 .../impl/netty/handler/ChannelStatistics.java      |  61 ++
 .../remoting/impl/netty/handler/Decoder.java       | 107 ++++
 .../remoting/impl/netty/handler/Encoder.java       |  89 +++
 .../impl/netty/handler/ExceptionHandler.java       |  37 ++
 .../remoting/impl/netty/handler/Http2Handler.java  | 139 +++++
 .../impl/netty/handler/ProtocolSelector.java       |  65 +++
 .../remoting/impl/protocol/Httpv2Protocol.java     |  52 ++
 .../impl/protocol/ProtocolFactoryImpl.java         |  83 +++
 .../impl/protocol/RemotingCoreProtocol.java        |  46 ++
 .../remoting/impl/protocol/WebSocketProtocol.java  |  38 ++
 .../compression/CompressorFactoryImpl.java         |  68 +++
 .../impl/protocol/compression/GZipCompressor.java  | 100 ++++
 .../impl/protocol/serializer/JsonSerializer.java   |  88 +++
 .../impl/protocol/serializer/Kryo3Serializer.java  |  90 +++
 .../protocol/serializer/MsgPackSerializer.java     |  78 +++
 .../protocol/serializer/SerializerFactoryImpl.java |  69 +++
 .../impl/protocol/serializer/ThreadSafeKryo.java   |  99 ++++
 .../rocketmq/remoting/internal/BeanUtils.java      | 210 +++++++
 .../rocketmq/remoting/internal/ByteUtils.java      | 379 ++++++++++++
 .../rocketmq/remoting/internal/ExceptionUtils.java |  80 +++
 .../rocketmq/remoting/internal/JvmUtils.java       |  94 +++
 .../rocketmq/remoting/internal/NetworkUtils.java   |  81 +++
 .../rocketmq/remoting/internal/PropertyUtils.java  |  60 ++
 .../rocketmq/remoting/internal/UIDGenerator.java   |  97 ++++
 .../org/apache/rocketmq/remoting/package-info.java |  49 ++
 style/copyright/Apache.xml                         |  24 +
 style/copyright/profiles_settings.xml              |  64 ++
 style/rmq_checkstyle.xml                           | 140 +++++
 style/rmq_codeStyle.xml                            | 143 +++++
 91 files changed, 7881 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..264f48d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*dependency-reduced-pom.xml
+.classpath
+.project
+.settings/
+target/
+devenv
+*.log*
+*.iml
+.idea/
+*.versionsBackup
+!NOTICE-BIN
+!LICENSE-BIN
+.DS_Store
+localbin
+nohup.out
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2b8325e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+## Apache RocketMQ XXX
+
+Apache RocketMQ XXX is the next generation of RocketMQ, which is extremely simple and high available.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a3f8246
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.rocketmq</groupId>
+    <artifactId>rocketmq-xxx</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <!-- Maven properties -->
+        <maven.test.skip>false</maven.test.skip>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <!-- Compiler settings properties -->
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+
+    <modules>
+        <module>remoting-core/remoting-api</module>
+        <module>remoting-core/remoting-impl</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>2.6.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>2.6.3</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>remoting-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-all</artifactId>
+                <version>4.1.26.Final</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>1.2.51</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.7.7</version>
+            </dependency>
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>1.0.13</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-lang3</artifactId>
+                <version>3.4</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jetbrains</groupId>
+                <artifactId>annotations</artifactId>
+                <version>15.0</version>
+            </dependency>
+            <dependency>
+                <groupId>com.esotericsoftware</groupId>
+                <artifactId>kryo</artifactId>
+                <version>3.0.3</version>
+            </dependency>
+            <dependency>
+                <groupId>org.msgpack</groupId>
+                <artifactId>msgpack</artifactId>
+                <version>0.6.12</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>
\ No newline at end of file
diff --git a/remoting-core/remoting-api/pom.xml b/remoting-core/remoting-api/pom.xml
new file mode 100644
index 0000000..a5d1d0b
--- /dev/null
+++ b/remoting-core/remoting-api/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>rocketmq-xxx</artifactId>
+        <groupId>org.apache.rocketmq</groupId>
+        <version>0.1.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>remoting-api</artifactId>
+
+    <properties>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/AsyncHandler.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/AsyncHandler.java
new file mode 100644
index 0000000..106431b
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/AsyncHandler.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+/**
+ * The AsyncHandler interface is implemented when wishing to receive callback notification of the completion of
+ * service invoked asynchronously.
+ *
+ * @since 1.0.0
+ */
+public interface AsyncHandler {
+    void onFailure(RemotingCommand command);
+
+    void onSuccess(RemotingCommand command);
+
+    void onTimeout(long costTimeMillis, long timeoutMillis);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ConnectionService.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ConnectionService.java
new file mode 100644
index 0000000..c42498f
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ConnectionService.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.channel.ChannelEventListener;
+
+public interface ConnectionService {
+    void registerChannelEventListener(ChannelEventListener listener);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ObjectLifecycle.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ObjectLifecycle.java
new file mode 100644
index 0000000..c4a75c8
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/ObjectLifecycle.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+public interface ObjectLifecycle {
+    @PostConstruct
+    void start();
+
+    @PreDestroy
+    void stop();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingClient.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingClient.java
new file mode 100644
index 0000000..1603af4
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingClient.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public interface RemotingClient extends RemotingService {
+    RemotingCommand invoke(String address, RemotingCommand request, long timeoutMillis);
+
+    void invokeAsync(String address, RemotingCommand request, AsyncHandler asyncHandler, long timeoutMillis);
+
+    void invokeOneWay(String address, RemotingCommand request, long timeoutMillis);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingEndPoint.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingEndPoint.java
new file mode 100644
index 0000000..2bc3edf
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingEndPoint.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+public enum RemotingEndPoint {
+    REQUEST,
+    RESPONSE
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingMarshaller.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingMarshaller.java
new file mode 100644
index 0000000..0386a03
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingMarshaller.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.protocol.ProtocolFactory;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+
+public interface RemotingMarshaller {
+    ProtocolFactory protocolFactory();
+
+    SerializerFactory serializerFactory();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingServer.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingServer.java
new file mode 100644
index 0000000..f36c83c
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingServer.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public interface RemotingServer extends RemotingService {
+    int localListenPort();
+
+    RemotingCommand invoke(RemotingChannel remotingChannel, RemotingCommand request, long timeoutMillis);
+
+    void invokeAsync(RemotingChannel remotingChannel, RemotingCommand request, AsyncHandler asyncHandler,
+        long timeoutMillis);
+
+    void invokeOneWay(RemotingChannel remotingChannel, RemotingCommand request, long timeoutMillis);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingService.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingService.java
new file mode 100644
index 0000000..2f6343c
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RemotingService.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import java.util.concurrent.ExecutorService;
+import org.apache.rocketmq.remoting.api.command.RemotingCommandFactory;
+import org.apache.rocketmq.remoting.api.interceptor.Interceptor;
+import org.apache.rocketmq.remoting.common.Pair;
+
+public interface RemotingService extends RemotingMarshaller, ConnectionService, ObjectLifecycle {
+    void registerInterceptor(Interceptor interceptor);
+
+    void registerRequestProcessor(final String requestCode, final RequestProcessor processor,
+        final ExecutorService executor);
+
+    void registerRequestProcessor(final String requestCode, final RequestProcessor processor);
+
+    void unregisterRequestProcessor(final String requestCode);
+
+    Pair<RequestProcessor, ExecutorService> processor(final String requestCode);
+
+    String remotingInstanceId();
+
+    RemotingCommandFactory commandFactory();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RequestProcessor.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RequestProcessor.java
new file mode 100644
index 0000000..cd201c2
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/RequestProcessor.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api;
+
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public interface RequestProcessor {
+    RemotingCommand processRequest(RemotingChannel channel, RemotingCommand request);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/buffer/ByteBufferWrapper.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/buffer/ByteBufferWrapper.java
new file mode 100644
index 0000000..7360c88
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/buffer/ByteBufferWrapper.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.buffer;
+
+import java.nio.ByteBuffer;
+
+public interface ByteBufferWrapper {
+    void writeByte(byte data);
+
+    void writeByte(int index, byte data);
+
+    void writeBytes(byte[] data);
+
+    void writeBytes(ByteBuffer data);
+
+    void writeInt(int data);
+
+    void writeShort(short value);
+
+    void writeLong(long id);
+
+    byte readByte();
+
+    void readBytes(byte[] dst);
+
+    void readBytes(ByteBuffer dst);
+
+    short readShort();
+
+    int readInt();
+
+    long readLong();
+
+    int readableBytes();
+
+    int readerIndex();
+
+    void setReaderIndex(int readerIndex);
+
+    void ensureCapacity(int capacity);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelEventListener.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelEventListener.java
new file mode 100644
index 0000000..0c0afcf
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.channel;
+
+public interface ChannelEventListener {
+    void onChannelConnect(final RemotingChannel channel);
+
+    void onChannelClose(final RemotingChannel channel);
+
+    void onChannelException(final RemotingChannel channel);
+
+    void onChannelIdle(final RemotingChannel channel);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelHandlerContextWrapper.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelHandlerContextWrapper.java
new file mode 100644
index 0000000..05c3b18
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChannelHandlerContextWrapper.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.remoting.api.channel;
+
+public interface ChannelHandlerContextWrapper<T> {
+    T getContext();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChunkRegion.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChunkRegion.java
new file mode 100644
index 0000000..8266ff0
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/ChunkRegion.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.channel;
+
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
+
+public interface ChunkRegion {
+    void release();
+
+    /**
+     * @return Returns the offset in the file where the transfer began.
+     */
+    long position();
+
+    /**
+     * @return Return the bytes which was transferred already
+     */
+    long transferred();
+
+    /**
+     * @return Returns the number of bytes to transfer.
+     */
+    long count();
+
+    /**
+     * Transfers the content of this file region to the specified channel.
+     *
+     * @param target the destination of the transfer
+     * @param position the relative offset of the file where the transfer begins
+     * from. For example, <tt>0</tt> will make the transfer start
+     * from {@link #position()}th byte and
+     * <tt>{@link #count()} - 1</tt> will make the last byte of the
+     * region transferred.
+     * @return the length of the transferred file region
+     * @throws IOException IOException
+     */
+    long transferTo(WritableByteChannel target, long position) throws IOException;
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/RemotingChannel.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/RemotingChannel.java
new file mode 100644
index 0000000..28cfc53
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/channel/RemotingChannel.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.channel;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public interface RemotingChannel {
+    /**
+     * Returns the local address where this {@code RemotingChannel} is bound to.  The returned
+     * {@link SocketAddress} is supposed to be down-cast into more concrete
+     * type such as {@link InetSocketAddress} to retrieve the detailed
+     * information.
+     *
+     * @return the local address of this channel.
+     * {@code null} if this channel is not bound.
+     */
+    SocketAddress localAddress();
+
+    /**
+     * Returns the remote address where this {@code RemotingChannel} is connected to.  The
+     * returned {@link SocketAddress} is supposed to be down-cast into more
+     * concrete type such as {@link InetSocketAddress} to retrieve the detailed
+     * information.
+     *
+     * @return the remote address of this channel.
+     * {@code null} if this channel is not connected.
+     */
+    SocketAddress remoteAddress();
+
+    /**
+     * Returns {@code true} if and only if the I/O thread will perform the
+     * requested write operation immediately.  Any write requests made when
+     * this method returns {@code false} are queued until the I/O thread is
+     * ready to process the queued write requests.
+     */
+    boolean isWritable();
+
+    /**
+     * Returns {@code true} if the {@code RemotingChannel} is active and so connected.
+     */
+    boolean isActive();
+
+    /**
+     * Requests to close the {@code RemotingChannel} immediately.
+     */
+    void close();
+
+    /**
+     * Writes a response {@code RemotingCommand} to remote.
+     *
+     * @param command the response command
+     */
+    void reply(RemotingCommand command);
+
+    /**
+     * Writes a response {@code ChunkRegion} to remote.
+     *
+     * @param fileRegion the response chunk file region
+     */
+    void reply(ChunkRegion fileRegion);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommand.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommand.java
new file mode 100644
index 0000000..f21a45d
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommand.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.command;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+
+public interface RemotingCommand {
+    byte protocolType();
+
+    void protocolType(byte value);
+
+    int requestID();
+
+    void requestID(int value);
+
+    byte serializerType();
+
+    void serializerType(byte value);
+
+    TrafficType trafficType();
+
+    void trafficType(TrafficType value);
+
+    String opCode();
+
+    void opCode(String value);
+
+    String remark();
+
+    void remark(String value);
+
+    Map<String, String> properties();
+
+    void properties(Map<String, String> value);
+
+    String property(String key);
+
+    void property(String key, String value);
+
+    Object parameter();
+
+    void parameter(Object value);
+
+    byte[] parameterBytes();
+
+    void parameterBytes(byte[] value);
+
+    byte[] extraPayload();
+
+    void extraPayload(byte[] value);
+
+    <T> T parameter(final SerializerFactory serializerFactory, Class<T> c);
+
+    <T> T parameter(final SerializerFactory serializerFactory, final TypePresentation<T> typePresentation);
+
+    <T> T parameter(final SerializerFactory serializerFactory, final Type type);
+
+    enum CommandFlag {
+        SUCCESS("0"),
+        ERROR("-1");
+
+        private String flag;
+
+        CommandFlag(final String flag) {
+            this.flag = flag;
+        }
+
+        public String flag() {
+            return flag;
+        }
+    }
+}
\ No newline at end of file
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommandFactory.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommandFactory.java
new file mode 100644
index 0000000..82a5c6a
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/RemotingCommandFactory.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.command;
+
+public interface RemotingCommandFactory {
+    RemotingCommand createRequest();
+
+    RemotingCommand createResponse(RemotingCommand command);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/TrafficType.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/TrafficType.java
new file mode 100644
index 0000000..efebfe7
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/command/TrafficType.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.command;
+
+public enum TrafficType {
+    REQUEST_SYNC,
+    REQUEST_ASYNC,
+    REQUEST_ONEWAY,
+    RESPONSE;
+
+    public static TrafficType parse(int index) {
+        switch (index) {
+            case 0:
+                return REQUEST_SYNC;
+            case 1:
+                return REQUEST_ASYNC;
+            case 2:
+                return REQUEST_ONEWAY;
+            case 3:
+                return RESPONSE;
+            default:
+                throw new IllegalArgumentException("Not supported " + index);
+        }
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/Compressor.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/Compressor.java
new file mode 100644
index 0000000..4688c45
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/Compressor.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.compressable;
+
+public interface Compressor {
+    String name();
+
+    byte type();
+
+    byte[] compress(final byte[] content) throws Exception;
+
+    byte[] deCompress(final byte[] content) throws Exception;
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/CompressorFactory.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/CompressorFactory.java
new file mode 100644
index 0000000..2494c78
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/compressable/CompressorFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.compressable;
+
+public interface CompressorFactory {
+    void register(Compressor compressor);
+
+    byte type(String compressionName);
+
+    Compressor get(byte type);
+
+    void clearAll();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/NestedRuntimeException.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/NestedRuntimeException.java
new file mode 100644
index 0000000..7ef01db
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/NestedRuntimeException.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.remoting.api.exception;
+
+/**
+ * Handy class for wrapping runtime {@code Exceptions} with a root cause.
+ *
+ * <p>This class is {@code abstract} to force the programmer to extend
+ * the class. {@code getMessage} will include nested exception
+ * information; {@code getRootCause} will include the innermost cause of
+ * this exception, if any; {@code printStackTrace} and other like methods will
+ * delegate to the wrapped exception, if any.
+ *
+ * @since 1.0.0
+ */
+public abstract class NestedRuntimeException extends RuntimeException {
+    private static final long serialVersionUID = -8371779880133933367L;
+
+    /**
+     * Construct a {@code NestedRuntimeException} with the specified detail message.
+     *
+     * @param msg the detail message
+     */
+    public NestedRuntimeException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Construct a {@code NestedRuntimeException} with the specified detail message
+     * and nested exception.
+     *
+     * @param msg the detail message
+     * @param cause the nested exception
+     */
+    public NestedRuntimeException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+    /**
+     * Build a message for the given base message and root cause.
+     *
+     * @param message the base message
+     * @param cause the root cause
+     * @return the full exception message
+     */
+    private static String getMessageWithCause(String message, Throwable cause) {
+        if (cause != null) {
+            StringBuilder sb = new StringBuilder();
+            if (message != null) {
+                sb.append(message).append("; ");
+            }
+            sb.append("nested exception is ").append(cause);
+            return sb.toString();
+        } else {
+            return message;
+        }
+    }
+
+    /**
+     * Return the detail message, including the message from the nested exception
+     * if there is one.
+     */
+    @Override
+    public String getMessage() {
+        return getMessageWithCause(super.getMessage(), getCause());
+    }
+
+    /**
+     * Retrieve the innermost cause of this exception, if any.
+     *
+     * @return the innermost exception, or {@code null} if none
+     */
+    public Throwable getRootCause() {
+        Throwable rootCause = null;
+        Throwable cause = getCause();
+        while (cause != null && cause != rootCause) {
+            rootCause = cause;
+            cause = cause.getCause();
+        }
+        return rootCause;
+    }
+
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteAccessException.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteAccessException.java
new file mode 100644
index 0000000..6ce6dd4
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteAccessException.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.exception;
+
+/**
+ * Generic remote access exception. A service proxy for any remoting
+ * protocol should throw this exception or subclasses of it, in order
+ * to transparently expose a plain Java business interface.
+ *
+ * <p>A client may catch RemoteAccessException if it wants to, but as
+ * remote access errors are typically unrecoverable, it will probably let
+ * such exceptions propagate to a higher level that handles them generically.
+ * In this case, the client opCode doesn't show any signs of being involved in
+ * remote access, as there aren't any remoting-specific dependencies.
+ *
+ * @since 1.0.0
+ */
+public class RemoteAccessException extends NestedRuntimeException {
+    private static final long serialVersionUID = 6280428909532427263L;
+
+    /**
+     * Constructor for RemoteAccessException with the specified detail message.
+     *
+     * @param msg the detail message
+     */
+    public RemoteAccessException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructor for RemoteAccessException with the specified detail message
+     * and nested exception.
+     *
+     * @param msg the detail message
+     * @param cause the root cause (usually from using an underlying
+     * remoting API such as RMI)
+     */
+    public RemoteAccessException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteCodecException.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteCodecException.java
new file mode 100644
index 0000000..a8b9e4e
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteCodecException.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.exception;
+
+/**
+ * @since 1.0.0
+ */
+public class RemoteCodecException extends RemoteAccessException {
+    private static final long serialVersionUID = -7597014042746200543L;
+
+    public RemoteCodecException(String msg) {
+        super(msg);
+    }
+
+    public RemoteCodecException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteConnectFailureException.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteConnectFailureException.java
new file mode 100644
index 0000000..af0a6e9
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteConnectFailureException.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.exception;
+
+/**
+ * RemoteConnectFailureException will be thrown when connection
+ * could not be established with a remote service.
+ *
+ * @since 1.0.0
+ */
+public class RemoteConnectFailureException extends RemoteAccessException {
+    private static final long serialVersionUID = -5565366231695911316L;
+
+    /**
+     * Constructor for RemoteConnectFailureException with the specified detail message
+     * and nested exception.
+     *
+     * @param msg the detail message
+     * @param cause the root cause from the remoting API in use
+     */
+    public RemoteConnectFailureException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+    /**
+     * Constructor for RemoteConnectFailureException with the specified detail message.
+     *
+     * @param msg the detail message
+     */
+    public RemoteConnectFailureException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteTimeoutException.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteTimeoutException.java
new file mode 100644
index 0000000..adfcc8d
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/exception/RemoteTimeoutException.java
@@ -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.
+ */
+package org.apache.rocketmq.remoting.api.exception;
+
+/**
+ * RemoteTimeoutException will be thrown when the execution
+ * of the target method did not complete before a configurable
+ * timeout, for example when a reply message was not received.
+ *
+ * @since 1.0.0
+ */
+public class RemoteTimeoutException extends RemoteAccessException {
+    private static final long serialVersionUID = 8710772392914461626L;
+
+    /**
+     * Constructor for RemoteTimeoutException with the specified detail message,configurable timeout.
+     *
+     * @param msg the detail message
+     * @param timeoutMillis configurable timeout
+     */
+    public RemoteTimeoutException(String msg, long timeoutMillis) {
+        this(msg, timeoutMillis, null);
+    }
+
+    /**
+     * Constructor for RemoteTimeoutException with the specified detail message,configurable timeout
+     * and nested exception..
+     *
+     * @param msg the detail message
+     * @param timeoutMillis configurable timeout
+     * @param cause Exception cause
+     */
+    public RemoteTimeoutException(String msg, long timeoutMillis, Throwable cause) {
+        super(String.format("%s, waiting for %s ms", msg, timeoutMillis), cause);
+    }
+
+    /**
+     * Constructor for RemoteTimeoutException with the specified detail message.
+     *
+     * @param msg the detail message
+     */
+    public RemoteTimeoutException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructor for RemoteTimeoutException with the specified detail message
+     * and nested exception.
+     *
+     * @param msg the detail message
+     * @param cause the root cause from the remoting API in use
+     */
+    public RemoteTimeoutException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ExceptionContext.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ExceptionContext.java
new file mode 100644
index 0000000..2452309
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ExceptionContext.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.api.interceptor;
+
+import org.apache.rocketmq.remoting.api.RemotingEndPoint;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public class ExceptionContext extends RequestContext {
+    private Throwable exception;
+    private String remark;
+
+    public ExceptionContext(RemotingEndPoint remotingEndPoint, String remoteAddr, RemotingCommand request,
+        Throwable exception, String remark) {
+        super(remotingEndPoint, remoteAddr, request);
+        this.remotingEndPoint = remotingEndPoint;
+        this.remoteAddr = remoteAddr;
+        this.request = request;
+        this.exception = exception;
+        this.remark = remark;
+    }
+
+    public RemotingEndPoint getRemotingEndPoint() {
+        return remotingEndPoint;
+    }
+
+    public void setRemotingEndPoint(RemotingEndPoint remotingEndPoint) {
+        this.remotingEndPoint = remotingEndPoint;
+    }
+
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    public void setRemoteAddr(String remoteAddr) {
+        this.remoteAddr = remoteAddr;
+    }
+
+    public RemotingCommand getRequest() {
+        return request;
+    }
+
+    public void setRequest(RemotingCommand request) {
+        this.request = request;
+    }
+
+    public Throwable getException() {
+        return exception;
+    }
+
+    public void setException(Throwable exception) {
+        this.exception = exception;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/Interceptor.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/Interceptor.java
new file mode 100644
index 0000000..62257ef
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/Interceptor.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.interceptor;
+
+public interface Interceptor {
+    void beforeRequest(final RequestContext context);
+
+    void afterResponseReceived(final ResponseContext context);
+
+    void onException(final ExceptionContext context);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/InterceptorGroup.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/InterceptorGroup.java
new file mode 100644
index 0000000..9ffc696
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/InterceptorGroup.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.interceptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InterceptorGroup {
+    private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
+
+    public void registerInterceptor(final Interceptor interceptor) {
+        if (interceptor != null) {
+            this.interceptors.add(interceptor);
+        }
+    }
+
+    public void beforeRequest(final RequestContext context) {
+        for (Interceptor interceptor : interceptors) {
+            interceptor.beforeRequest(context);
+        }
+    }
+
+    public void afterResponseReceived(final ResponseContext context) {
+        for (Interceptor interceptor : interceptors) {
+            interceptor.afterResponseReceived(context);
+        }
+    }
+
+    public void onException(final ExceptionContext context) {
+        for (Interceptor interceptor : interceptors) {
+            interceptor.onException(context);
+        }
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/RequestContext.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/RequestContext.java
new file mode 100644
index 0000000..d961556
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/RequestContext.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.api.interceptor;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.rocketmq.remoting.api.RemotingEndPoint;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public class RequestContext {
+    protected RemotingEndPoint remotingEndPoint;
+    protected String remoteAddr;
+    protected RemotingCommand request;
+
+    public RequestContext(RemotingEndPoint remotingEndPoint, String remoteAddr, RemotingCommand request) {
+        super();
+        this.remotingEndPoint = remotingEndPoint;
+        this.remoteAddr = remoteAddr;
+        this.request = request;
+    }
+
+    public RemotingEndPoint getRemotingEndPoint() {
+        return remotingEndPoint;
+    }
+
+    public void setRemotingEndPoint(RemotingEndPoint remotingEndPoint) {
+        this.remotingEndPoint = remotingEndPoint;
+    }
+
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    public void setRemoteAddr(String remoteAddr) {
+        this.remoteAddr = remoteAddr;
+    }
+
+    public RemotingCommand getRequest() {
+        return request;
+    }
+
+    public void setRequest(RemotingCommand request) {
+        this.request = request;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ResponseContext.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ResponseContext.java
new file mode 100644
index 0000000..97ec2e6
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/interceptor/ResponseContext.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.api.interceptor;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.rocketmq.remoting.api.RemotingEndPoint;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public class ResponseContext extends RequestContext {
+    private RemotingCommand response;
+
+    public ResponseContext(RemotingEndPoint remotingEndPoint, String remoteAddr, RemotingCommand request,
+        RemotingCommand response) {
+        super(remotingEndPoint, remoteAddr, request);
+        this.remotingEndPoint = remotingEndPoint;
+        this.remoteAddr = remoteAddr;
+        this.request = request;
+        this.response = response;
+    }
+
+    public RemotingEndPoint getRemotingEndPoint() {
+        return remotingEndPoint;
+    }
+
+    public void setRemotingEndPoint(RemotingEndPoint remotingEndPoint) {
+        this.remotingEndPoint = remotingEndPoint;
+    }
+
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    public void setRemoteAddr(String remoteAddr) {
+        this.remoteAddr = remoteAddr;
+    }
+
+    public RemotingCommand getRequest() {
+        return request;
+    }
+
+    public void setRequest(RemotingCommand request) {
+        this.request = request;
+    }
+
+    public RemotingCommand getResponse() {
+        return response;
+    }
+
+    public void setResponse(RemotingCommand response) {
+        this.response = response;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/Protocol.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/Protocol.java
new file mode 100644
index 0000000..5caf167
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/Protocol.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.protocol;
+
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+
+public interface Protocol {
+    /**
+     * Minimum Viable Protocol
+     */
+    String MVP = "mvp";
+    String HTTP2 = "http2";
+    String WEBSOCKET = "websocket";
+
+    byte MVP_MAGIC = 0x14;
+    byte WEBSOCKET_MAGIC = 0x15;
+    byte HTTP_2_MAGIC = 0x16;
+
+    String name();
+
+    byte type();
+
+    void assembleHandler(ChannelHandlerContextWrapper ctx);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/ProtocolFactory.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/ProtocolFactory.java
new file mode 100644
index 0000000..cf016f9
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/protocol/ProtocolFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.protocol;
+
+public interface ProtocolFactory {
+    void register(Protocol protocol);
+
+    void resetAll(Protocol protocol);
+
+    byte type(String protocolName);
+
+    Protocol get(byte type);
+
+    void clearAll();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/Serializer.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/Serializer.java
new file mode 100644
index 0000000..8ef8dcd
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/Serializer.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.serializable;
+
+import java.lang.reflect.Type;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+
+public interface Serializer {
+    String name();
+
+    byte type();
+
+    <T> T decode(final byte[] content, final Class<T> c);
+
+    <T> T decode(final byte[] content, final TypePresentation<T> typePresentation);
+
+    <T> T decode(final byte[] content, final Type type);
+
+    ByteBuffer encode(final Object object);
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/SerializerFactory.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/SerializerFactory.java
new file mode 100644
index 0000000..b47bf99
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/api/serializable/SerializerFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.api.serializable;
+
+public interface SerializerFactory {
+    void register(Serializer serialization);
+
+    byte type(String serializationName);
+
+    Serializer get(byte type);
+
+    void clearAll();
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/Pair.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/Pair.java
new file mode 100644
index 0000000..505e104
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/Pair.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+public class Pair<L, R> {
+    private L left;
+    private R right;
+
+    public Pair(L left, R right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    public L getLeft() {
+        return left;
+    }
+
+    public void setLeft(L left) {
+        this.left = left;
+    }
+
+    public R getRight() {
+        return right;
+    }
+
+    public void setRight(R right) {
+        this.right = right;
+    }
+}
diff --git a/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/TypePresentation.java b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/TypePresentation.java
new file mode 100644
index 0000000..ef3d5f8
--- /dev/null
+++ b/remoting-core/remoting-api/src/main/java/org/apache/rocketmq/remoting/common/TypePresentation.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Represents a generic type {@code T}. Java doesn't yet provide a way to
+ * represent generic types, so this class does. Forces clients to create a
+ * subclass of this class which enables retrieval the type information even at
+ * runtime.
+ *
+ * <p>For example, to create a type literal for {@code List<String>}, you can
+ * create an empty anonymous inner class:
+ *
+ * <pre>
+ * TypePresentation&lt;List&lt;String&gt;&gt; list = new TypePresentation&lt;List&lt;String&gt;&gt;() {};
+ * </pre>
+ *
+ * To create a type literal for {@code Map<String, Integer>}:
+ *
+ * <pre>
+ * TypePresentation&lt;Map&lt;String, Integer&gt;&gt; map = new TypePresentation&lt;Map&lt;String, Integer&gt;&gt;() {};
+ * </pre>
+ *
+ * This syntax cannot be used to create type literals that have wildcard
+ * parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
+ *
+ * @since 1.0.0
+ */
+public class TypePresentation<T> {
+    static ConcurrentMap<Class<?>, ConcurrentMap<Type, ConcurrentMap<Type, Type>>> classTypeCache
+        = new ConcurrentHashMap<Class<?>, ConcurrentMap<Type, ConcurrentMap<Type, Type>>>(16, 0.75f, 1);
+    protected final Type type;
+
+    /**
+     * Constructs a new type literal. Derives represented class from type
+     * parameter.
+     *
+     * <p>Clients create an empty anonymous subclass. Doing so embeds the type
+     * parameter in the anonymous class's type hierarchy so we can reconstitute it
+     * at runtime despite erasure.
+     */
+    protected TypePresentation() {
+        Type superClass = getClass().getGenericSuperclass();
+        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
+    }
+
+    /**
+     * @return underlying {@code Type} instance.
+     */
+    public Type getType() {
+        return type;
+    }
+}
diff --git a/remoting-core/remoting-impl/pom.xml b/remoting-core/remoting-impl/pom.xml
new file mode 100644
index 0000000..c8be150
--- /dev/null
+++ b/remoting-core/remoting-impl/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>rocketmq-xxx</artifactId>
+        <groupId>org.apache.rocketmq</groupId>
+        <version>0.1.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>remoting-impl</artifactId>
+
+    <properties>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>remoting-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.esotericsoftware</groupId>
+            <artifactId>kryo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.msgpack</groupId>
+            <artifactId>msgpack</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-tcnative-boringssl-static</artifactId>
+            <version>1.1.33.Fork26</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ChannelEventListenerGroup.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ChannelEventListenerGroup.java
new file mode 100644
index 0000000..8af61f7
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ChannelEventListenerGroup.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.rocketmq.remoting.api.channel.ChannelEventListener;
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+
+public class ChannelEventListenerGroup {
+    private final List<ChannelEventListener> listenerList = new ArrayList<ChannelEventListener>();
+
+    public int size() {
+        return this.listenerList.size();
+    }
+
+    public void registerChannelEventListener(final ChannelEventListener listener) {
+        if (listener != null) {
+            this.listenerList.add(listener);
+        }
+    }
+
+    public void onChannelConnect(final RemotingChannel channel) {
+        for (ChannelEventListener listener : listenerList) {
+            listener.onChannelConnect(channel);
+        }
+    }
+
+    public void onChannelClose(final RemotingChannel channel) {
+        for (ChannelEventListener listener : listenerList) {
+            listener.onChannelClose(channel);
+        }
+    }
+
+    public void onChannelException(final RemotingChannel channel) {
+        for (ChannelEventListener listener : listenerList) {
+            listener.onChannelException(channel);
+        }
+    }
+
+    public void onChannelIdle(final RemotingChannel channel) {
+        for (ChannelEventListener listener : listenerList) {
+            listener.onChannelIdle(channel);
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/RemotingCommandFactoryMeta.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/RemotingCommandFactoryMeta.java
new file mode 100644
index 0000000..d5c0aaa
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/RemotingCommandFactoryMeta.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+import org.apache.rocketmq.remoting.api.protocol.ProtocolFactory;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+import org.apache.rocketmq.remoting.impl.protocol.Httpv2Protocol;
+import org.apache.rocketmq.remoting.impl.protocol.ProtocolFactoryImpl;
+import org.apache.rocketmq.remoting.impl.protocol.serializer.MsgPackSerializer;
+import org.apache.rocketmq.remoting.impl.protocol.serializer.SerializerFactoryImpl;
+
+public class RemotingCommandFactoryMeta {
+    private final ProtocolFactory protocolFactory = new ProtocolFactoryImpl();
+    private final SerializerFactory serializerFactory = new SerializerFactoryImpl();
+    private byte protocolType = Httpv2Protocol.MVP_MAGIC;
+    private byte serializeType = MsgPackSerializer.SERIALIZER_TYPE;
+
+    public RemotingCommandFactoryMeta() {
+    }
+
+    public RemotingCommandFactoryMeta(String protocolName, String serializeName) {
+        this.protocolType = protocolFactory.type(protocolName);
+        this.serializeType = serializerFactory.type(serializeName);
+    }
+
+    public byte getSerializeType() {
+        return serializeType;
+    }
+
+    public byte getProtocolType() {
+        return protocolType;
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ResponseResult.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ResponseResult.java
new file mode 100644
index 0000000..2557cdf
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/ResponseResult.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.rocketmq.remoting.api.AsyncHandler;
+import org.apache.rocketmq.remoting.api.RemotingEndPoint;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.interceptor.ExceptionContext;
+import org.apache.rocketmq.remoting.api.interceptor.InterceptorGroup;
+import org.apache.rocketmq.remoting.api.interceptor.ResponseContext;
+
+public class ResponseResult {
+    private final long beginTimestamp = System.currentTimeMillis();
+    private final CountDownLatch countDownLatch = new CountDownLatch(1);
+    private final AtomicBoolean interceptorExecuted = new AtomicBoolean(false);
+
+    private int requestId;
+    private long timeoutMillis;
+    private AsyncHandler asyncHandler;
+
+    private volatile RemotingCommand responseCommand;
+    private volatile boolean sendRequestOK = true;
+    private volatile Throwable cause;
+    private SemaphoreReleaseOnlyOnce once;
+
+    private RemotingCommand requestCommand;
+    private InterceptorGroup interceptorGroup;
+    private String remoteAddr;
+
+    public ResponseResult(int requestId, long timeoutMillis, AsyncHandler asyncHandler, SemaphoreReleaseOnlyOnce once) {
+        this.requestId = requestId;
+        this.timeoutMillis = timeoutMillis;
+        this.asyncHandler = asyncHandler;
+        this.once = once;
+    }
+
+    public ResponseResult(int requestId, long timeoutMillis) {
+        this.requestId = requestId;
+        this.timeoutMillis = timeoutMillis;
+    }
+
+    public void executeRequestSendFailed() {
+        if (this.interceptorExecuted.compareAndSet(false, true)) {
+            try {
+                interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.REQUEST, this.remoteAddr, this.requestCommand,
+                    cause, "REQUEST_SEND_FAILED"));
+            } catch (Throwable e) {
+            }
+            //Sync call
+            if (null != asyncHandler) {
+                asyncHandler.onFailure(requestCommand);
+            }
+        }
+    }
+
+    public void executeCallbackArrived(final RemotingCommand response) {
+        if (this.interceptorExecuted.compareAndSet(false, true)) {
+            try {
+                interceptorGroup.afterResponseReceived(new ResponseContext(RemotingEndPoint.REQUEST, this.remoteAddr,
+                    this.requestCommand, response));
+            } catch (Throwable e) {
+            }
+            if (null != asyncHandler) {
+                asyncHandler.onSuccess(response);
+            }
+        }
+    }
+
+    public void onTimeout(long costTimeMillis, long timoutMillis) {
+        if (this.interceptorExecuted.compareAndSet(false, true)) {
+            try {
+                interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.REQUEST, this.remoteAddr, this.requestCommand,
+                    null, "CALLBACK_TIMEOUT"));
+            } catch (Throwable e) {
+            }
+            if (null != asyncHandler) {
+                asyncHandler.onTimeout(costTimeMillis, timoutMillis);
+            }
+        }
+    }
+
+    public void release() {
+        if (this.once != null) {
+            this.once.release();
+        }
+    }
+
+    public RemotingCommand waitResponse(final long timeoutMillis) {
+        try {
+            this.countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return this.responseCommand;
+    }
+
+    public void putResponse(final RemotingCommand responseCommand) {
+        this.responseCommand = responseCommand;
+        this.countDownLatch.countDown();
+    }
+
+    public long getBeginTimestamp() {
+        return beginTimestamp;
+    }
+
+    public boolean isSendRequestOK() {
+        return sendRequestOK;
+    }
+
+    public void setSendRequestOK(boolean sendRequestOK) {
+        this.sendRequestOK = sendRequestOK;
+    }
+
+    public long getTimeoutMillis() {
+        return timeoutMillis;
+    }
+
+    public AsyncHandler getAsyncHandler() {
+        return asyncHandler;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    public void setCause(Throwable cause) {
+        this.cause = cause;
+    }
+
+    public RemotingCommand getResponseCommand() {
+        return responseCommand;
+    }
+
+    public void setResponseCommand(RemotingCommand responseCommand) {
+        this.responseCommand = responseCommand;
+    }
+
+    public int getRequestId() {
+        return requestId;
+    }
+
+    public RemotingCommand getRequestCommand() {
+        return requestCommand;
+    }
+
+    public void setRequestCommand(RemotingCommand requestCommand) {
+        this.requestCommand = requestCommand;
+    }
+
+    public InterceptorGroup getInterceptorGroup() {
+        return interceptorGroup;
+    }
+
+    public void setInterceptorGroup(InterceptorGroup interceptorGroup) {
+        this.interceptorGroup = interceptorGroup;
+    }
+
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    public void setRemoteAddr(String remoteAddr) {
+        this.remoteAddr = remoteAddr;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java
new file mode 100644
index 0000000..1c5849b
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/SemaphoreReleaseOnlyOnce.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class SemaphoreReleaseOnlyOnce {
+    private final AtomicBoolean released = new AtomicBoolean(false);
+    private final Semaphore semaphore;
+
+    public SemaphoreReleaseOnlyOnce(Semaphore semaphore) {
+        this.semaphore = semaphore;
+    }
+
+    public void release() {
+        if (this.released.compareAndSet(false, true)) {
+            this.semaphore.release();
+        }
+    }
+
+    public Semaphore getSemaphore() {
+        return semaphore;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/metrics/ChannelMetrics.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/metrics/ChannelMetrics.java
new file mode 100755
index 0000000..db959b7
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/common/metrics/ChannelMetrics.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.common.metrics;
+
+import io.netty.channel.group.ChannelGroup;
+
+public interface ChannelMetrics {
+
+    Integer getChannelCount();
+
+    ChannelGroup getChannels();
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/RemotingConfig.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/RemotingConfig.java
new file mode 100644
index 0000000..b330041
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/RemotingConfig.java
@@ -0,0 +1,375 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.config;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+import org.apache.rocketmq.remoting.impl.protocol.compression.GZipCompressor;
+import org.apache.rocketmq.remoting.impl.protocol.serializer.MsgPackSerializer;
+
+public class RemotingConfig extends TcpSocketConfig {
+    private int connectionMaxRetries = 3;
+    private int connectionChannelReaderIdleSeconds = 0;
+    private int connectionChannelWriterIdleSeconds = 0;
+    /**
+     * IdleStateEvent will be triggered when neither read nor write was
+     * performed for the specified period of this time. Specify {@code 0} to
+     * disable
+     */
+    private int connectionChannelIdleSeconds = 120;
+    private int writeBufLowWaterMark = 32 * 10240;
+    private int writeBufHighWaterMark = 64 * 10240;
+    private int threadTaskLowWaterMark = 30000;
+    private int threadTaskHighWaterMark = 50000;
+    private int connectionRetryBackoffMillis = 3000;
+    private String protocolName = Protocol.MVP;
+    private String serializerName = MsgPackSerializer.SERIALIZER_NAME;
+    private String compressorName = GZipCompressor.COMPRESSOR_NAME;
+    private int serviceThreadBlockQueueSize = 50000;
+    private boolean clientNativeEpollEnable = false;
+    private int clientWorkerThreads = 16 + Runtime.getRuntime().availableProcessors() * 2;
+    private int clientConnectionFutureAwaitTimeoutMillis = 30000;
+    private int clientAsyncCallbackExecutorThreads = 16 + Runtime.getRuntime().availableProcessors() * 2;
+    private int clientOnewayInvokeSemaphore = 20480;
+
+    //=============Server configuration==================
+    private int clientAsyncInvokeSemaphore = 20480;
+    private boolean clientPooledBytebufAllocatorEnable = false;
+    private boolean clientCloseSocketIfTimeout = true;
+    private boolean clientShortConnectionEnable = false;
+    private long clientPublishServiceTimeout = 10000;
+    private long clientConsumerServiceTimeout = 10000;
+    private long clientInvokeServiceTimeout = 10000;
+    private int clientMaxRetryCount = 10;
+    private int clientSleepBeforeRetry = 100;
+    private int serverListenPort = 8888;
+    /**
+     * If server only listened 1 port,recommend to set the value to 1
+     */
+    private int serverAcceptorThreads = 1;
+    private int serverIoThreads = 16 + Runtime.getRuntime().availableProcessors() * 2;
+    private int serverWorkerThreads = 16 + Runtime.getRuntime().availableProcessors() * 2;
+    private int serverOnewayInvokeSemaphore = 256;
+    private int serverAsyncInvokeSemaphore = 6400;
+    private boolean serverNativeEpollEnable = false;
+    private int serverAsyncCallbackExecutorThreads = Runtime.getRuntime().availableProcessors() * 2;
+    private boolean serverPooledBytebufAllocatorEnable = true;
+    private boolean serverAuthOpenEnable = true;
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+
+    public int getConnectionMaxRetries() {
+        return connectionMaxRetries;
+    }
+
+    public void setConnectionMaxRetries(final int connectionMaxRetries) {
+        this.connectionMaxRetries = connectionMaxRetries;
+    }
+
+    public int getConnectionChannelReaderIdleSeconds() {
+        return connectionChannelReaderIdleSeconds;
+    }
+
+    public void setConnectionChannelReaderIdleSeconds(final int connectionChannelReaderIdleSeconds) {
+        this.connectionChannelReaderIdleSeconds = connectionChannelReaderIdleSeconds;
+    }
+
+    public int getConnectionChannelWriterIdleSeconds() {
+        return connectionChannelWriterIdleSeconds;
+    }
+
+    public void setConnectionChannelWriterIdleSeconds(final int connectionChannelWriterIdleSeconds) {
+        this.connectionChannelWriterIdleSeconds = connectionChannelWriterIdleSeconds;
+    }
+
+    public int getConnectionChannelIdleSeconds() {
+        return connectionChannelIdleSeconds;
+    }
+
+    public void setConnectionChannelIdleSeconds(final int connectionChannelIdleSeconds) {
+        this.connectionChannelIdleSeconds = connectionChannelIdleSeconds;
+    }
+
+    public int getWriteBufLowWaterMark() {
+        return writeBufLowWaterMark;
+    }
+
+    public void setWriteBufLowWaterMark(final int writeBufLowWaterMark) {
+        this.writeBufLowWaterMark = writeBufLowWaterMark;
+    }
+
+    public int getWriteBufHighWaterMark() {
+        return writeBufHighWaterMark;
+    }
+
+    public void setWriteBufHighWaterMark(final int writeBufHighWaterMark) {
+        this.writeBufHighWaterMark = writeBufHighWaterMark;
+    }
+
+    public int getThreadTaskLowWaterMark() {
+        return threadTaskLowWaterMark;
+    }
+
+    public void setThreadTaskLowWaterMark(final int threadTaskLowWaterMark) {
+        this.threadTaskLowWaterMark = threadTaskLowWaterMark;
+    }
+
+    public int getThreadTaskHighWaterMark() {
+        return threadTaskHighWaterMark;
+    }
+
+    public void setThreadTaskHighWaterMark(final int threadTaskHighWaterMark) {
+        this.threadTaskHighWaterMark = threadTaskHighWaterMark;
+    }
+
+    public int getConnectionRetryBackoffMillis() {
+        return connectionRetryBackoffMillis;
+    }
+
+    public void setConnectionRetryBackoffMillis(final int connectionRetryBackoffMillis) {
+        this.connectionRetryBackoffMillis = connectionRetryBackoffMillis;
+    }
+
+    public String getProtocolName() {
+        return protocolName;
+    }
+
+    public void setProtocolName(final String protocolName) {
+        this.protocolName = protocolName;
+    }
+
+    public String getSerializerName() {
+        return serializerName;
+    }
+
+    public void setSerializerName(final String serializerName) {
+        this.serializerName = serializerName;
+    }
+
+    public String getCompressorName() {
+        return compressorName;
+    }
+
+    public void setCompressorName(final String compressorName) {
+        this.compressorName = compressorName;
+    }
+
+    public int getServiceThreadBlockQueueSize() {
+        return serviceThreadBlockQueueSize;
+    }
+
+    public void setServiceThreadBlockQueueSize(final int serviceThreadBlockQueueSize) {
+        this.serviceThreadBlockQueueSize = serviceThreadBlockQueueSize;
+    }
+
+    public boolean isClientNativeEpollEnable() {
+        return clientNativeEpollEnable;
+    }
+
+    public void setClientNativeEpollEnable(final boolean clientNativeEpollEnable) {
+        this.clientNativeEpollEnable = clientNativeEpollEnable;
+    }
+
+    public int getClientWorkerThreads() {
+        return clientWorkerThreads;
+    }
+
+    public void setClientWorkerThreads(final int clientWorkerThreads) {
+        this.clientWorkerThreads = clientWorkerThreads;
+    }
+
+    public int getClientConnectionFutureAwaitTimeoutMillis() {
+        return clientConnectionFutureAwaitTimeoutMillis;
+    }
+
+    public void setClientConnectionFutureAwaitTimeoutMillis(final int clientConnectionFutureAwaitTimeoutMillis) {
+        this.clientConnectionFutureAwaitTimeoutMillis = clientConnectionFutureAwaitTimeoutMillis;
+    }
+
+    public int getClientAsyncCallbackExecutorThreads() {
+        return clientAsyncCallbackExecutorThreads;
+    }
+
+    public void setClientAsyncCallbackExecutorThreads(final int clientAsyncCallbackExecutorThreads) {
+        this.clientAsyncCallbackExecutorThreads = clientAsyncCallbackExecutorThreads;
+    }
+
+    public int getClientOnewayInvokeSemaphore() {
+        return clientOnewayInvokeSemaphore;
+    }
+
+    public void setClientOnewayInvokeSemaphore(final int clientOnewayInvokeSemaphore) {
+        this.clientOnewayInvokeSemaphore = clientOnewayInvokeSemaphore;
+    }
+
+    public int getClientAsyncInvokeSemaphore() {
+        return clientAsyncInvokeSemaphore;
+    }
+
+    public void setClientAsyncInvokeSemaphore(final int clientAsyncInvokeSemaphore) {
+        this.clientAsyncInvokeSemaphore = clientAsyncInvokeSemaphore;
+    }
+
+    public boolean isClientPooledBytebufAllocatorEnable() {
+        return clientPooledBytebufAllocatorEnable;
+    }
+
+    public void setClientPooledBytebufAllocatorEnable(final boolean clientPooledBytebufAllocatorEnable) {
+        this.clientPooledBytebufAllocatorEnable = clientPooledBytebufAllocatorEnable;
+    }
+
+    public boolean isClientCloseSocketIfTimeout() {
+        return clientCloseSocketIfTimeout;
+    }
+
+    public void setClientCloseSocketIfTimeout(final boolean clientCloseSocketIfTimeout) {
+        this.clientCloseSocketIfTimeout = clientCloseSocketIfTimeout;
+    }
+
+    public boolean isClientShortConnectionEnable() {
+        return clientShortConnectionEnable;
+    }
+
+    public void setClientShortConnectionEnable(final boolean clientShortConnectionEnable) {
+        this.clientShortConnectionEnable = clientShortConnectionEnable;
+    }
+
+    public long getClientPublishServiceTimeout() {
+        return clientPublishServiceTimeout;
+    }
+
+    public void setClientPublishServiceTimeout(final long clientPublishServiceTimeout) {
+        this.clientPublishServiceTimeout = clientPublishServiceTimeout;
+    }
+
+    public long getClientConsumerServiceTimeout() {
+        return clientConsumerServiceTimeout;
+    }
+
+    public void setClientConsumerServiceTimeout(final long clientConsumerServiceTimeout) {
+        this.clientConsumerServiceTimeout = clientConsumerServiceTimeout;
+    }
+
+    public long getClientInvokeServiceTimeout() {
+        return clientInvokeServiceTimeout;
+    }
+
+    public void setClientInvokeServiceTimeout(final long clientInvokeServiceTimeout) {
+        this.clientInvokeServiceTimeout = clientInvokeServiceTimeout;
+    }
+
+    public int getClientMaxRetryCount() {
+        return clientMaxRetryCount;
+    }
+
+    public void setClientMaxRetryCount(final int clientMaxRetryCount) {
+        this.clientMaxRetryCount = clientMaxRetryCount;
+    }
+
+    public int getClientSleepBeforeRetry() {
+        return clientSleepBeforeRetry;
+    }
+
+    public void setClientSleepBeforeRetry(final int clientSleepBeforeRetry) {
+        this.clientSleepBeforeRetry = clientSleepBeforeRetry;
+    }
+
+    public int getServerListenPort() {
+        return serverListenPort;
+    }
+
+    public void setServerListenPort(final int serverListenPort) {
+        this.serverListenPort = serverListenPort;
+    }
+
+    public int getServerAcceptorThreads() {
+        return serverAcceptorThreads;
+    }
+
+    public void setServerAcceptorThreads(final int serverAcceptorThreads) {
+        this.serverAcceptorThreads = serverAcceptorThreads;
+    }
+
+    public int getServerIoThreads() {
+        return serverIoThreads;
+    }
+
+    public void setServerIoThreads(final int serverIoThreads) {
+        this.serverIoThreads = serverIoThreads;
+    }
+
+    public int getServerWorkerThreads() {
+        return serverWorkerThreads;
+    }
+
+    public void setServerWorkerThreads(final int serverWorkerThreads) {
+        this.serverWorkerThreads = serverWorkerThreads;
+    }
+
+    public int getServerOnewayInvokeSemaphore() {
+        return serverOnewayInvokeSemaphore;
+    }
+
+    public void setServerOnewayInvokeSemaphore(final int serverOnewayInvokeSemaphore) {
+        this.serverOnewayInvokeSemaphore = serverOnewayInvokeSemaphore;
+    }
+
+    public int getServerAsyncInvokeSemaphore() {
+        return serverAsyncInvokeSemaphore;
+    }
+
+    public void setServerAsyncInvokeSemaphore(final int serverAsyncInvokeSemaphore) {
+        this.serverAsyncInvokeSemaphore = serverAsyncInvokeSemaphore;
+    }
+
+    public boolean isServerNativeEpollEnable() {
+        return serverNativeEpollEnable;
+    }
+
+    public void setServerNativeEpollEnable(final boolean serverNativeEpollEnable) {
+        this.serverNativeEpollEnable = serverNativeEpollEnable;
+    }
+
+    public int getServerAsyncCallbackExecutorThreads() {
+        return serverAsyncCallbackExecutorThreads;
+    }
+
+    public void setServerAsyncCallbackExecutorThreads(final int serverAsyncCallbackExecutorThreads) {
+        this.serverAsyncCallbackExecutorThreads = serverAsyncCallbackExecutorThreads;
+    }
+
+    public boolean isServerPooledBytebufAllocatorEnable() {
+        return serverPooledBytebufAllocatorEnable;
+    }
+
+    public void setServerPooledBytebufAllocatorEnable(final boolean serverPooledBytebufAllocatorEnable) {
+        this.serverPooledBytebufAllocatorEnable = serverPooledBytebufAllocatorEnable;
+    }
+
+    public boolean isServerAuthOpenEnable() {
+        return serverAuthOpenEnable;
+    }
+
+    public void setServerAuthOpenEnable(final boolean serverAuthOpenEnable) {
+        this.serverAuthOpenEnable = serverAuthOpenEnable;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/TcpSocketConfig.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/TcpSocketConfig.java
new file mode 100755
index 0000000..4dfcde7
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/config/TcpSocketConfig.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.config;
+
+/**
+ * TCP socket configuration
+ *
+ * @see java.net.SocketOptions
+ */
+public class TcpSocketConfig {
+    private boolean tcpSoReuseAddress;
+    private boolean tcpSoKeepAlive;
+    private boolean tcpSoNoDelay;
+    private int tcpSoSndBufSize;  // see /proc/sys/net/ipv4/tcp_rmem
+    private int tcpSoRcvBufSize;  // see /proc/sys/net/ipv4/tcp_wmem
+    private int tcpSoBacklogSize;
+    private int tcpSoLinger;
+    private int tcpSoTimeout;
+
+    public boolean isTcpSoReuseAddress() {
+        return tcpSoReuseAddress;
+    }
+
+    public void setTcpSoReuseAddress(final boolean tcpSoReuseAddress) {
+        this.tcpSoReuseAddress = tcpSoReuseAddress;
+    }
+
+    public boolean isTcpSoKeepAlive() {
+        return tcpSoKeepAlive;
+    }
+
+    public void setTcpSoKeepAlive(final boolean tcpSoKeepAlive) {
+        this.tcpSoKeepAlive = tcpSoKeepAlive;
+    }
+
+    public boolean isTcpSoNoDelay() {
+        return tcpSoNoDelay;
+    }
+
+    public void setTcpSoNoDelay(final boolean tcpSoNoDelay) {
+        this.tcpSoNoDelay = tcpSoNoDelay;
+    }
+
+    public int getTcpSoSndBufSize() {
+        return tcpSoSndBufSize;
+    }
+
+    public void setTcpSoSndBufSize(final int tcpSoSndBufSize) {
+        this.tcpSoSndBufSize = tcpSoSndBufSize;
+    }
+
+    public int getTcpSoRcvBufSize() {
+        return tcpSoRcvBufSize;
+    }
+
+    public void setTcpSoRcvBufSize(final int tcpSoRcvBufSize) {
+        this.tcpSoRcvBufSize = tcpSoRcvBufSize;
+    }
+
+    public int getTcpSoBacklogSize() {
+        return tcpSoBacklogSize;
+    }
+
+    public void setTcpSoBacklogSize(final int tcpSoBacklogSize) {
+        this.tcpSoBacklogSize = tcpSoBacklogSize;
+    }
+
+    public int getTcpSoLinger() {
+        return tcpSoLinger;
+    }
+
+    public void setTcpSoLinger(final int tcpSoLinger) {
+        this.tcpSoLinger = tcpSoLinger;
+    }
+
+    public int getTcpSoTimeout() {
+        return tcpSoTimeout;
+    }
+
+    public void setTcpSoTimeout(final int tcpSoTimeout) {
+        this.tcpSoTimeout = tcpSoTimeout;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/external/ThreadUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/external/ThreadUtils.java
new file mode 100644
index 0000000..5a50089
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/external/ThreadUtils.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.external;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ThreadUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(ThreadUtils.class);
+
+    /**
+     * A constructor to stop this class being constructed.
+     */
+    private ThreadUtils() {
+        // Unused
+
+    }
+
+    public static ExecutorService newThreadPoolExecutor(int corePoolSize,
+        int maximumPoolSize,
+        long keepAliveTime,
+        TimeUnit unit,
+        BlockingQueue<Runnable> workQueue,
+        String processName, boolean isDaemon) {
+        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, newGenericThreadFactory(processName, isDaemon));
+    }
+
+    public static ExecutorService newFixedThreadPool(int nThreads, int workQueueCapacity, String processName, boolean isDaemon) {
+        return new ThreadPoolExecutor(
+            nThreads,
+            nThreads,
+            0,
+            TimeUnit.MILLISECONDS,
+            new LinkedBlockingQueue<Runnable>(workQueueCapacity),
+            newGenericThreadFactory(processName, isDaemon));
+    }
+
+    public static ExecutorService newSingleThreadExecutor(String processName, boolean isDaemon) {
+        return Executors.newSingleThreadExecutor(newGenericThreadFactory(processName, isDaemon));
+    }
+
+    public static ScheduledExecutorService newSingleThreadScheduledExecutor(String processName, boolean isDaemon) {
+        return Executors.newSingleThreadScheduledExecutor(newGenericThreadFactory(processName, isDaemon));
+    }
+
+    public static ScheduledExecutorService newFixedThreadScheduledPool(int nThreads, String processName,
+        boolean isDaemon) {
+        return Executors.newScheduledThreadPool(nThreads, newGenericThreadFactory(processName, isDaemon));
+    }
+
+    public static ThreadFactory newGenericThreadFactory(String processName) {
+        return newGenericThreadFactory(processName, false);
+    }
+
+    public static ThreadFactory newGenericThreadFactory(String processName, int threads) {
+        return newGenericThreadFactory(processName, threads, false);
+    }
+
+    public static ThreadFactory newGenericThreadFactory(final String processName, final boolean isDaemon) {
+        return new ThreadFactory() {
+            private AtomicInteger threadIndex = new AtomicInteger(0);
+
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread thread = new Thread(r, String.format("%s_%d", processName, this.threadIndex.incrementAndGet()));
+                thread.setDaemon(isDaemon);
+                return thread;
+            }
+        };
+    }
+
+    public static ThreadFactory newGenericThreadFactory(final String processName, final int threads,
+        final boolean isDaemon) {
+        return new ThreadFactory() {
+            private AtomicInteger threadIndex = new AtomicInteger(0);
+
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread thread = new Thread(r, String.format("%s_%d_%d", processName, threads, this.threadIndex.incrementAndGet()));
+                thread.setDaemon(isDaemon);
+                return thread;
+            }
+        };
+    }
+
+    /**
+     * Create a new thread
+     *
+     * @param name The name of the thread
+     * @param runnable The work for the thread to do
+     * @param daemon Should the thread block JVM stop?
+     * @return The unstarted thread
+     */
+    public static Thread newThread(String name, Runnable runnable, boolean daemon) {
+        Thread thread = new Thread(runnable, name);
+        thread.setDaemon(daemon);
+        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+            public void uncaughtException(Thread t, Throwable e) {
+                LOG.error("Uncaught exception in thread '" + t.getName() + "':", e);
+            }
+        });
+        return thread;
+    }
+
+    /**
+     * Shutdown passed thread using isAlive and join.
+     *
+     * @param t Thread to stop
+     */
+    public static void shutdownGracefully(final Thread t) {
+        shutdownGracefully(t, 0);
+    }
+
+    /**
+     * Shutdown passed thread using isAlive and join.
+     *
+     * @param millis Pass 0 if we're to wait forever.
+     * @param t Thread to stop
+     */
+    public static void shutdownGracefully(final Thread t, final long millis) {
+        if (t == null)
+            return;
+        while (t.isAlive()) {
+            try {
+                t.interrupt();
+                t.join(millis);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    /**
+     * An implementation of the graceful stop sequence recommended by
+     * {@link ExecutorService}.
+     *
+     * @param executor executor
+     * @param timeout timeout
+     * @param timeUnit timeUnit
+     */
+    public static void shutdownGracefully(ExecutorService executor, long timeout, TimeUnit timeUnit) {
+        // Disable new tasks from being submitted.
+        executor.shutdown();
+        try {
+            // Wait a while for existing tasks to terminate.
+            if (!executor
+                .awaitTermination(timeout, timeUnit)) {
+                executor.shutdownNow();
+                // Wait a while for tasks to respond to being cancelled.
+                if (!executor.awaitTermination(timeout, timeUnit)) {
+                    LOG.warn(String.format("%s didn't terminate!", executor));
+                }
+            }
+        } catch (InterruptedException ie) {
+            // (Re-)Cancel if current thread also interrupted.
+            executor.shutdownNow();
+            // Preserve interrupt status.
+            Thread.currentThread().interrupt();
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/buffer/NettyByteBufferWrapper.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/buffer/NettyByteBufferWrapper.java
new file mode 100644
index 0000000..5a71452
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/buffer/NettyByteBufferWrapper.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.buffer;
+
+import io.netty.buffer.ByteBuf;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.api.buffer.ByteBufferWrapper;
+
+public class NettyByteBufferWrapper implements ByteBufferWrapper {
+    private final ByteBuf buffer;
+
+    public NettyByteBufferWrapper(ByteBuf buffer) {
+        this.buffer = buffer;
+    }
+
+    @Override
+    public void writeByte(byte data) {
+        buffer.writeByte(data);
+    }
+
+    @Override
+    public void writeByte(int index, byte data) {
+        buffer.writeByte(data);
+    }
+
+    @Override
+    public void writeBytes(byte[] data) {
+        buffer.writeBytes(data);
+    }
+
+    @Override
+    public void writeBytes(final ByteBuffer data) {
+        buffer.writeBytes(data);
+    }
+
+    @Override
+    public void writeShort(final short value) {
+        buffer.writeShort(value);
+    }
+
+    @Override
+    public void writeInt(int data) {
+        buffer.writeInt(data);
+    }
+
+    @Override
+    public void writeLong(long value) {
+        buffer.writeLong(value);
+    }
+
+    @Override
+    public byte readByte() {
+        return buffer.readByte();
+    }
+
+    @Override
+    public void readBytes(final ByteBuffer dst) {
+        buffer.readBytes(dst);
+    }
+
+    @Override
+    public void readBytes(byte[] dst) {
+        buffer.readBytes(dst);
+    }
+
+    @Override
+    public short readShort() {
+        return buffer.readShort();
+    }
+
+    @Override
+    public int readInt() {
+        return buffer.readInt();
+    }
+
+    @Override
+    public long readLong() {
+        return buffer.readLong();
+    }
+
+    @Override
+    public int readableBytes() {
+        return buffer.readableBytes();
+    }
+
+    @Override
+    public int readerIndex() {
+        return buffer.readerIndex();
+    }
+
+    @Override
+    public void setReaderIndex(int index) {
+        buffer.setIndex(index, buffer.writerIndex());
+    }
+
+    @Override
+    public void ensureCapacity(int capacity) {
+        buffer.capacity(capacity);
+    }
+}
+
+
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/ChannelHandlerContextWrapperImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/ChannelHandlerContextWrapperImpl.java
new file mode 100644
index 0000000..bbd33ea
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/ChannelHandlerContextWrapperImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.channel;
+
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+
+public class ChannelHandlerContextWrapperImpl<ChannelHandlerContext> implements ChannelHandlerContextWrapper {
+
+    private io.netty.channel.ChannelHandlerContext context;
+
+    public ChannelHandlerContextWrapperImpl(io.netty.channel.ChannelHandlerContext context) {
+        this.context = context;
+    }
+
+    public io.netty.channel.ChannelHandlerContext getContext() {
+        return context;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/FileRegionImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/FileRegionImpl.java
new file mode 100644
index 0000000..b90afc1
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/FileRegionImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.channel;
+
+import io.netty.channel.FileRegion;
+import io.netty.util.AbstractReferenceCounted;
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
+import org.apache.rocketmq.remoting.api.channel.ChunkRegion;
+
+public class FileRegionImpl extends AbstractReferenceCounted implements FileRegion {
+    private final ChunkRegion chunkRegion;
+
+    public FileRegionImpl(ChunkRegion chunkRegion) {
+        this.chunkRegion = chunkRegion;
+    }
+
+    @Override
+    public long position() {
+        return chunkRegion.position();
+    }
+
+    @Override
+    public long transfered() {
+        return chunkRegion.transferred();
+    }
+
+    @Override
+    public long transferred() {
+        return chunkRegion.transferred();
+    }
+
+    @Override
+    public long count() {
+        return chunkRegion.count();
+    }
+
+    @Override
+    public long transferTo(WritableByteChannel target, long position) throws IOException {
+        return chunkRegion.transferTo(target, position);
+    }
+
+    @Override
+    protected void deallocate() {
+        chunkRegion.release();
+    }
+
+    @Override
+    public FileRegion retain() {
+        super.retain();
+        return this;
+    }
+
+    @Override
+    public FileRegion retain(int increment) {
+        super.retain(increment);
+        return this;
+    }
+
+    @Override
+    public FileRegion touch() {
+        return this;
+    }
+
+    @Override
+    public FileRegion touch(Object hint) {
+        return this;
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/NettyChannelImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/NettyChannelImpl.java
new file mode 100644
index 0000000..ba4a969
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/channel/NettyChannelImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.channel;
+
+import io.netty.channel.Channel;
+import java.net.SocketAddress;
+import org.apache.rocketmq.remoting.api.channel.ChunkRegion;
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+
+public class NettyChannelImpl implements RemotingChannel {
+    private final io.netty.channel.Channel channel;
+
+    public NettyChannelImpl(Channel channel) {
+        this.channel = channel;
+    }
+
+    @Override
+    public SocketAddress localAddress() {
+        return channel.localAddress();
+    }
+
+    @Override
+    public SocketAddress remoteAddress() {
+        return channel.remoteAddress();
+    }
+
+    @Override
+    public boolean isWritable() {
+        return channel.isWritable();
+    }
+
+    @Override
+    public boolean isActive() {
+        return channel.isActive();
+    }
+
+    @Override
+    public void close() {
+        channel.close();
+    }
+
+    @Override
+    public void reply(final RemotingCommand command) {
+        channel.writeAndFlush(command);
+    }
+
+    @Override
+    public void reply(final ChunkRegion fileRegion) {
+        channel.writeAndFlush(fileRegion);
+    }
+
+    public io.netty.channel.Channel getChannel() {
+        return channel;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        final NettyChannelImpl that = (NettyChannelImpl) o;
+
+        return channel != null ? channel.equals(that.channel) : that.channel == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        return channel != null ? channel.hashCode() : 0;
+    }
+
+    @Override
+    public String toString() {
+        return "NettyChannelImpl [channel=" + channel + "]";
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/CodecHelper.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/CodecHelper.java
new file mode 100644
index 0000000..44d4fd9
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/CodecHelper.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.command;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Map.Entry;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.command.TrafficType;
+import org.apache.rocketmq.remoting.api.exception.RemoteCodecException;
+
+public class CodecHelper {
+    //ProtocolType + TotalLength + RequestId + SerializeType + TrafficType + CodeLength + RemarkLength + PropertiesSize + ParameterLength
+    public final static int MIN_PROTOCOL_LEN = 1 + 4 + 4 + 1 + 1 + 2 + 2 + 2 + 4;
+    public final static char PROPERTY_SEPARATOR = '\n';
+    public final static Charset REMOTING_CHARSET = Charset.forName("UTF-8");
+
+    public final static int CODE_MAX_LEN = 512;
+    public final static int PARAMETER_MAX_LEN = 33554432;
+    public final static int BODY_MAX_LEN = 33554432;
+    public final static int PACKET_MAX_LEN = 33554432;
+
+    public static ByteBuffer encodeHeader(final RemotingCommand command, final int parameterLength,
+        final int extraPayload) {
+        byte[] code = command.opCode().getBytes(REMOTING_CHARSET);
+        int codeLength = code.length;
+
+        byte[] remark = command.remark().getBytes(REMOTING_CHARSET);
+        int remarkLength = remark.length;
+
+        byte[][] props = null;
+        int propsLength = 0;
+        StringBuilder sb = new StringBuilder();
+        if (!command.properties().isEmpty()) {
+            props = new byte[command.properties().size()][];
+            int i = 0;
+            for (Entry<String, String> next : command.properties().entrySet()) {
+                sb.setLength(0);
+                sb.append(next.getKey());
+                sb.append(PROPERTY_SEPARATOR);
+                sb.append(next.getValue());
+
+                props[i] = sb.toString().getBytes(REMOTING_CHARSET);
+
+                propsLength += 2;
+                propsLength += props[i].length;
+                i++;
+            }
+        }
+
+        int totalLength = MIN_PROTOCOL_LEN - 1 - 4
+            + codeLength
+            + remarkLength
+            + propsLength
+            + parameterLength
+            + extraPayload;
+
+        int headerLength = 1 + 4 + totalLength - parameterLength - extraPayload;
+
+        ByteBuffer buf = ByteBuffer.allocate(headerLength);
+        buf.put(command.protocolType());
+        buf.putInt(totalLength);
+        buf.putInt(command.requestID());
+        buf.put(command.serializerType());
+        buf.put((byte) command.trafficType().ordinal());
+
+        buf.putShort((short) codeLength);
+        if (codeLength > 0) {
+            buf.put(code);
+        }
+        buf.putShort((short) remarkLength);
+        if (remarkLength > 0) {
+            buf.put(remark);
+        }
+        if (props != null) {
+            buf.putShort((short) props.length);
+            for (byte[] prop : props) {
+                buf.putShort((short) prop.length);
+                buf.put(prop);
+            }
+        } else {
+            buf.putShort((short) 0);
+        }
+
+        buf.putInt(parameterLength);
+
+        buf.flip();
+
+        return buf;
+    }
+
+    public static RemotingCommand decode(final ByteBuffer byteBuffer) {
+        RemotingCommandImpl cmd = new RemotingCommandImpl();
+        int totalLength = byteBuffer.limit();
+        cmd.requestID(byteBuffer.getInt());
+        cmd.serializerType(byteBuffer.get());
+        cmd.trafficType(TrafficType.parse(byteBuffer.get()));
+
+        {
+            short size = byteBuffer.getShort();
+            if (size > 0 && size <= CODE_MAX_LEN) {
+                byte[] bytes = new byte[size];
+                byteBuffer.get(bytes);
+                String str = new String(bytes, REMOTING_CHARSET);
+                cmd.opCode(str);
+            } else {
+                throw new RemoteCodecException(String.format("Code length: %d over max limit: %d", size, CODE_MAX_LEN));
+            }
+        }
+
+        {
+            short size = byteBuffer.getShort();
+            if (size > 0) {
+                byte[] bytes = new byte[size];
+                byteBuffer.get(bytes);
+                String str = new String(bytes, REMOTING_CHARSET);
+                cmd.remark(str);
+            }
+        }
+
+        {
+            short size = byteBuffer.getShort();
+            if (size > 0) {
+                for (int i = 0; i < size; i++) {
+                    short length = byteBuffer.getShort();
+                    if (length > 0) {
+                        byte[] bytes = new byte[length];
+                        byteBuffer.get(bytes);
+                        String str = new String(bytes, REMOTING_CHARSET);
+                        int index = str.indexOf(PROPERTY_SEPARATOR);
+                        if (index > 0) {
+                            String key = str.substring(0, index);
+                            String value = str.substring(index + 1);
+                            cmd.property(key, value);
+                        }
+                    }
+                }
+            }
+        }
+
+        {
+            int size = byteBuffer.getInt();
+            if (size > 0 && size <= PARAMETER_MAX_LEN) {
+                byte[] bytes = new byte[size];
+                byteBuffer.get(bytes);
+                cmd.parameterBytes(bytes);
+            } else if (size != 0) {
+                throw new RemoteCodecException(String.format("Parameter size: %d over max limit: %d", size, PARAMETER_MAX_LEN));
+            }
+        }
+
+        {
+            int size = totalLength - byteBuffer.position();
+            if (size > 0 && size <= BODY_MAX_LEN) {
+                byte[] bytes = new byte[size];
+                byteBuffer.get(bytes);
+                cmd.extraPayload(bytes);
+            } else if (size != 0) {
+                throw new RemoteCodecException(String.format("Body size: %d over max limit: %d", size, BODY_MAX_LEN));
+            }
+        }
+
+        return cmd;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandFactoryImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandFactoryImpl.java
new file mode 100644
index 0000000..f5d2126
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandFactoryImpl.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.command;
+
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.command.RemotingCommandFactory;
+import org.apache.rocketmq.remoting.api.command.TrafficType;
+import org.apache.rocketmq.remoting.common.RemotingCommandFactoryMeta;
+
+public class RemotingCommandFactoryImpl implements RemotingCommandFactory {
+    private RemotingCommandFactoryMeta remotingCommandFactoryMeta;
+
+    public RemotingCommandFactoryImpl() {
+        this(new RemotingCommandFactoryMeta());
+    }
+
+    public RemotingCommandFactoryImpl(final RemotingCommandFactoryMeta remotingCommandFactoryMeta) {
+        this.remotingCommandFactoryMeta = remotingCommandFactoryMeta;
+    }
+
+    @Override
+    public RemotingCommand createRequest() {
+        RemotingCommand request = new RemotingCommandImpl();
+        request.protocolType(this.remotingCommandFactoryMeta.getProtocolType());
+        request.serializerType(this.remotingCommandFactoryMeta.getSerializeType());
+        return request;
+    }
+
+    @Override
+    public RemotingCommand createResponse(final RemotingCommand command) {
+        RemotingCommand response = new RemotingCommandImpl();
+        response.requestID(command.requestID());
+        response.protocolType(command.protocolType());
+        response.serializerType(command.serializerType());
+        response.trafficType(TrafficType.RESPONSE);
+        return response;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandImpl.java
new file mode 100644
index 0000000..bcf2338
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RemotingCommandImpl.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.command;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.command.TrafficType;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+
+public class RemotingCommandImpl implements RemotingCommand {
+    public final static RequestIdGenerator REQUEST_ID_GENERATOR = RequestIdGenerator.inst;
+
+    private byte protocolType;
+    private byte serializeType;
+
+    private volatile int requestId = REQUEST_ID_GENERATOR.incrementAndGet();
+    private TrafficType trafficType = TrafficType.REQUEST_SYNC;
+    private String code = CommandFlag.SUCCESS.flag();
+    private String remark = "";
+    private Map<String, String> properties = new HashMap<String, String>();
+    private Object parameter;
+    private byte[] extraPayload;
+
+    private byte[] parameterByte;
+
+    protected RemotingCommandImpl() {
+    }
+
+    @Override
+    public byte protocolType() {
+        return this.protocolType;
+    }
+
+    @Override
+    public void protocolType(byte value) {
+        this.protocolType = value;
+    }
+
+    @Override
+    public int requestID() {
+        return requestId;
+    }
+
+    @Override
+    public void requestID(int value) {
+        this.requestId = value;
+    }
+
+    @Override
+    public byte serializerType() {
+        return this.serializeType;
+    }
+
+    @Override
+    public void serializerType(byte value) {
+        this.serializeType = value;
+    }
+
+    @Override
+    public TrafficType trafficType() {
+        return this.trafficType;
+    }
+
+    @Override
+    public void trafficType(TrafficType value) {
+        this.trafficType = value;
+    }
+
+    @Override
+    public String opCode() {
+        return this.code;
+    }
+
+    @Override
+    public void opCode(String value) {
+        this.code = value;
+    }
+
+    @Override
+    public String remark() {
+        return this.remark;
+    }
+
+    @Override
+    public void remark(String value) {
+        this.remark = value;
+    }
+
+    @Override
+    public Map<String, String> properties() {
+        return this.properties;
+    }
+
+    @Override
+    public void properties(Map<String, String> value) {
+        this.properties = value;
+    }
+
+    @Override
+    public String property(String key) {
+        return this.properties.get(key);
+    }
+
+    @Override
+    public void property(String key, String value) {
+        this.properties.put(key, value);
+    }
+
+    @Override
+    public Object parameter() {
+        return this.parameter;
+    }
+
+    @Override
+    public void parameter(Object value) {
+        this.parameter = value;
+    }
+
+    @Override
+    public byte[] parameterBytes() {
+        return this.getParameterByte();
+    }
+
+    public byte[] getParameterByte() {
+        return parameterByte;
+    }
+
+    public void setParameterByte(byte[] parameterByte) {
+        this.parameterByte = parameterByte;
+    }
+
+    @Override
+    public void parameterBytes(byte[] value) {
+        this.setParameterByte(value);
+    }
+
+    @Override
+    public byte[] extraPayload() {
+        return this.extraPayload;
+    }
+
+    @Override
+    public void extraPayload(byte[] value) {
+        this.extraPayload = value;
+    }
+
+    @Override
+    public <T> T parameter(SerializerFactory serializerFactory, Class<T> c) {
+        if (this.parameter() != null)
+            return (T) this.parameter();
+        final T decode = serializerFactory.get(this.serializerType()).decode(this.parameterBytes(), c);
+        this.parameter(decode);
+        return decode;
+    }
+
+    @Override
+    public <T> T parameter(SerializerFactory serializerFactory, TypePresentation<T> typePresentation) {
+        if (this.parameter() != null)
+            return (T) this.parameter();
+        final T decode = serializerFactory.get(this.serializerType()).decode(this.parameterBytes(), typePresentation);
+        this.parameter(decode);
+        return decode;
+    }
+
+    @Override
+    public <T> T parameter(SerializerFactory serializerFactory, Type type) {
+        if (this.parameter() != null)
+            return (T) this.parameter();
+        final T decode = serializerFactory.get(this.serializerType()).decode(this.parameterBytes(), type);
+        this.parameter(decode);
+        return decode;
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return EqualsBuilder.reflectionEquals(this, o);
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RequestIdGenerator.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RequestIdGenerator.java
new file mode 100644
index 0000000..9b85c95
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/command/RequestIdGenerator.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.command;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class RequestIdGenerator {
+    public static RequestIdGenerator inst = new RequestIdGenerator();
+
+    private AtomicInteger generator = new AtomicInteger(0);
+
+    private RequestIdGenerator() {
+
+    }
+
+    public int incrementAndGet() {
+        return generator.incrementAndGet();
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEvent.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEvent.java
new file mode 100644
index 0000000..ec9cece
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+import io.netty.channel.Channel;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class NettyChannelEvent {
+    private final Channel channel;
+    private final NettyChannelEventType type;
+    private final Throwable cause;
+
+    public NettyChannelEvent(NettyChannelEventType type, Channel channel) {
+        this(type, channel, null);
+    }
+
+    public NettyChannelEvent(NettyChannelEventType type, Channel channel, Throwable cause) {
+        this.type = type;
+        this.channel = channel;
+        this.cause = cause;
+    }
+
+    public NettyChannelEventType getType() {
+        return type;
+    }
+
+    public Channel getChannel() {
+        return channel;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEventType.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEventType.java
new file mode 100644
index 0000000..1bf2277
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyChannelEventType.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+public enum NettyChannelEventType {
+    ACTIVE,
+    INACTIVE,
+    IDLE,
+    EXCEPTION
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingAbstract.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingAbstract.java
new file mode 100644
index 0000000..82b17f4
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingAbstract.java
@@ -0,0 +1,642 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.rocketmq.remoting.api.AsyncHandler;
+import org.apache.rocketmq.remoting.api.RemotingEndPoint;
+import org.apache.rocketmq.remoting.api.RemotingService;
+import org.apache.rocketmq.remoting.api.RequestProcessor;
+import org.apache.rocketmq.remoting.api.channel.ChannelEventListener;
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.command.RemotingCommandFactory;
+import org.apache.rocketmq.remoting.api.command.TrafficType;
+import org.apache.rocketmq.remoting.api.exception.RemoteTimeoutException;
+import org.apache.rocketmq.remoting.api.interceptor.ExceptionContext;
+import org.apache.rocketmq.remoting.api.interceptor.Interceptor;
+import org.apache.rocketmq.remoting.api.interceptor.InterceptorGroup;
+import org.apache.rocketmq.remoting.api.interceptor.RequestContext;
+import org.apache.rocketmq.remoting.api.interceptor.ResponseContext;
+import org.apache.rocketmq.remoting.api.protocol.ProtocolFactory;
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+import org.apache.rocketmq.remoting.common.ChannelEventListenerGroup;
+import org.apache.rocketmq.remoting.common.Pair;
+import org.apache.rocketmq.remoting.common.RemotingCommandFactoryMeta;
+import org.apache.rocketmq.remoting.common.ResponseResult;
+import org.apache.rocketmq.remoting.common.SemaphoreReleaseOnlyOnce;
+import org.apache.rocketmq.remoting.config.RemotingConfig;
+import org.apache.rocketmq.remoting.external.ThreadUtils;
+import org.apache.rocketmq.remoting.impl.channel.NettyChannelImpl;
+import org.apache.rocketmq.remoting.impl.command.RemotingCommandFactoryImpl;
+import org.apache.rocketmq.remoting.impl.protocol.ProtocolFactoryImpl;
+import org.apache.rocketmq.remoting.impl.protocol.serializer.SerializerFactoryImpl;
+import org.apache.rocketmq.remoting.internal.UIDGenerator;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class NettyRemotingAbstract implements RemotingService {
+    protected static final Logger LOG = LoggerFactory.getLogger(NettyRemotingAbstract.class);
+    protected final ProtocolFactory protocolFactory = new ProtocolFactoryImpl();
+    protected final SerializerFactory serializerFactory = new SerializerFactoryImpl();
+    protected final ChannelEventExecutor channelEventExecutor = new ChannelEventExecutor("ChannelEventExecutor");
+    private final Semaphore semaphoreOneway;
+    private final Semaphore semaphoreAsync;
+    private final Map<Integer, ResponseResult> ackTables = new ConcurrentHashMap<Integer, ResponseResult>(256);
+    private final Map<String, Pair<RequestProcessor, ExecutorService>> processorTables = new ConcurrentHashMap<String, Pair<RequestProcessor, ExecutorService>>();
+    private final AtomicLong responseCounter = new AtomicLong(0);
+    private final RemotingCommandFactory remotingCommandFactory;
+    private final String remotingInstanceId = UIDGenerator.instance().createUID();
+
+    private final ExecutorService publicExecutor;
+    protected ScheduledExecutorService houseKeepingService = ThreadUtils.newSingleThreadScheduledExecutor("HouseKeepingService", true);
+    private InterceptorGroup interceptorGroup = new InterceptorGroup();
+    private ChannelEventListenerGroup channelEventListenerGroup = new ChannelEventListenerGroup();
+
+    NettyRemotingAbstract(RemotingConfig clientConfig) {
+        this(clientConfig, new RemotingCommandFactoryMeta());
+    }
+
+    NettyRemotingAbstract(RemotingConfig clientConfig, RemotingCommandFactoryMeta remotingCommandFactoryMeta) {
+        this.semaphoreOneway = new Semaphore(clientConfig.getClientOnewayInvokeSemaphore(), true);
+        this.semaphoreAsync = new Semaphore(clientConfig.getClientAsyncInvokeSemaphore(), true);
+        this.publicExecutor = ThreadUtils.newFixedThreadPool(
+            clientConfig.getClientAsyncCallbackExecutorThreads(),
+            10000, "Remoting-PublicExecutor", true);
+        this.remotingCommandFactory = new RemotingCommandFactoryImpl(remotingCommandFactoryMeta);
+    }
+
+    public SerializerFactory getSerializerFactory() {
+        return serializerFactory;
+    }
+
+    protected void putNettyEvent(final NettyChannelEvent event) {
+        this.channelEventExecutor.putNettyEvent(event);
+    }
+
+    protected void startUpHouseKeepingService() {
+        this.houseKeepingService.scheduleAtFixedRate(new Runnable() {
+            @Override
+            public void run() {
+                scanResponseTable();
+            }
+        }, 3000, 1000, TimeUnit.MICROSECONDS);
+    }
+
+    @Override
+    public void start() {
+        if (this.channelEventListenerGroup.size() > 0) {
+            this.channelEventExecutor.start();
+        }
+    }
+
+    @Override
+    public void stop() {
+        ThreadUtils.shutdownGracefully(publicExecutor, 2000, TimeUnit.MILLISECONDS);
+        ThreadUtils.shutdownGracefully(channelEventExecutor);
+    }
+
+    protected void processMessageReceived(ChannelHandlerContext ctx, RemotingCommand command) throws Exception {
+        if (command != null) {
+            switch (command.trafficType()) {
+                case REQUEST_ONEWAY:
+                case REQUEST_ASYNC:
+                case REQUEST_SYNC:
+                    processRequestCommand(ctx, command);
+                    break;
+                case RESPONSE:
+                    processResponseCommand(ctx, command);
+                    break;
+                default:
+                    LOG.warn("Not supported The traffic type {} !", command.trafficType());
+                    break;
+            }
+        }
+    }
+
+    public void processRequestCommand(final ChannelHandlerContext ctx, final RemotingCommand cmd) {
+        Pair<RequestProcessor, ExecutorService> processorExecutorPair = this.processorTables.get(cmd.opCode());
+
+        RemotingChannel channel = new NettyChannelImpl(ctx.channel());
+
+        Runnable run = buildProcessorTask(ctx, cmd, processorExecutorPair, channel);
+
+        try {
+            processorExecutorPair.getRight().submit(run);
+        } catch (RejectedExecutionException e) {
+            if ((System.currentTimeMillis() % 10000) == 0) {
+                LOG.warn(String.format("Request %s from %s Rejected by server executor %s !", cmd,
+                    extractRemoteAddress(ctx.channel()), processorExecutorPair.getRight().toString()));
+            }
+
+            if (cmd.trafficType() != TrafficType.REQUEST_ONEWAY) {
+                interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.RESPONSE,
+                    extractRemoteAddress(ctx.channel()), cmd, e, "FLOW_CONTROL"));
+
+                RemotingCommand response = remotingCommandFactory.createResponse(cmd);
+                response.opCode(RemotingCommand.CommandFlag.ERROR.flag());
+                response.remark("SYSTEM_BUSY");
+                writeAndFlush(ctx.channel(), response);
+            }
+        }
+    }
+
+    @NotNull
+    private Runnable buildProcessorTask(final ChannelHandlerContext ctx, final RemotingCommand cmd,
+        final Pair<RequestProcessor, ExecutorService> processorExecutorPair, final RemotingChannel channel) {
+        return new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    interceptorGroup.beforeRequest(new RequestContext(RemotingEndPoint.RESPONSE,
+                        extractRemoteAddress(ctx.channel()), cmd));
+
+                    RemotingCommand response = processorExecutorPair.getLeft().processRequest(channel, cmd);
+
+                    interceptorGroup.afterResponseReceived(new ResponseContext(RemotingEndPoint.RESPONSE,
+                        extractRemoteAddress(ctx.channel()), cmd, response));
+
+                    handleResponse(response, cmd, ctx);
+                } catch (Throwable e) {
+                    LOG.error(String.format("Process request %s error !", cmd.toString()), e);
+
+                    handleException(e, cmd, ctx);
+                }
+            }
+        };
+    }
+
+    private void handleException(Throwable e, RemotingCommand cmd, ChannelHandlerContext ctx) {
+        if (cmd.trafficType() != TrafficType.REQUEST_ONEWAY) {
+            //FiXME Exception interceptor can not throw exception
+            interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.RESPONSE, extractRemoteAddress(ctx.channel()), cmd, e, ""));
+            RemotingCommand response = remotingCommandFactory.createResponse(cmd);
+            response.opCode(RemotingCommand.CommandFlag.ERROR.flag());
+            response.remark(serializeException(cmd.serializerType(), e));
+            response.property("Exception", e.getClass().getName());
+            ctx.writeAndFlush(response);
+        }
+    }
+
+    private String serializeException(byte serializeType, Throwable exception) {
+        final Serializer serialization = getSerializerFactory().get(serializeType);
+        return serialization.encode(exception).toString();
+    }
+
+    private void handleResponse(RemotingCommand response, RemotingCommand cmd, ChannelHandlerContext ctx) {
+        if (cmd.trafficType() != TrafficType.REQUEST_ONEWAY) {
+            if (response != null) {
+                try {
+                    writeAndFlush(ctx.channel(), response);
+                } catch (Throwable e) {
+                    LOG.error(String.format("Process request %s success, but transfer response %s failed !",
+                        cmd.toString(), response.toString()), e);
+                }
+            }
+        }
+
+    }
+
+    private void processResponseCommand(ChannelHandlerContext ctx, RemotingCommand cmd) {
+        final ResponseResult responseResult = ackTables.get(cmd.requestID());
+        if (responseResult != null) {
+            responseResult.setResponseCommand(cmd);
+            responseResult.release();
+
+            long time = System.currentTimeMillis();
+            ackTables.remove(cmd.requestID());
+            if (responseCounter.incrementAndGet() % 5000 == 0) {
+                LOG.info("REQUEST ID:{}, cost time:{}, ackTables.size:{}", cmd.requestID(), time - responseResult.getBeginTimestamp(),
+                    ackTables.size());
+            }
+            if (responseResult.getAsyncHandler() != null) {
+                boolean sameThread = false;
+                ExecutorService executor = this.getCallbackExecutor();
+                if (executor != null) {
+                    try {
+                        executor.submit(new Runnable() {
+                            @Override
+                            public void run() {
+                                try {
+                                    responseResult.executeCallbackArrived(responseResult.getResponseCommand());
+                                } catch (Throwable e) {
+                                    LOG.warn("Execute callback error !", e);
+                                }
+                            }
+                        });
+                    } catch (RejectedExecutionException e) {
+                        sameThread = true;
+                        LOG.warn("Execute submit error !", e);
+                    }
+                } else {
+                    sameThread = true;
+                }
+
+                if (sameThread) {
+                    try {
+                        responseResult.executeCallbackArrived(responseResult.getResponseCommand());
+                    } catch (Throwable e) {
+                        LOG.warn("Execute callback in response thread error !", e);
+                    }
+                }
+            } else {
+                responseResult.putResponse(cmd);
+            }
+        } else {
+            LOG.warn("request {} from {} has not matched response !", cmd, extractRemoteAddress(ctx.channel()));
+        }
+    }
+
+    private void writeAndFlush(final Channel channel, final Object msg, final ChannelFutureListener listener) {
+        channel.writeAndFlush(msg).addListener(listener);
+    }
+
+    private void writeAndFlush(final Channel channel, final Object msg) {
+        channel.writeAndFlush(msg);
+    }
+
+    public ExecutorService getCallbackExecutor() {
+        return this.publicExecutor;
+    }
+
+    void scanResponseTable() {
+        /*
+        Iterator<Map.Entry<Integer, ResponseResult>> iterator = this.ackTables.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<Integer, ResponseResult> next = iterator.next();
+            ResponseResult result = next.getValue();
+
+            if ((result.getBeginTimestamp() + result.getTimeoutMillis()) <= System.currentTimeMillis()) {
+                iterator.remove();
+                try {
+                    long timeoutMillis = result.getTimeoutMillis();
+                    long costTimeMillis = System.currentTimeMillis() - result.getBeginTimestamp();
+                    result.onTimeout(timeoutMillis, costTimeMillis);
+                    LOG.error("scan response table command {} failed", result.getRequestId());
+                } catch (Throwable e) {
+                    LOG.warn("Error occurred when execute timeout callback !", e);
+                } finally {
+                    result.release();
+                    LOG.warn("Removed timeout request {} ", result);
+                }
+            }
+        }
+        */
+    }
+
+    public RemotingCommand invokeWithInterceptor(final Channel channel, final RemotingCommand request,
+        long timeoutMillis) {
+        request.trafficType(TrafficType.REQUEST_SYNC);
+
+        final String remoteAddr = extractRemoteAddress(channel);
+
+        //FIXME try catch here
+        this.interceptorGroup.beforeRequest(new RequestContext(RemotingEndPoint.REQUEST, remoteAddr, request));
+
+        RemotingCommand responseCommand = this.invoke0(remoteAddr, channel, request, timeoutMillis);
+
+        this.interceptorGroup.afterResponseReceived(new ResponseContext(RemotingEndPoint.REQUEST,
+            extractRemoteAddress(channel), request, responseCommand));
+
+        return responseCommand;
+    }
+
+    private RemotingCommand invoke0(final String remoteAddr, final Channel channel, final RemotingCommand request,
+        final long timeoutMillis) {
+        try {
+            final int opaque = request.requestID();
+            final ResponseResult responseResult = new ResponseResult(opaque, timeoutMillis);
+            responseResult.setRequestCommand(request);
+            //FIXME one interceptor for all case ?
+            responseResult.setInterceptorGroup(this.interceptorGroup);
+            responseResult.setRemoteAddr(remoteAddr);
+
+            this.ackTables.put(opaque, responseResult);
+
+            ChannelFutureListener listener = new ChannelFutureListener() {
+                @Override
+                public void operationComplete(ChannelFuture f) throws Exception {
+                    if (f.isSuccess()) {
+                        responseResult.setSendRequestOK(true);
+                        return;
+                    } else {
+                        responseResult.setSendRequestOK(false);
+
+                        ackTables.remove(opaque);
+                        responseResult.setCause(f.cause());
+                        responseResult.putResponse(null);
+
+                        LOG.warn("Send request command to {} failed !", remoteAddr);
+                    }
+                }
+            };
+
+            this.writeAndFlush(channel, request, listener);
+
+            RemotingCommand responseCommand = responseResult.waitResponse(timeoutMillis);
+
+            if (null == responseCommand) {
+                if (responseResult.isSendRequestOK()) {
+                    throw new RemoteTimeoutException(extractRemoteAddress(channel), timeoutMillis, responseResult.getCause());
+                }
+                /*
+                else {
+                    throw new RemoteAccessException(extractRemoteAddress(channel), responseResult.getCause());
+                }*/
+            }
+
+            return responseCommand;
+        } finally {
+            this.ackTables.remove(request.requestID());
+        }
+    }
+
+    public void invokeAsyncWithInterceptor(final Channel channel, final RemotingCommand request,
+        final AsyncHandler invokeCallback, long timeoutMillis) {
+        request.trafficType(TrafficType.REQUEST_ASYNC);
+
+        final String remoteAddr = extractRemoteAddress(channel);
+
+        this.interceptorGroup.beforeRequest(new RequestContext(RemotingEndPoint.REQUEST, remoteAddr, request));
+
+        Exception exception = null;
+
+        try {
+            this.invokeAsync0(remoteAddr, channel, request, timeoutMillis, invokeCallback);
+        } catch (InterruptedException e) {
+            exception = e;
+        } finally {
+            if (null != exception) {
+                try {
+                    this.interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.REQUEST, extractRemoteAddress(channel), request, exception, "REMOTING_EXCEPTION"));
+                } catch (Throwable e) {
+                    LOG.warn("onException ", e);
+                }
+            }
+        }
+    }
+
+    private void invokeAsync0(final String remoteAddr, final Channel channel, final RemotingCommand request,
+        final long timeoutMillis, final AsyncHandler invokeCallback) throws InterruptedException {
+        boolean acquired = this.semaphoreAsync.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS);
+        if (acquired) {
+            final int requestID = request.requestID();
+
+            SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreAsync);
+
+            final ResponseResult responseResult = new ResponseResult(request.requestID(), timeoutMillis, invokeCallback, once);
+            responseResult.setRequestCommand(request);
+            responseResult.setInterceptorGroup(this.interceptorGroup);
+            responseResult.setRemoteAddr(remoteAddr);
+
+            this.ackTables.put(request.requestID(), responseResult);
+            try {
+                ChannelFutureListener listener = new ChannelFutureListener() {
+                    @Override
+                    public void operationComplete(ChannelFuture f) throws Exception {
+                        responseResult.setSendRequestOK(f.isSuccess());
+                        if (f.isSuccess()) {
+                            return;
+                        }
+
+                        responseResult.putResponse(null);
+                        ackTables.remove(requestID);
+                        try {
+                            responseResult.executeRequestSendFailed();
+                        } catch (Throwable e) {
+                            LOG.warn("Execute callback error !", e);
+                        } finally {
+                            responseResult.release();
+                        }
+
+                        LOG.warn("Send request command to channel  failed.", remoteAddr);
+                    }
+                };
+
+                this.writeAndFlush(channel, request, listener);
+            } catch (Exception e) {
+                responseResult.release();
+                LOG.error("Send request command to channel " + channel + " error !", e);
+            }
+        } else {
+            String info = String.format("Semaphore tryAcquire %d ms timeout for request %s ,waiting thread nums: %d,availablePermits: %d",
+                timeoutMillis, request.toString(), semaphoreAsync.getQueueLength(), this.semaphoreAsync.availablePermits());
+            LOG.error(info);
+            throw new RemoteTimeoutException(info);
+        }
+    }
+
+    public void invokeOnewayWithInterceptor(final Channel channel, final RemotingCommand request, long timeoutMillis) {
+        request.trafficType(TrafficType.REQUEST_ONEWAY);
+
+        this.interceptorGroup.beforeRequest(new RequestContext(RemotingEndPoint.REQUEST, extractRemoteAddress(channel), request));
+
+        Exception exception = null;
+
+        try {
+            this.invokeOneway0(channel, request, timeoutMillis);
+        } catch (InterruptedException e) {
+            exception = e;
+        } finally {
+            if (null != exception) {
+                try {
+                    this.interceptorGroup.onException(new ExceptionContext(RemotingEndPoint.REQUEST, extractRemoteAddress(channel), request, exception, "REMOTING_EXCEPTION"));
+                } catch (Throwable e) {
+                    LOG.warn("onException ", e);
+                }
+            }
+        }
+    }
+
+    private void invokeOneway0(final Channel channel, final RemotingCommand request,
+        final long timeoutMillis) throws InterruptedException {
+        boolean acquired = this.semaphoreOneway.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS);
+        if (acquired) {
+            final SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreOneway);
+            try {
+                final SocketAddress socketAddress = channel.remoteAddress();
+
+                ChannelFutureListener listener = new ChannelFutureListener() {
+                    @Override
+                    public void operationComplete(ChannelFuture f) throws Exception {
+                        once.release();
+                        if (!f.isSuccess()) {
+                            LOG.warn("Send request command to channel {} failed !", socketAddress);
+                        }
+                    }
+                };
+
+                this.writeAndFlush(channel, request, listener);
+            } catch (Exception e) {
+                once.release();
+                LOG.error("Send request command to channel " + channel + " error !", e);
+            }
+        } else {
+            String info = String.format("Semaphore tryAcquire %d ms timeout for request %s ,waiting thread nums: %d,availablePermits: %d",
+                timeoutMillis, request.toString(), semaphoreAsync.getQueueLength(), this.semaphoreAsync.availablePermits());
+            LOG.error(info);
+            throw new RemoteTimeoutException(info);
+        }
+    }
+
+    public String getRemotingInstanceId() {
+        return remotingInstanceId;
+    }
+
+    @Override
+    public ProtocolFactory protocolFactory() {
+        return this.protocolFactory;
+    }
+
+    @Override
+    public SerializerFactory serializerFactory() {
+        return this.serializerFactory;
+    }
+
+    @Override
+    public RemotingCommandFactory commandFactory() {
+        return this.remotingCommandFactory;
+    }
+
+    @Override
+    public void registerRequestProcessor(String requestCode, RequestProcessor processor, ExecutorService executor) {
+        Pair<RequestProcessor, ExecutorService> pair = new Pair<RequestProcessor, ExecutorService>(processor, executor);
+        if (!this.processorTables.containsKey(requestCode)) {
+            this.processorTables.put(requestCode, pair);
+        }
+    }
+
+    @Override
+    public void registerRequestProcessor(String requestCode, RequestProcessor processor) {
+        this.registerRequestProcessor(requestCode, processor, publicExecutor);
+    }
+
+    @Override
+    public void unregisterRequestProcessor(String requestCode) {
+        this.processorTables.remove(requestCode);
+    }
+
+    @Override
+    public String remotingInstanceId() {
+        return this.getRemotingInstanceId();
+    }
+
+    @Override
+    public void registerInterceptor(Interceptor interceptor) {
+        this.interceptorGroup.registerInterceptor(interceptor);
+    }
+
+    @Override
+    public void registerChannelEventListener(ChannelEventListener listener) {
+        this.channelEventListenerGroup.registerChannelEventListener(listener);
+    }
+
+    @Override
+    public Pair<RequestProcessor, ExecutorService> processor(String requestCode) {
+        return processorTables.get(requestCode);
+    }
+
+    protected String extractRemoteAddress(Channel channel) {
+        return ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
+    }
+
+    class ChannelEventExecutor extends Thread {
+        private final static int MAX_SIZE = 10000;
+        private final LinkedBlockingQueue<NettyChannelEvent> eventQueue = new LinkedBlockingQueue<NettyChannelEvent>();
+        private String name;
+
+        public ChannelEventExecutor(String nettyEventExector) {
+            super(nettyEventExector);
+            this.name = nettyEventExector;
+        }
+        //private final AtomicBoolean isStopped = new AtomicBoolean(true);
+
+        public void putNettyEvent(final NettyChannelEvent event) {
+            if (this.eventQueue.size() <= MAX_SIZE) {
+                this.eventQueue.add(event);
+            } else {
+                LOG.warn("event queue size[{}] enough, so drop this event {}", this.eventQueue.size(), event.toString());
+            }
+        }
+
+        @Override
+        public void run() {
+            LOG.info(this.name + " service started");
+
+            ChannelEventListenerGroup listener = NettyRemotingAbstract.this.channelEventListenerGroup;
+
+            while (true) {
+                try {
+                    NettyChannelEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS);
+                    if (event != null && listener != null) {
+                        RemotingChannel channel = new NettyChannelImpl(event.getChannel());
+
+                        LOG.warn("Channel Event, {}", event);
+
+                        switch (event.getType()) {
+                            case IDLE:
+                                listener.onChannelIdle(channel);
+                                break;
+                            case INACTIVE:
+                                listener.onChannelClose(channel);
+                                break;
+                            case ACTIVE:
+                                listener.onChannelConnect(channel);
+                                break;
+                            case EXCEPTION:
+                                listener.onChannelException(channel);
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                } catch (Exception e) {
+                    LOG.error("error", e);
+                    break;
+                }
+            }
+        }
+
+    }
+
+    protected class EventDispatcher extends SimpleChannelInboundHandler<RemotingCommand> {
+
+        @Override
+        protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception {
+            processMessageReceived(ctx, msg);
+        }
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingClient.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingClient.java
new file mode 100644
index 0000000..7481574
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingClient.java
@@ -0,0 +1,499 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPromise;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.WriteBufferWaterMark;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http2.Http2SecurityUtil;
+import io.netty.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.SupportedCipherSuiteFilter;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.concurrent.DefaultEventExecutorGroup;
+import io.netty.util.concurrent.EventExecutorGroup;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.net.ssl.SSLException;
+import org.apache.rocketmq.remoting.api.AsyncHandler;
+import org.apache.rocketmq.remoting.api.RemotingClient;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.command.TrafficType;
+import org.apache.rocketmq.remoting.api.exception.RemoteConnectFailureException;
+import org.apache.rocketmq.remoting.api.exception.RemoteTimeoutException;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+import org.apache.rocketmq.remoting.common.RemotingCommandFactoryMeta;
+import org.apache.rocketmq.remoting.config.RemotingConfig;
+import org.apache.rocketmq.remoting.external.ThreadUtils;
+import org.apache.rocketmq.remoting.impl.netty.handler.Decoder;
+import org.apache.rocketmq.remoting.impl.netty.handler.Encoder;
+import org.apache.rocketmq.remoting.impl.netty.handler.ExceptionHandler;
+import org.apache.rocketmq.remoting.impl.netty.handler.Http2Handler;
+import org.apache.rocketmq.remoting.internal.JvmUtils;
+
+public class NettyRemotingClient extends NettyRemotingAbstract implements RemotingClient {
+    private static final long LOCK_TIMEOUT_MILLIS = 3000;
+    private final Bootstrap clientBootstrap = new Bootstrap();
+    private final EventLoopGroup ioGroup;
+    private final Class<? extends SocketChannel> socketChannelClass;
+
+    private final RemotingConfig clientConfig;
+
+    private final ConcurrentHashMap<String, ChannelWrapper> channelTables = new ConcurrentHashMap<String, ChannelWrapper>();
+    private final Lock lockChannelTables = new ReentrantLock();
+    private EventExecutorGroup workerGroup;
+    private SslContext sslContext;
+
+    NettyRemotingClient(final RemotingConfig clientConfig) {
+        super(clientConfig, new RemotingCommandFactoryMeta(clientConfig.getProtocolName(), clientConfig.getSerializerName()));
+        this.clientConfig = clientConfig;
+
+        if (JvmUtils.isLinux() && this.clientConfig.isClientNativeEpollEnable()) {
+            this.ioGroup = new EpollEventLoopGroup(clientConfig.getClientWorkerThreads(), ThreadUtils.newGenericThreadFactory("NettyClientEpollIoThreads",
+                clientConfig.getClientWorkerThreads()));
+            socketChannelClass = EpollSocketChannel.class;
+        } else {
+            this.ioGroup = new NioEventLoopGroup(clientConfig.getClientWorkerThreads(), ThreadUtils.newGenericThreadFactory("NettyClientNioIoThreads",
+                clientConfig.getClientWorkerThreads()));
+            socketChannelClass = NioSocketChannel.class;
+        }
+
+        this.workerGroup = new DefaultEventExecutorGroup(clientConfig.getClientWorkerThreads(),
+            ThreadUtils.newGenericThreadFactory("NettyClientWorkerThreads", clientConfig.getClientWorkerThreads()));
+
+        if (Protocol.HTTP2.equals(clientConfig.getProtocolName())) {
+            buildSslContext();
+        }
+    }
+
+    private void applyOptions(Bootstrap bootstrap) {
+        if (null != clientConfig) {
+            if (clientConfig.getTcpSoLinger() > 0) {
+                bootstrap.option(ChannelOption.SO_LINGER, clientConfig.getTcpSoLinger());
+            }
+
+            if (clientConfig.getTcpSoSndBufSize() > 0) {
+                bootstrap.option(ChannelOption.SO_SNDBUF, clientConfig.getTcpSoSndBufSize());
+            }
+            if (clientConfig.getTcpSoRcvBufSize() > 0) {
+                bootstrap.option(ChannelOption.SO_RCVBUF, clientConfig.getTcpSoRcvBufSize());
+            }
+
+            bootstrap.option(ChannelOption.SO_REUSEADDR, clientConfig.isTcpSoReuseAddress()).
+                option(ChannelOption.SO_KEEPALIVE, clientConfig.isTcpSoKeepAlive()).
+                option(ChannelOption.TCP_NODELAY, clientConfig.isTcpSoNoDelay()).
+                option(ChannelOption.CONNECT_TIMEOUT_MILLIS, clientConfig.getTcpSoTimeout()).
+                option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(clientConfig.getWriteBufLowWaterMark(),
+                    clientConfig.getWriteBufHighWaterMark()));
+        }
+    }
+
+    @Override
+    public void start() {
+        super.start();
+
+        this.clientBootstrap.group(this.ioGroup).channel(socketChannelClass)
+            .handler(new ChannelInitializer<SocketChannel>() {
+                @Override
+                public void initChannel(SocketChannel ch) throws Exception {
+                    if (Protocol.HTTP2.equals(clientConfig.getProtocolName())) {
+                        ch.pipeline().addFirst(sslContext.newHandler(ch.alloc()), Http2Handler.newHandler(false));
+                    }
+                    ch.pipeline().addLast(workerGroup, new Decoder(), new Encoder(), new IdleStateHandler(clientConfig.getConnectionChannelReaderIdleSeconds(),
+                            clientConfig.getConnectionChannelWriterIdleSeconds(), clientConfig.getConnectionChannelIdleSeconds()),
+                        new ClientConnectionHandler(), new EventDispatcher(), new ExceptionHandler());
+                }
+            });
+
+        applyOptions(clientBootstrap);
+
+        startUpHouseKeepingService();
+    }
+
+    private void buildSslContext() {
+        SslProvider provider = OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK;
+        try {
+            sslContext = SslContextBuilder.forClient()
+                .sslProvider(provider)
+                    /* NOTE: the cipher filter may not include all ciphers required by the HTTP/2 specification.
+                     * Please refer to the HTTP/2 specification for cipher requirements. */
+                .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)
+                .trustManager(InsecureTrustManagerFactory.INSTANCE)
+                .build();
+        } catch (SSLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void stop() {
+        // try {
+        ThreadUtils.shutdownGracefully(houseKeepingService, 3000, TimeUnit.MILLISECONDS);
+
+        for (ChannelWrapper cw : this.channelTables.values()) {
+            this.closeChannel(null, cw.getChannel());
+        }
+
+        this.channelTables.clear();
+
+        this.ioGroup.shutdownGracefully();
+
+        ThreadUtils.shutdownGracefully(channelEventExecutor);
+
+        this.workerGroup.shutdownGracefully();
+        /*
+        } catch (Exception e) {
+            LOG.error("RemotingClient stopped error !", e);
+        }
+        */
+
+        super.stop();
+    }
+
+    private void closeChannel(final String addr, final Channel channel) {
+        if (null == channel)
+            return;
+
+        final String addrRemote = null == addr ? extractRemoteAddress(channel) : addr;
+        try {
+            if (this.lockChannelTables.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+                try {
+                    boolean removeItemFromTable = true;
+                    ChannelWrapper prevCW = this.channelTables.get(addrRemote);
+                    //Workaround for null
+                    if (null == prevCW) {
+                        return;
+                    }
+
+                    LOG.info("Begin to close the remote address {} channel {}", addrRemote, prevCW);
+
+                    if (prevCW.getChannel() != channel) {
+                        LOG.info("Channel {} has been closed,this is a new channel.", prevCW.getChannel(), channel);
+                        removeItemFromTable = false;
+                    }
+
+                    if (removeItemFromTable) {
+                        this.channelTables.remove(addrRemote);
+                        LOG.info("Channel {} has been removed !", addrRemote);
+                    }
+
+                    channel.close().addListener(new ChannelFutureListener() {
+                        @Override
+                        public void operationComplete(ChannelFuture future) throws Exception {
+                            LOG.warn("Close channel {} {}", channel, future.isSuccess());
+                        }
+                    });
+                } catch (Exception e) {
+                    LOG.error("Close channel error !", e);
+                } finally {
+                    this.lockChannelTables.unlock();
+                }
+            } else {
+                LOG.warn("Can not lock channel table in {} ms", LOCK_TIMEOUT_MILLIS);
+            }
+        } catch (InterruptedException e) {
+            LOG.error("Close channel error !", e);
+        }
+    }
+
+    private Channel createIfAbsent(final String addr) {
+        ChannelWrapper cw = this.channelTables.get(addr);
+        if (cw != null && cw.isActive()) {
+            return cw.getChannel();
+        }
+        return this.createChannel(addr);
+    }
+
+    //FIXME need test to verify
+    private Channel createChannel(final String addr) {
+        ChannelWrapper cw = null;
+        try {
+            if (this.lockChannelTables.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+                try {
+                    boolean createNewConnection;
+                    cw = this.channelTables.get(addr);
+                    if (cw != null) {
+                        if (cw.isActive()) {
+                            return cw.getChannel();
+                        } else if (!cw.getChannelFuture().isDone()) {
+                            createNewConnection = false;
+                        } else {
+                            this.channelTables.remove(addr);
+                            createNewConnection = true;
+                        }
+                    } else {
+                        createNewConnection = true;
+                    }
+
+                    if (createNewConnection) {
+                        String[] s = addr.split(":");
+                        SocketAddress socketAddress = new InetSocketAddress(s[0], Integer.valueOf(s[1]));
+                        ChannelFuture channelFuture = this.clientBootstrap.connect(socketAddress);
+                        LOG.info("createChannel: begin to connect remote host[{}] asynchronously", addr);
+                        cw = new ChannelWrapper(channelFuture);
+                        this.channelTables.put(addr, cw);
+                    }
+                } catch (Exception e) {
+                    LOG.error("createChannel: create channel exception", e);
+                } finally {
+                    this.lockChannelTables.unlock();
+                }
+            } else {
+                LOG.warn("createChannel: try to lock channel table, but timeout, {}ms", LOCK_TIMEOUT_MILLIS);
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        if (cw != null) {
+            ChannelFuture channelFuture = cw.getChannelFuture();
+            if (channelFuture.awaitUninterruptibly(this.clientConfig.getClientConnectionFutureAwaitTimeoutMillis())) {
+                if (cw.isActive()) {
+                    LOG.info("createChannel: connect remote host[{}] success, {}", addr, channelFuture.toString());
+                    return cw.getChannel();
+                } else {
+                    LOG.warn("createChannel: connect remote host[" + addr + "] failed, and destroy the channel" + channelFuture.toString(), channelFuture.cause());
+                    this.closeChannel(addr, cw.getChannel());
+                }
+            } else {
+                LOG.warn("createChannel: connect remote host[{}] timeout {}ms, {}, and destroy the channel", addr, this.clientConfig.getClientConnectionFutureAwaitTimeoutMillis(),
+                    channelFuture.toString());
+                this.closeChannel(addr, cw.getChannel());
+            }
+        }
+        return null;
+    }
+
+    private void closeChannel(final Channel channel) {
+        if (null == channel)
+            return;
+
+        try {
+            if (this.lockChannelTables.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
+                try {
+                    boolean removeItemFromTable = true;
+                    ChannelWrapper prevCW = null;
+                    String addrRemote = null;
+
+                    for (Map.Entry<String, ChannelWrapper> entry : channelTables.entrySet()) {
+                        ChannelWrapper prev = entry.getValue();
+                        if (prev.getChannel() != null) {
+                            if (prev.getChannel() == channel) {
+                                prevCW = prev;
+                                addrRemote = entry.getKey();
+                                break;
+                            }
+                        }
+                    }
+
+                    if (null == prevCW) {
+                        LOG.info("eventCloseChannel: the channel[{}] has been removed from the channel table before", addrRemote);
+                        removeItemFromTable = false;
+                    }
+
+                    if (removeItemFromTable) {
+                        this.channelTables.remove(addrRemote);
+                        LOG.info("closeChannel: the channel[{}] was removed from channel table", addrRemote);
+                        //RemotingHelper.closeChannel(channel);
+                    }
+                } catch (Exception e) {
+                    LOG.error("closeChannel: close the channel exception", e);
+                } finally {
+                    this.lockChannelTables.unlock();
+                }
+            } else {
+                LOG.warn("closeChannel: try to lock channel table, but timeout, {}ms", LOCK_TIMEOUT_MILLIS);
+            }
+        } catch (InterruptedException e) {
+            LOG.error("closeChannel exception", e);
+        }
+    }
+
+    @Override
+    public RemotingCommand invoke(final String address, final RemotingCommand request, final long timeoutMillis) {
+        request.trafficType(TrafficType.REQUEST_SYNC);
+
+        Channel channel = this.createIfAbsent(address);
+        if (channel != null && channel.isActive()) {
+            try {
+                return this.invokeWithInterceptor(channel, request, timeoutMillis);
+
+            } catch (RemoteTimeoutException e) {
+                if (this.clientConfig.isClientCloseSocketIfTimeout()) {
+                    LOG.warn("invoke: timeout, so close the socket {} ms, {}", timeoutMillis, address);
+                    this.closeChannel(address, channel);
+                }
+
+                LOG.warn("invoke: wait response timeout<{}ms> exception, so close the channel[{}]", timeoutMillis, address);
+                throw e;
+            } finally {
+                /*
+                if (this.clientConfig.isClientShortConnectionEnable()) {
+                    this.closeChannel(addr, channel);
+                }
+                */
+            }
+        } else {
+            this.closeChannel(address, channel);
+            throw new RemoteConnectFailureException(address);
+        }
+
+    }
+
+    @Override
+    public void invokeAsync(final String address, final RemotingCommand request, final AsyncHandler asyncHandler,
+        final long timeoutMillis) {
+
+        final Channel channel = this.createIfAbsent(address);
+        if (channel != null && channel.isActive()) {
+            // We support Netty's channel-level backpressure thereby respecting slow receivers on the other side.
+            if (!channel.isWritable()) {
+                // Note: It's up to the layer above a transport to decide whether or not to requeue a canceled write.
+                LOG.warn("Channel statistics - bytesBeforeUnwritable:{},bytesBeforeWritable:{}", channel.bytesBeforeUnwritable(), channel.bytesBeforeWritable());
+            }
+            this.invokeAsyncWithInterceptor(channel, request, asyncHandler, timeoutMillis);
+        } else {
+            this.closeChannel(address, channel);
+        }
+    }
+
+    @Override
+    public void invokeOneWay(final String address, final RemotingCommand request, final long timeoutMillis) {
+        final Channel channel = this.createIfAbsent(address);
+        if (channel != null && channel.isActive()) {
+            if (!channel.isWritable()) {
+                //if (this.clientConfig.isSocketFlowControl()) {
+                LOG.warn("Channel statistics - bytesBeforeUnwritable:{},bytesBeforeWritable:{}", channel.bytesBeforeUnwritable(), channel.bytesBeforeWritable());
+                //throw new ServiceInvocationFailureException(String.format("Channel[%s] is not writable now", channel.toString()));
+            }
+            this.invokeOnewayWithInterceptor(channel, request, timeoutMillis);
+        } else {
+            this.closeChannel(address, channel);
+        }
+    }
+
+    private class ChannelWrapper {
+        private final ChannelFuture channelFuture;
+
+        ChannelWrapper(ChannelFuture channelFuture) {
+            this.channelFuture = channelFuture;
+        }
+
+        boolean isActive() {
+            return this.channelFuture.channel() != null && this.channelFuture.channel().isActive();
+        }
+
+        boolean isWriteable() {
+            return this.channelFuture.channel().isWritable();
+        }
+
+        private Channel getChannel() {
+            return this.channelFuture.channel();
+        }
+
+        ChannelFuture getChannelFuture() {
+            return channelFuture;
+        }
+    }
+
+    private class ClientConnectionHandler extends ChannelDuplexHandler {
+
+        @Override
+        public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
+            LOG.warn("Channel {} channelWritabilityChanged event triggered - bytesBeforeUnwritable:{},bytesBeforeWritable:{}", ctx.channel(),
+                ctx.channel().bytesBeforeUnwritable(), ctx.channel().bytesBeforeWritable());
+        }
+
+        @Override
+        public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress,
+            ChannelPromise promise)
+            throws Exception {
+            LOG.info("Connected from {} to {}.", localAddress, remoteAddress);
+            super.connect(ctx, remoteAddress, localAddress, promise);
+
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.ACTIVE, ctx.channel()));
+        }
+
+        @Override
+        public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+            LOG.info("Remote address {} disconnect channel {}.", ctx.channel().remoteAddress(), ctx.channel());
+
+            closeChannel(ctx.channel());
+
+            super.disconnect(ctx, promise);
+
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.INACTIVE, ctx.channel()));
+        }
+
+        @Override
+        public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+            LOG.info("Remote address {} close channel {}.", ctx.channel().remoteAddress(), ctx.channel());
+
+            closeChannel(ctx.channel());
+
+            super.close(ctx, promise);
+
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.INACTIVE, ctx.channel()));
+        }
+
+        @Override
+        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+            if (evt instanceof IdleStateEvent) {
+                IdleStateEvent event = (IdleStateEvent) evt;
+                if (event.state().equals(IdleState.ALL_IDLE)) {
+                    LOG.info("Close channel {} because of idle event {} ", ctx.channel(), event);
+                    closeChannel(ctx.channel());
+                    putNettyEvent(new NettyChannelEvent(NettyChannelEventType.IDLE, ctx.channel()));
+                }
+            }
+
+            ctx.fireUserEventTriggered(evt);
+        }
+
+        @Override
+        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+            LOG.info("Close channel {} because of error {} ", ctx.channel(), cause);
+
+            closeChannel(ctx.channel());
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.EXCEPTION, ctx.channel()));
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingServer.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingServer.java
new file mode 100644
index 0000000..d875f95
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/NettyRemotingServer.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.http2.Http2SecurityUtil;
+import io.netty.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.SupportedCipherSuiteFilter;
+import io.netty.handler.ssl.util.SelfSignedCertificate;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.concurrent.DefaultEventExecutorGroup;
+import io.netty.util.concurrent.EventExecutorGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+import org.apache.rocketmq.remoting.api.AsyncHandler;
+import org.apache.rocketmq.remoting.api.RemotingServer;
+import org.apache.rocketmq.remoting.api.channel.RemotingChannel;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.config.RemotingConfig;
+import org.apache.rocketmq.remoting.external.ThreadUtils;
+import org.apache.rocketmq.remoting.impl.channel.NettyChannelImpl;
+import org.apache.rocketmq.remoting.impl.netty.handler.ChannelStatistics;
+import org.apache.rocketmq.remoting.impl.netty.handler.ProtocolSelector;
+import org.apache.rocketmq.remoting.internal.JvmUtils;
+
+public class NettyRemotingServer extends NettyRemotingAbstract implements RemotingServer {
+    private final RemotingConfig serverConfig;
+
+    private final ServerBootstrap serverBootstrap;
+    private final EventLoopGroup bossGroup;
+    private final EventLoopGroup ioGroup;
+    private EventExecutorGroup workerGroup;
+    private Class<? extends ServerSocketChannel> socketChannelClass;
+
+    private int port;
+    private SslContext sslContext;
+
+    NettyRemotingServer(final RemotingConfig serverConfig) {
+        super(serverConfig);
+
+        this.serverBootstrap = new ServerBootstrap();
+        this.serverConfig = serverConfig;
+
+        if (JvmUtils.isLinux() && this.serverConfig.isServerNativeEpollEnable()) {
+            this.ioGroup = new EpollEventLoopGroup(serverConfig.getServerIoThreads(), ThreadUtils.newGenericThreadFactory("NettyEpollIoThreads",
+                serverConfig.getServerIoThreads()));
+
+            this.bossGroup = new EpollEventLoopGroup(serverConfig.getServerAcceptorThreads(), ThreadUtils.newGenericThreadFactory("NettyBossThreads",
+                serverConfig.getServerAcceptorThreads()));
+
+            this.socketChannelClass = EpollServerSocketChannel.class;
+        } else {
+            this.bossGroup = new NioEventLoopGroup(serverConfig.getServerAcceptorThreads(), ThreadUtils.newGenericThreadFactory("NettyBossThreads",
+                serverConfig.getServerAcceptorThreads()));
+
+            this.ioGroup = new NioEventLoopGroup(serverConfig.getServerIoThreads(), ThreadUtils.newGenericThreadFactory("NettyNioIoThreads",
+                serverConfig.getServerIoThreads()));
+
+            this.socketChannelClass = NioServerSocketChannel.class;
+        }
+
+        this.workerGroup = new DefaultEventExecutorGroup(serverConfig.getServerWorkerThreads(),
+            ThreadUtils.newGenericThreadFactory("NettyWorkerThreads", serverConfig.getServerWorkerThreads()));
+
+        buildHttp2SslContext();
+    }
+
+    private void buildHttp2SslContext() {
+        try {
+            SslProvider provider = OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK;
+            SelfSignedCertificate ssc;
+            //NOTE: the cipher filter may not include all ciphers required by the HTTP/2 specification.
+            //Please refer to the HTTP/2 specification for cipher requirements.
+            ssc = new SelfSignedCertificate();
+            sslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
+                .sslProvider(provider)
+                .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE).build();
+        } catch (Exception e) {
+            LOG.error("Can not build SSL context !", e);
+        }
+    }
+
+    private void applyOptions(ServerBootstrap bootstrap) {
+        //option() is for the NioServerSocketChannel that accepts incoming connections.
+        //childOption() is for the Channels accepted by the parent ServerChannel, which is NioServerSocketChannel in this case
+        if (null != serverConfig) {
+            if (serverConfig.getTcpSoBacklogSize() > 0) {
+                bootstrap.option(ChannelOption.SO_BACKLOG, serverConfig.getTcpSoBacklogSize());
+            }
+
+            if (serverConfig.getTcpSoLinger() > 0) {
+                bootstrap.option(ChannelOption.SO_LINGER, serverConfig.getTcpSoLinger());
+            }
+
+            if (serverConfig.getTcpSoSndBufSize() > 0) {
+                bootstrap.childOption(ChannelOption.SO_SNDBUF, serverConfig.getTcpSoSndBufSize());
+            }
+            if (serverConfig.getTcpSoRcvBufSize() > 0) {
+                bootstrap.childOption(ChannelOption.SO_RCVBUF, serverConfig.getTcpSoRcvBufSize());
+            }
+
+            bootstrap.option(ChannelOption.SO_REUSEADDR, serverConfig.isTcpSoReuseAddress()).
+                childOption(ChannelOption.SO_KEEPALIVE, serverConfig.isTcpSoKeepAlive()).
+                childOption(ChannelOption.TCP_NODELAY, serverConfig.isTcpSoNoDelay()).
+                option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serverConfig.getTcpSoTimeout());
+        }
+
+        if (serverConfig.isServerPooledBytebufAllocatorEnable()) {
+            bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
+        }
+    }
+
+    @Override
+    public void start() {
+        super.start();
+
+        final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
+        this.serverBootstrap.group(this.bossGroup, this.ioGroup).
+            channel(socketChannelClass).childHandler(new ChannelInitializer<SocketChannel>() {
+            @Override
+            public void initChannel(SocketChannel ch) throws Exception {
+                channels.add(ch);
+
+                ChannelPipeline cp = ch.pipeline();
+
+                cp.addLast(ChannelStatistics.NAME, new ChannelStatistics(channels));
+
+                cp.addFirst(ProtocolSelector.NAME, new ProtocolSelector(sslContext));
+                cp.addLast(workerGroup, new IdleStateHandler(serverConfig.getConnectionChannelReaderIdleSeconds(),
+                        serverConfig.getConnectionChannelWriterIdleSeconds(),
+                        serverConfig.getConnectionChannelIdleSeconds()),
+                    new ServerConnectionHandler(),
+                    new EventDispatcher());
+            }
+        });
+
+        applyOptions(serverBootstrap);
+
+        ChannelFuture channelFuture = this.serverBootstrap.bind(this.serverConfig.getServerListenPort()).syncUninterruptibly();
+        this.port = ((InetSocketAddress) channelFuture.channel().localAddress()).getPort();
+
+        startUpHouseKeepingService();
+    }
+
+    @Override
+    public void stop() {
+        try {
+
+            ThreadUtils.shutdownGracefully(houseKeepingService, 3000, TimeUnit.MILLISECONDS);
+
+            ThreadUtils.shutdownGracefully(channelEventExecutor);
+
+            this.bossGroup.shutdownGracefully().syncUninterruptibly();
+
+            this.ioGroup.shutdownGracefully().syncUninterruptibly();
+
+            this.workerGroup.shutdownGracefully().syncUninterruptibly();
+        } catch (Exception e) {
+            LOG.error("RemotingServer stopped error !", e);
+        }
+
+        super.stop();
+    }
+
+    @Override
+    public int localListenPort() {
+        return this.port;
+    }
+
+    @Override
+    public RemotingCommand invoke(final RemotingChannel remotingChannel, final RemotingCommand request,
+        final long timeoutMillis) {
+        return invokeWithInterceptor(((NettyChannelImpl) remotingChannel).getChannel(), request, timeoutMillis);
+    }
+
+    @Override
+    public void invokeAsync(final RemotingChannel remotingChannel, final RemotingCommand request,
+        final AsyncHandler asyncHandler,
+        final long timeoutMillis) {
+        invokeAsyncWithInterceptor(((NettyChannelImpl) remotingChannel).getChannel(), request, asyncHandler, timeoutMillis);
+    }
+
+    @Override
+    public void invokeOneWay(final RemotingChannel remotingChannel, final RemotingCommand request,
+        final long timeoutMillis) {
+        invokeOnewayWithInterceptor(((NettyChannelImpl) remotingChannel).getChannel(), request, timeoutMillis);
+    }
+
+    private class ServerConnectionHandler extends ChannelDuplexHandler {
+        @Override
+        public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
+            LOG.warn("Channel {} channelWritabilityChanged event triggered - bytesBeforeUnwritable:{},bytesBeforeWritable:{}", ctx.channel(),
+                ctx.channel().bytesBeforeUnwritable(), ctx.channel().bytesBeforeWritable());
+        }
+
+        @Override
+        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+            super.channelRegistered(ctx);
+        }
+
+        @Override
+        public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+            super.channelUnregistered(ctx);
+        }
+
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) throws Exception {
+            super.channelActive(ctx);
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.ACTIVE, ctx.channel()));
+        }
+
+        @Override
+        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+            super.channelInactive(ctx);
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.INACTIVE, ctx.channel()));
+        }
+
+        @Override
+        public void userEventTriggered(final ChannelHandlerContext ctx, Object evt) throws Exception {
+            if (evt instanceof IdleStateEvent) {
+                final IdleStateEvent event = (IdleStateEvent) evt;
+                if (event.state().equals(IdleState.ALL_IDLE)) {
+                    ctx.channel().close().addListener(new ChannelFutureListener() {
+                        @Override
+                        public void operationComplete(ChannelFuture future) throws Exception {
+                            LOG.warn("Close channel {} because of event {},result is {}", ctx.channel(), event, future.isSuccess());
+                        }
+                    });
+
+                    putNettyEvent(new NettyChannelEvent(NettyChannelEventType.IDLE, ctx.channel()));
+                }
+            }
+            ctx.fireUserEventTriggered(evt);
+        }
+
+        @Override
+        public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
+            putNettyEvent(new NettyChannelEvent(NettyChannelEventType.EXCEPTION, ctx.channel(), cause));
+
+            ctx.channel().close().addListener(new ChannelFutureListener() {
+                @Override
+                public void operationComplete(ChannelFuture future) throws Exception {
+                    LOG.warn("Close channel {} because of error {},result is {}", ctx.channel(), cause, future.isSuccess());
+                }
+            });
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/RemotingBootstrapFactory.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/RemotingBootstrapFactory.java
new file mode 100644
index 0000000..4dd502c
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/RemotingBootstrapFactory.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty;
+
+import java.util.Properties;
+import org.apache.rocketmq.remoting.api.RemotingClient;
+import org.apache.rocketmq.remoting.config.RemotingConfig;
+import org.apache.rocketmq.remoting.internal.BeanUtils;
+import org.apache.rocketmq.remoting.internal.PropertyUtils;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Remoting Bootstrap entrance.
+ */
+public final class RemotingBootstrapFactory {
+    public static RemotingClient createRemotingClient(@NotNull final String fileName) {
+        Properties prop = PropertyUtils.loadProps(fileName);
+        RemotingConfig config = BeanUtils.populate(prop, RemotingConfig.class);
+        return new NettyRemotingClient(config);
+    }
+
+    public static RemotingClient createRemotingClient(@NotNull final RemotingConfig config) {
+        return new NettyRemotingClient(config);
+    }
+
+    public static RemotingClient createRemotingClient(@NotNull final Properties properties) {
+        RemotingConfig config = BeanUtils.populate(properties, RemotingConfig.class);
+        return new NettyRemotingClient(config);
+    }
+
+    public static NettyRemotingServer createRemotingServer(@NotNull final String fileName) {
+        Properties prop = PropertyUtils.loadProps(fileName);
+        RemotingConfig config = BeanUtils.populate(prop, RemotingConfig.class);
+        return new NettyRemotingServer(config);
+    }
+
+    public static NettyRemotingServer createRemotingServer(@NotNull final Properties properties) {
+        RemotingConfig config = BeanUtils.populate(properties, RemotingConfig.class);
+        return new NettyRemotingServer(config);
+    }
+
+    public static NettyRemotingServer createRemotingServer(@NotNull final RemotingConfig config) {
+        return new NettyRemotingServer(config);
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ChannelStatistics.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ChannelStatistics.java
new file mode 100755
index 0000000..ff0f9c9
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ChannelStatistics.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.group.ChannelGroup;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.rocketmq.remoting.common.metrics.ChannelMetrics;
+
+public class ChannelStatistics extends ChannelDuplexHandler implements ChannelMetrics {
+    public static final String NAME = ChannelStatistics.class.getSimpleName();
+    private final AtomicInteger channelCount = new AtomicInteger(0);
+    private final ChannelGroup allChannels;
+
+    public ChannelStatistics(ChannelGroup allChannels) {
+        this.allChannels = allChannels;
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        // connect
+        channelCount.incrementAndGet();
+        allChannels.add(ctx.channel());
+        super.channelActive(ctx);
+    }
+
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+        // disconnect
+        channelCount.decrementAndGet();
+        allChannels.remove(ctx.channel());
+        super.channelInactive(ctx);
+    }
+
+    @Override
+    public Integer getChannelCount() {
+        return channelCount.get();
+    }
+
+    @Override
+    public ChannelGroup getChannels() {
+        return allChannels;
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Decoder.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Decoder.java
new file mode 100644
index 0000000..ec1d69d
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Decoder.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.apache.rocketmq.remoting.api.buffer.ByteBufferWrapper;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.exception.RemoteCodecException;
+import org.apache.rocketmq.remoting.impl.buffer.NettyByteBufferWrapper;
+import org.apache.rocketmq.remoting.impl.command.CodecHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Decoder extends ByteToMessageDecoder {
+    private static final Logger LOG = LoggerFactory.getLogger(Decoder.class);
+
+    public Decoder() {
+    }
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        if (!in.isReadable()) {
+            return;
+        }
+
+        NettyByteBufferWrapper wrapper = new NettyByteBufferWrapper(in);
+
+        Object msg = this.decode(ctx, wrapper);
+        if (msg != null) {
+            out.add(msg);
+        }
+    }
+
+    private Object decode(final ChannelHandlerContext ctx, ByteBufferWrapper wrapper) throws Exception {
+        int originReaderIndex = wrapper.readerIndex();
+
+        byte type = wrapper.readByte();
+        try {
+            RemotingCommand cmd = decode(wrapper, originReaderIndex);
+            if (cmd != null) {
+                cmd.protocolType(type);
+            }
+            return cmd;
+        } catch (final RemoteCodecException e) {
+            LOG.warn("Decode error {}, close the channel {}", e.getMessage(), ctx.channel());
+            ctx.channel().close().addListener(new ChannelFutureListener() {
+                @Override
+                public void operationComplete(ChannelFuture future) throws Exception {
+                    LOG.warn("Close channel {} because of error {},result is {}", ctx.channel(), e, future.isSuccess());
+                }
+            });
+        }
+        return null;
+    }
+
+    public RemotingCommand decode(final ByteBufferWrapper wrapper, final int originReaderIndex) {
+        // Full message isn't available yet, return nothing for now
+        if (wrapper.readableBytes() < CodecHelper.MIN_PROTOCOL_LEN - 1) {
+            wrapper.setReaderIndex(originReaderIndex);
+            return null;
+        }
+
+        int totalLength = wrapper.readInt();
+
+        if (totalLength <= 0) {
+            throw new IllegalArgumentException("Illegal total length " + totalLength);
+        }
+
+        if (totalLength > CodecHelper.PACKET_MAX_LEN) {
+            throw new IllegalArgumentException(String.format("Total length %d is more than limit %d", totalLength, CodecHelper.PACKET_MAX_LEN));
+        }
+
+        if (wrapper.readableBytes() < totalLength) {
+            wrapper.setReaderIndex(originReaderIndex);
+            return null;
+        }
+
+        ByteBuffer totalBuffer = ByteBuffer.allocate(totalLength);
+
+        wrapper.readBytes(totalBuffer);
+
+        totalBuffer.flip();
+
+        return CodecHelper.decode(totalBuffer);
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Encoder.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Encoder.java
new file mode 100644
index 0000000..10aa504
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Encoder.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.api.buffer.ByteBufferWrapper;
+import org.apache.rocketmq.remoting.api.command.RemotingCommand;
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+import org.apache.rocketmq.remoting.impl.buffer.NettyByteBufferWrapper;
+import org.apache.rocketmq.remoting.impl.command.CodecHelper;
+import org.apache.rocketmq.remoting.impl.protocol.serializer.SerializerFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Encoder extends MessageToByteEncoder<RemotingCommand> {
+    private static final Logger LOG = LoggerFactory.getLogger(Encoder.class);
+
+    private final SerializerFactory serializerFactory = new SerializerFactoryImpl();
+
+    public Encoder() {
+    }
+
+    @Override
+    public void encode(final ChannelHandlerContext ctx, RemotingCommand remotingCommand, ByteBuf out) throws Exception {
+        try {
+            ByteBufferWrapper wrapper = new NettyByteBufferWrapper(out);
+
+            encode(serializerFactory, remotingCommand, wrapper);
+        } catch (final Exception e) {
+            LOG.error("Error occurred when encoding response for channel " + ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress(), e);
+            if (remotingCommand != null) {
+                LOG.error(remotingCommand.toString());
+            }
+            ctx.channel().close().addListener(new ChannelFutureListener() {
+                @Override
+                public void operationComplete(ChannelFuture future) throws Exception {
+                    LOG.warn("Close channel {} because of error {},result is {}", ctx.channel(), e, future.isSuccess());
+                }
+            });
+        }
+    }
+
+    public void encode(final SerializerFactory serializerFactory, final RemotingCommand remotingCommand,
+        final ByteBufferWrapper out) {
+        ByteBuffer encodeParameter = null;
+        if (remotingCommand.parameterBytes() != null) {
+            encodeParameter = ByteBuffer.wrap(remotingCommand.parameterBytes());
+        } else if (remotingCommand.parameter() != null) {
+            final Serializer serialization = serializerFactory.get(remotingCommand.serializerType());
+            encodeParameter = serialization.encode(remotingCommand.parameter());
+        }
+
+        int parameterLength = encodeParameter != null ? encodeParameter.limit() : 0;
+        int extBodyLength = remotingCommand.extraPayload() != null ? remotingCommand.extraPayload().length : 0;
+
+        ByteBuffer header = CodecHelper.encodeHeader(remotingCommand, parameterLength, extBodyLength);
+        out.writeBytes(header);
+
+        if (encodeParameter != null) {
+            out.writeBytes(encodeParameter);
+        }
+
+        if (remotingCommand.extraPayload() != null) {
+            out.writeBytes(remotingCommand.extraPayload());
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ExceptionHandler.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ExceptionHandler.java
new file mode 100644
index 0000000..52563f4
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ExceptionHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ChannelHandler.Sharable
+public class ExceptionHandler extends ChannelDuplexHandler {
+    private final static Logger LOG = LoggerFactory.getLogger(ExceptionHandler.class);
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+        // Uncaught exceptions from inbound handlers will propagate up to this handler
+        LOG.error(String.format("channel exception %s occurred ! ", ctx.channel()), cause);
+        ctx.close();
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Http2Handler.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Http2Handler.java
new file mode 100644
index 0000000..7cdb976
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/Http2Handler.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.handler.codec.http2.DefaultHttp2Connection;
+import io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder;
+import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder;
+import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
+import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
+import io.netty.handler.codec.http2.DefaultHttp2Headers;
+import io.netty.handler.codec.http2.DefaultHttp2HeadersDecoder;
+import io.netty.handler.codec.http2.DefaultHttp2LocalFlowController;
+import io.netty.handler.codec.http2.Http2Connection;
+import io.netty.handler.codec.http2.Http2ConnectionDecoder;
+import io.netty.handler.codec.http2.Http2ConnectionEncoder;
+import io.netty.handler.codec.http2.Http2ConnectionHandler;
+import io.netty.handler.codec.http2.Http2Exception;
+import io.netty.handler.codec.http2.Http2FrameAdapter;
+import io.netty.handler.codec.http2.Http2FrameReader;
+import io.netty.handler.codec.http2.Http2FrameWriter;
+import io.netty.handler.codec.http2.Http2Headers;
+import io.netty.handler.codec.http2.Http2HeadersDecoder;
+import io.netty.handler.codec.http2.Http2Settings;
+import io.netty.handler.codec.http2.StreamBufferingEncoder;
+
+import static io.netty.handler.codec.http.HttpResponseStatus.OK;
+import static io.netty.handler.codec.http2.DefaultHttp2LocalFlowController.DEFAULT_WINDOW_UPDATE_RATIO;
+
+public class Http2Handler extends Http2ConnectionHandler {
+
+    private boolean isServer;
+    private int lastStreamId;
+
+    private Http2Handler(final Http2ConnectionDecoder decoder, final Http2ConnectionEncoder encoder,
+        final Http2Settings initialSettings, final boolean isServer) {
+        super(decoder, encoder, initialSettings);
+        decoder.frameListener(new FrameListener());
+        this.isServer = isServer;
+    }
+
+    public static Http2Handler newHandler(final boolean isServer) {
+
+        Http2HeadersDecoder headersDecoder = new DefaultHttp2HeadersDecoder(true);
+        Http2FrameReader frameReader = new DefaultHttp2FrameReader(headersDecoder);
+        Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter();
+
+        Http2Connection connection = new DefaultHttp2Connection(isServer);
+
+        Http2ConnectionEncoder encoder = new StreamBufferingEncoder(
+            new DefaultHttp2ConnectionEncoder(connection, frameWriter));
+
+        connection.local().flowController(new DefaultHttp2LocalFlowController(connection,
+            DEFAULT_WINDOW_UPDATE_RATIO, true));
+
+        Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(connection, encoder,
+            frameReader);
+
+        Http2Settings settings = new Http2Settings();
+
+        if (!isServer)
+            settings.pushEnabled(true);
+
+        settings.initialWindowSize(1048576 * 10); //10MiB
+        settings.maxConcurrentStreams(Integer.MAX_VALUE);
+
+        return newHandler(decoder, encoder, settings, isServer);
+    }
+
+    private static Http2Handler newHandler(final Http2ConnectionDecoder decoder, final Http2ConnectionEncoder encoder,
+        final Http2Settings settings, boolean isServer) {
+        return new Http2Handler(decoder, encoder, settings, isServer);
+    }
+
+    @Override
+    public void write(final ChannelHandlerContext ctx, final Object msg,
+        final ChannelPromise promise) throws Exception {
+        if (isServer) {
+            assert msg instanceof ByteBuf;
+            sendAPushPromise(ctx, lastStreamId, lastStreamId + 1, (ByteBuf) msg);
+        } else {
+
+            final Http2Headers headers = new DefaultHttp2Headers();
+
+            try {
+                long threadId = Thread.currentThread().getId();
+                long streamId = (threadId % 2 == 0) ? threadId + 1 : threadId + 2;
+                encoder().writeHeaders(ctx, (int) streamId, headers, 0, false, promise);
+                encoder().writeData(ctx, (int) streamId, (ByteBuf) msg, 0, false, ctx.newPromise());
+                ctx.flush();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
+    private void sendAPushPromise(ChannelHandlerContext ctx, int streamId, int pushPromiseStreamId,
+        ByteBuf payload) throws Http2Exception {
+
+        encoder().writePushPromise(ctx, streamId, pushPromiseStreamId,
+            new DefaultHttp2Headers().status(OK.codeAsText()), 0, ctx.newPromise());
+
+        //Http2Stream stream = connection.local().reservePushStream(pushPromiseStreamId, connection.connectionStream());
+        Http2Headers headers = new DefaultHttp2Headers();
+        headers.status(OK.codeAsText());
+        encoder().writeHeaders(ctx, pushPromiseStreamId, headers, 0, false, ctx.newPromise());
+        encoder().writeData(ctx, pushPromiseStreamId, payload, 0, false, ctx.newPromise());
+    }
+
+    private class FrameListener extends Http2FrameAdapter {
+        @Override
+        public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding,
+            boolean endOfStream) throws Http2Exception {
+            //Http2Handler.this.onDataRead(ctx, streamId, data, endOfStream);
+            data.retain();
+            Http2Handler.this.lastStreamId = streamId;
+            ctx.fireChannelRead(data);
+            return data.readableBytes() + padding;
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ProtocolSelector.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ProtocolSelector.java
new file mode 100644
index 0000000..e00a213
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/netty/handler/ProtocolSelector.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.impl.netty.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.ssl.SslContext;
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+import org.apache.rocketmq.remoting.api.protocol.ProtocolFactory;
+import org.apache.rocketmq.remoting.impl.channel.ChannelHandlerContextWrapperImpl;
+import org.apache.rocketmq.remoting.impl.protocol.ProtocolFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProtocolSelector extends SimpleChannelInboundHandler<ByteBuf> {
+    public static final String NAME = ProtocolSelector.class.getSimpleName();
+    private static final Logger LOG = LoggerFactory.getLogger(ProtocolSelector.class);
+    private ProtocolFactory protocolFactory;
+
+    public ProtocolSelector(final SslContext sslContext) {
+        this.protocolFactory = new ProtocolFactoryImpl(sslContext);
+    }
+
+    @Override
+    protected void channelRead0(final ChannelHandlerContext ctx, final ByteBuf msg) throws Exception {
+        if (msg.readableBytes() < 1) {
+            return;
+        }
+        msg.markReaderIndex();
+        Protocol protocol = protocolFactory.get(msg.readByte());
+        if (protocol == null) {
+            ctx.channel().close().addListener(new ChannelFutureListener() {
+                @Override
+                public void operationComplete(ChannelFuture future) throws Exception {
+                    LOG.warn("Close channel {},result is {}", ctx.channel(), future.isSuccess());
+                }
+            });
+            return;
+        }
+        ChannelHandlerContextWrapper chcw = new ChannelHandlerContextWrapperImpl(ctx);
+        protocol.assembleHandler(chcw);
+        msg.resetReaderIndex();
+        ctx.pipeline().remove(this);
+        ctx.fireChannelRead(msg.retain());
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/Httpv2Protocol.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/Httpv2Protocol.java
new file mode 100644
index 0000000..1dc371d
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/Httpv2Protocol.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.ssl.SslContext;
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+import org.apache.rocketmq.remoting.impl.netty.handler.Http2Handler;
+import org.apache.rocketmq.remoting.impl.netty.handler.ProtocolSelector;
+
+public class Httpv2Protocol extends RemotingCoreProtocol {
+    private SslContext sslContext;
+
+    public Httpv2Protocol(final SslContext sslContext) {
+        this.sslContext = sslContext;
+    }
+
+    @Override
+    public String name() {
+        return HTTP2;
+    }
+
+    @Override
+    public byte type() {
+        return HTTP_2_MAGIC;
+    }
+
+    @Override
+    public void assembleHandler(final ChannelHandlerContextWrapper ctx) {
+        super.assembleHandler(ctx);
+        ChannelHandlerContext chx = (ChannelHandlerContext) ctx.getContext();
+
+        chx.pipeline().addAfter(ProtocolSelector.NAME, "sslHandler", sslContext.newHandler(chx.alloc()));
+        chx.pipeline().addAfter("sslHandler", "http2Handler", Http2Handler.newHandler(true));
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/ProtocolFactoryImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/ProtocolFactoryImpl.java
new file mode 100644
index 0000000..15322be
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/ProtocolFactoryImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol;
+
+import io.netty.handler.ssl.SslContext;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+import org.apache.rocketmq.remoting.api.protocol.ProtocolFactory;
+
+public class ProtocolFactoryImpl implements ProtocolFactory {
+    private static final int MAX_COUNT = 0x0FF;
+    private final Protocol[] tables = new Protocol[MAX_COUNT];
+
+    private SslContext sslContext;
+
+    public ProtocolFactoryImpl(final SslContext sslContext) {
+        this.sslContext = sslContext;
+        this.register(new RemotingCoreProtocol());
+        this.register(new Httpv2Protocol(sslContext));
+        this.register(new WebSocketProtocol());
+    }
+
+    public ProtocolFactoryImpl() {
+        this.register(new RemotingCoreProtocol());
+        this.register(new Httpv2Protocol(sslContext));
+        this.register(new WebSocketProtocol());
+    }
+
+    @Override
+    public void register(Protocol protocol) {
+        if (tables[protocol.type() & MAX_COUNT] != null) {
+            throw new RuntimeException("protocol header's sign is overlapped");
+        }
+        tables[protocol.type() & MAX_COUNT] = protocol;
+    }
+
+    @Override
+    public void resetAll(final Protocol protocol) {
+        for (int i = 0; i < MAX_COUNT; i++) {
+            tables[i] = protocol;
+        }
+    }
+
+    @Override
+    public byte type(final String protocolName) {
+
+        for (int i = 0; i < this.tables.length; i++) {
+            if (this.tables[i] != null) {
+                if (this.tables[i].name().equalsIgnoreCase(protocolName)) {
+                    return this.tables[i].type();
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(String.format("the protocol: %s not exist", protocolName));
+    }
+
+    @Override
+    public Protocol get(byte type) {
+        return tables[type & MAX_COUNT];
+    }
+
+    @Override
+    public void clearAll() {
+        for (int i = 0; i < this.tables.length; i++) {
+            this.tables[i] = null;
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/RemotingCoreProtocol.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/RemotingCoreProtocol.java
new file mode 100644
index 0000000..317b24f
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/RemotingCoreProtocol.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol;
+
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+import org.apache.rocketmq.remoting.impl.netty.handler.Decoder;
+import org.apache.rocketmq.remoting.impl.netty.handler.Encoder;
+import org.apache.rocketmq.remoting.impl.netty.handler.ProtocolSelector;
+
+public class RemotingCoreProtocol implements Protocol {
+    @Override
+    public String name() {
+        return MVP;
+    }
+
+    @Override
+    public byte type() {
+        return MVP_MAGIC;
+    }
+
+    @Override
+    public void assembleHandler(final ChannelHandlerContextWrapper ctx) {
+
+        ChannelHandlerContext chx = (ChannelHandlerContext) ctx.getContext();
+
+        chx.pipeline().addAfter(ProtocolSelector.NAME, "decoder", new Decoder());
+        chx.pipeline().addAfter("decoder", "encoder", new Encoder());
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/WebSocketProtocol.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/WebSocketProtocol.java
new file mode 100644
index 0000000..18a3a11
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/WebSocketProtocol.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol;
+
+import org.apache.rocketmq.remoting.api.channel.ChannelHandlerContextWrapper;
+import org.apache.rocketmq.remoting.api.protocol.Protocol;
+
+public class WebSocketProtocol implements Protocol {
+    @Override
+    public String name() {
+        return WEBSOCKET;
+    }
+
+    @Override
+    public byte type() {
+        return WEBSOCKET_MAGIC;
+    }
+
+    @Override
+    public void assembleHandler(final ChannelHandlerContextWrapper ctx) {
+
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/CompressorFactoryImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/CompressorFactoryImpl.java
new file mode 100644
index 0000000..10e97ba
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/CompressorFactoryImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.compression;
+
+import org.apache.rocketmq.remoting.api.compressable.Compressor;
+import org.apache.rocketmq.remoting.api.compressable.CompressorFactory;
+
+public class CompressorFactoryImpl implements CompressorFactory {
+    private static final int MAX_COUNT = 0x0FF;
+    private final Compressor[] tables = new Compressor[MAX_COUNT];
+
+    public CompressorFactoryImpl() {
+        this.register(new GZipCompressor());
+    }
+
+    @Override
+    public void register(Compressor compressor) {
+        if (tables[compressor.type() & MAX_COUNT] != null) {
+            throw new RuntimeException("compressor header's sign is overlapped");
+        }
+        tables[compressor.type() & MAX_COUNT] = compressor;
+    }
+
+    @Override
+    public byte type(String compressionName) {
+        for (Compressor table : this.tables) {
+            if (table != null) {
+                if (table.name().equalsIgnoreCase(compressionName)) {
+                    return table.type();
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(String.format("the compressor: %s not exist", compressionName));
+
+    }
+
+    @Override
+    public Compressor get(byte type) {
+        return tables[type & MAX_COUNT];
+    }
+
+    @Override
+    public void clearAll() {
+        for (int i = 0; i < this.tables.length; i++) {
+            this.tables[i] = null;
+        }
+    }
+
+    public Compressor[] getTables() {
+        return tables;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/GZipCompressor.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/GZipCompressor.java
new file mode 100644
index 0000000..fc33f4c
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/compression/GZipCompressor.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.compression;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.apache.rocketmq.remoting.api.compressable.Compressor;
+
+public class GZipCompressor implements Compressor {
+    public static final int BUFFER = 1024;
+    public static final String COMPRESSOR_NAME = GZipCompressor.class.getSimpleName();
+    public static final byte COMPRESSOR_TYPE = 'G';
+
+    @Override
+    public String name() {
+        return COMPRESSOR_NAME;
+    }
+
+    @Override
+    public byte type() {
+        return COMPRESSOR_TYPE;
+    }
+
+    @Override
+    public byte[] compress(byte[] content) throws Exception {
+        if (content == null)
+            return new byte[0];
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(content);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        compress(bais, baos);
+        byte[] output = baos.toByteArray();
+        baos.flush();
+        baos.close();
+        bais.close();
+        return output;
+
+    }
+
+    private void compress(InputStream is, OutputStream os) throws Exception {
+        GZIPOutputStream gos = new GZIPOutputStream(os);
+
+        int count;
+        byte data[] = new byte[BUFFER];
+        while ((count = is.read(data, 0, BUFFER)) != -1) {
+            gos.write(data, 0, count);
+        }
+        gos.finish();
+        gos.flush();
+        gos.close();
+    }
+
+    @Override
+    public byte[] deCompress(byte[] content) throws Exception {
+        if (content == null)
+            return new byte[0];
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(content);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        decompress(bais, baos);
+        content = baos.toByteArray();
+        baos.flush();
+        baos.close();
+        bais.close();
+        return content;
+    }
+
+    private void decompress(InputStream is, OutputStream os) throws Exception {
+        GZIPInputStream gis = new GZIPInputStream(is);
+
+        int count;
+        byte data[] = new byte[BUFFER];
+        while ((count = gis.read(data, 0, BUFFER)) != -1) {
+            os.write(data, 0, count);
+        }
+        gis.close();
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/JsonSerializer.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/JsonSerializer.java
new file mode 100644
index 0000000..c85d44b
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/JsonSerializer.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.serializer;
+
+import com.alibaba.fastjson.JSON;
+import java.lang.reflect.Type;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+import org.apache.rocketmq.remoting.impl.command.CodecHelper;
+
+public class JsonSerializer implements Serializer {
+    public static final String SERIALIZER_NAME = JsonSerializer.class.getSimpleName();
+    public static final byte SERIALIZER_TYPE = 'J';
+
+    public JsonSerializer() {
+    }
+
+    @Override
+    public String name() {
+        return SERIALIZER_NAME;
+    }
+
+    @Override
+    public byte type() {
+        return SERIALIZER_TYPE;
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final Class<T> c) {
+        if (content != null) {
+            try {
+                final String jsonString = new String(content, CodecHelper.REMOTING_CHARSET);
+                return JSON.parseObject(jsonString, c);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final TypePresentation<T> typePresentation) {
+        return decode(content, typePresentation.getType());
+    }
+
+    @Override
+    public <T> T decode(byte[] content, Type type) {
+        if (content != null) {
+            try {
+                final String jsonString = new String(content, CodecHelper.REMOTING_CHARSET);
+                return JSON.parseObject(jsonString, type);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public ByteBuffer encode(final Object object) {
+        if (object != null) {
+            String jsonString = JSON.toJSONString(object);
+            byte[] bytes = jsonString.getBytes(CodecHelper.REMOTING_CHARSET);
+            try {
+                return ByteBuffer.wrap(bytes, 0, bytes.length);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return null;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/Kryo3Serializer.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/Kryo3Serializer.java
new file mode 100644
index 0000000..06ea217
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/Kryo3Serializer.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.serializer;
+
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+
+public class Kryo3Serializer implements Serializer {
+    public static final String SERIALIZER_NAME = Kryo3Serializer.class.getSimpleName();
+    public static final byte SERIALIZER_TYPE = 'K';
+
+    public Kryo3Serializer() {
+    }
+
+    @Override
+    public String name() {
+        return SERIALIZER_NAME;
+    }
+
+    @Override
+    public byte type() {
+        return SERIALIZER_TYPE;
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final Class<T> c) {
+        if (content != null) {
+            Input input = null;
+            try {
+                input = new Input(content);
+                return (T) ThreadSafeKryo.getKryoInstance().readClassAndObject(input);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            } finally {
+                input.close();
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final TypePresentation<T> typePresentation) {
+        return decode(content, typePresentation.getType());
+    }
+
+    @Override
+    public <T> T decode(byte[] content, Type type) {
+        if (type instanceof ParameterizedType) {
+            return decode(content, (Class<? extends T>) ((ParameterizedType) type).getRawType());
+        } else if (type instanceof Class) {
+            return decode(content, (Class<? extends T>) type);
+        }
+        return null;
+    }
+
+    @Override
+    public ByteBuffer encode(final Object object) {
+        if (object != null) {
+            try (Output output = new Output(1024, 1024 * 1024 * 6)) {
+                ThreadSafeKryo.getKryoInstance().writeClassAndObject(output, object);
+                return ByteBuffer.wrap(output.getBuffer(), 0, output.position());
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/MsgPackSerializer.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/MsgPackSerializer.java
new file mode 100644
index 0000000..1097f8f
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/MsgPackSerializer.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.serializer;
+
+import java.lang.reflect.Type;
+import java.nio.ByteBuffer;
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.common.TypePresentation;
+import org.msgpack.MessagePack;
+import org.msgpack.template.Template;
+
+public class MsgPackSerializer implements Serializer {
+    public static final String SERIALIZER_NAME = MsgPackSerializer.class.getSimpleName();
+    public static final byte SERIALIZER_TYPE = 'M';
+    private final MessagePack messagePack = new MessagePack();
+
+    public MsgPackSerializer() {
+    }
+
+    @Override
+    public String name() {
+        return SERIALIZER_NAME;
+    }
+
+    @Override
+    public byte type() {
+        return SERIALIZER_TYPE;
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final Class<T> c) {
+        try {
+            return messagePack.read(content, c);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public <T> T decode(final byte[] content, final TypePresentation<T> typePresentation) {
+        return decode(content, typePresentation.getType());
+    }
+
+    @Override
+    public <T> T decode(byte[] content, Type type) {
+        Template<T> template = (Template<T>) messagePack.lookup(type);
+        try {
+            return messagePack.read(content, template);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ByteBuffer encode(final Object object) {
+        try {
+            byte[] data = messagePack.write(object);
+            return ByteBuffer.wrap(data);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/SerializerFactoryImpl.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/SerializerFactoryImpl.java
new file mode 100644
index 0000000..632b61f
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/SerializerFactoryImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.serializer;
+
+import org.apache.rocketmq.remoting.api.serializable.Serializer;
+import org.apache.rocketmq.remoting.api.serializable.SerializerFactory;
+
+public class SerializerFactoryImpl implements SerializerFactory {
+    private static final int MAX_COUNT = 0x0FF;
+    private final Serializer[] tables = new Serializer[MAX_COUNT];
+
+    public SerializerFactoryImpl() {
+        this.register(new JsonSerializer());
+        this.register(new Kryo3Serializer());
+        this.register(new MsgPackSerializer());
+    }
+
+    @Override
+    public void register(Serializer serialization) {
+        if (tables[serialization.type() & MAX_COUNT] != null) {
+            throw new RuntimeException("serialization header's sign is overlapped");
+        }
+        tables[serialization.type() & MAX_COUNT] = serialization;
+    }
+
+    @Override
+    public byte type(final String serializationName) {
+        for (Serializer table : this.tables) {
+            if (table != null) {
+                if (table.name().equalsIgnoreCase(serializationName)) {
+                    return table.type();
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(String.format("the serialization: %s not exist", serializationName));
+    }
+
+    @Override
+    public Serializer get(byte type) {
+        return tables[type & MAX_COUNT];
+    }
+
+    @Override
+    public void clearAll() {
+        for (int i = 0; i < this.tables.length; i++) {
+            this.tables[i] = null;
+        }
+    }
+
+    public Serializer[] getTables() {
+        return tables;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/ThreadSafeKryo.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/ThreadSafeKryo.java
new file mode 100644
index 0000000..cadfc27
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/impl/protocol/serializer/ThreadSafeKryo.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.impl.protocol.serializer;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.KryoSerializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Currency;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import org.objenesis.strategy.StdInstantiatorStrategy;
+
+public class ThreadSafeKryo {
+    private static final ThreadLocal<Kryo> KRYOS = new ThreadLocal<Kryo>() {
+        protected Kryo initialValue() {
+            Kryo kryo = new Kryo();
+
+            kryo.register(byte[].class);
+            kryo.register(char[].class);
+            kryo.register(short[].class);
+            kryo.register(int[].class);
+            kryo.register(long[].class);
+            kryo.register(float[].class);
+            kryo.register(double[].class);
+            kryo.register(boolean[].class);
+            kryo.register(String[].class);
+            kryo.register(Object[].class);
+            kryo.register(KryoSerializable.class);
+            kryo.register(BigInteger.class);
+            kryo.register(BigDecimal.class);
+            kryo.register(Class.class);
+            kryo.register(Date.class);
+            // kryo.register(Enum.class);
+            kryo.register(EnumSet.class);
+            kryo.register(Currency.class);
+            kryo.register(StringBuffer.class);
+            kryo.register(StringBuilder.class);
+            kryo.register(Collections.EMPTY_LIST.getClass());
+            kryo.register(Collections.EMPTY_MAP.getClass());
+            kryo.register(Collections.EMPTY_SET.getClass());
+            kryo.register(Collections.singletonList(null).getClass());
+            kryo.register(Collections.singletonMap(null, null).getClass());
+            kryo.register(Collections.singleton(null).getClass());
+            kryo.register(TreeSet.class);
+            kryo.register(Collection.class);
+            kryo.register(TreeMap.class);
+            kryo.register(Map.class);
+            try {
+                kryo.register(Class.forName("sun.util.calendar.ZoneInfo"));
+            } catch (ClassNotFoundException e) {
+                // Noop
+            }
+            kryo.register(Calendar.class);
+            kryo.register(Locale.class);
+
+            kryo.register(BitSet.class);
+            kryo.register(HashMap.class);
+            kryo.register(Timestamp.class);
+            kryo.register(ArrayList.class);
+
+            // kryo.setRegistrationRequired(true);
+            kryo.setReferences(false);
+            kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
+
+            return kryo;
+        }
+    };
+
+    public static Kryo getKryoInstance() {
+        return KRYOS.get();
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/BeanUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/BeanUtils.java
new file mode 100644
index 0000000..0177990
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/BeanUtils.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BeanUtils {
+    private final static Logger LOG = LoggerFactory.getLogger(BeanUtils.class);
+
+    /**
+     * <p>Populate the JavaBeans properties of the specified bean, based on
+     * the specified name/value pairs.  This method uses Java reflection APIs
+     * to identify corresponding "property setter" method names, and deals
+     * with setter arguments of type <Code>String</Code>, <Code>boolean</Code>,
+     * <Code>int</Code>, <Code>long</Code>, <Code>float</Code>, and
+     * <Code>double</Code>.</p>
+     *
+     * <p>The particular setter method to be called for each property is
+     * determined using the usual JavaBeans introspection mechanisms.  Thus,
+     * you may identify custom setter methods using a BeanInfo class that is
+     * associated with the class of the bean itself.  If no such BeanInfo
+     * class is available, the standard method name conversion ("set" plus
+     * the capitalized name of the property in question) is used.</p>
+     *
+     * <p><strong>NOTE</strong>:  It is contrary to the JavaBeans Specification
+     * to have more than one setter method (with different argument
+     * signatures) for the same property.</p>
+     *
+     * @param clazz JavaBean class whose properties are being populated
+     * @param properties Map keyed by property name, with the corresponding (String or String[]) value(s) to be set
+     * @param <T> Class type
+     * @return Class instance
+     */
+    public static <T> T populate(final Properties properties, final Class<T> clazz) {
+        T obj = null;
+        try {
+            obj = clazz.newInstance();
+            return populate(properties, obj);
+        } catch (Throwable e) {
+            LOG.warn("Error occurs !", e);
+        }
+        return obj;
+    }
+
+    private static <T> void setField(final Field field, final Properties properties, final T obj) throws Exception {
+        Type fieldType = field.getType();
+        String fieldName = field.getName();
+
+        String value = null;
+        String configName = convertToConfigName(fieldName);
+        String envName = convertToEnvName(fieldName);
+
+        if (properties.containsKey(envName)) {
+            value = properties.getProperty(envName);
+        }
+
+        if (properties.containsKey(configName)) {
+            value = properties.getProperty(configName);
+        }
+
+        if (value == null) {
+            return;
+        }
+
+        if (fieldType == Boolean.TYPE) {
+            field.set(obj, Boolean.valueOf(value));
+        } else if (fieldType == Integer.TYPE) {
+            field.set(obj, Integer.valueOf(value));
+        } else if (fieldType == Double.TYPE) {
+            field.set(obj, Double.valueOf(value));
+        } else if (fieldType == Float.TYPE) {
+            field.set(obj, Float.valueOf(value));
+        } else if (fieldType == Long.TYPE) {
+            field.set(obj, Long.valueOf(value));
+        } else
+            field.set(obj, value);
+    }
+
+    private static String convertToConfigName(String variableName) {
+        StringBuilder sb = new StringBuilder();
+        for (char c : variableName.toCharArray()) {
+            if (Character.isUpperCase(c)) {
+                sb.append('.');
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    private static String convertToEnvName(String variableName) {
+        StringBuilder sb = new StringBuilder();
+        for (char c : variableName.toCharArray()) {
+            if (Character.isUpperCase(c)) {
+                sb.append('_');
+            }
+            sb.append(Character.toUpperCase(c));
+        }
+        return sb.toString();
+    }
+
+    public static <T> T populate(final Properties properties, final T obj) {
+        Class<?> clazz = obj.getClass();
+        List<Field> allFields = new ArrayList<>();
+        allFields = getAllFields(allFields, clazz);
+        Properties fullProp = extractProperties(properties);
+
+        try {
+            for (Field field : allFields) {
+                if (!Modifier.isStatic(field.getModifiers())) {
+                    field.setAccessible(true);
+                    setField(field, fullProp, obj);
+                }
+            }
+        } catch (Exception e) {
+            LOG.warn("Error occurs !", e);
+        }
+        return obj;
+    }
+
+    public static String configObjectToString(final Object object) {
+        List<Field> allFields = new ArrayList<>();
+        getAllFields(allFields, object.getClass());
+        StringBuilder sb = new StringBuilder();
+        for (Field field : allFields) {
+            if (!Modifier.isStatic(field.getModifiers())) {
+                String name = field.getName();
+                if (!name.startsWith("this")) {
+                    Object value = null;
+                    try {
+                        field.setAccessible(true);
+                        value = field.get(object);
+                        if (null == value) {
+                            value = "";
+                        }
+                    } catch (IllegalAccessException ignored) {
+                    }
+                    sb.append(name).append("=").append(value).append("%n");
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private static List<Field> getAllFields(List<Field> fields, Class<?> type) {
+        fields.addAll(Arrays.asList(type.getDeclaredFields()));
+        if (type.getSuperclass() != null) {
+            getAllFields(fields, type.getSuperclass());
+        }
+        return fields;
+    }
+
+    private static Properties extractProperties(final Properties properties) {
+        Properties newPro = new Properties();
+
+        Map<String, String> envMap = System.getenv();
+        for (final Map.Entry<String, String> entry : envMap.entrySet()) {
+            newPro.setProperty(entry.getKey().toUpperCase(), entry.getValue());
+            newPro.setProperty(entry.getKey().toLowerCase(), entry.getValue()); //EnvProp supports A_B_C and a.b.c
+        }
+
+        Properties systemProp = System.getProperties(); //SystemProp supports a.b.c
+        for (final Map.Entry<Object, Object> entry : systemProp.entrySet()) {
+            newPro.setProperty(String.valueOf(entry.getKey()).toLowerCase(), String.valueOf(entry.getValue()));
+        }
+
+        Properties inner = null;
+        try {
+            Field field = Properties.class.getDeclaredField("defaults");
+            field.setAccessible(true);
+            inner = (Properties) field.get(properties);
+        } catch (Exception ignore) {
+        }
+
+        if (inner != null) {
+            for (final Map.Entry<Object, Object> entry : inner.entrySet()) {
+                newPro.setProperty(String.valueOf(entry.getKey()).toLowerCase(), String.valueOf(entry.getValue()));
+            }
+        }
+
+        for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
+            newPro.setProperty(String.valueOf(entry.getKey()).toLowerCase(), String.valueOf(entry.getValue()));
+        }
+
+        return newPro;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ByteUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ByteUtils.java
new file mode 100644
index 0000000..c298ce7
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ByteUtils.java
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+/**
+ * Copy from Bouncy Castle Crypto APIs
+ *
+ * This class is a utility class for manipulating byte arrays.
+ */
+public final class ByteUtils {
+
+    private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+    /**
+     * Default constructor (private)
+     */
+    private ByteUtils() {
+        // empty
+    }
+
+    /**
+     * Compare two byte arrays (perform null checks beforehand).
+     *
+     * @param left the first byte array
+     * @param right the second byte array
+     * @return the result of the comparison
+     */
+    public static boolean equals(byte[] left, byte[] right) {
+        if (left == null) {
+            return right == null;
+        }
+        if (right == null) {
+            return false;
+        }
+
+        if (left.length != right.length) {
+            return false;
+        }
+        boolean result = true;
+        for (int i = left.length - 1; i >= 0; i--) {
+            result &= left[i] == right[i];
+        }
+        return result;
+    }
+
+    /**
+     * Compare two two-dimensional byte arrays. No null checks are performed.
+     *
+     * @param left the first byte array
+     * @param right the second byte array
+     * @return the result of the comparison
+     */
+    public static boolean equals(byte[][] left, byte[][] right) {
+        if (left.length != right.length) {
+            return false;
+        }
+
+        boolean result = true;
+        for (int i = left.length - 1; i >= 0; i--) {
+            result &= ByteUtils.equals(left[i], right[i]);
+        }
+
+        return result;
+    }
+
+    /**
+     * Compare two three-dimensional byte arrays. No null checks are performed.
+     *
+     * @param left the first byte array
+     * @param right the second byte array
+     * @return the result of the comparison
+     */
+    public static boolean equals(byte[][][] left, byte[][][] right) {
+        if (left.length != right.length) {
+            return false;
+        }
+
+        boolean result = true;
+        for (int i = left.length - 1; i >= 0; i--) {
+            if (left[i].length != right[i].length) {
+                return false;
+            }
+            for (int j = left[i].length - 1; j >= 0; j--) {
+                result &= ByteUtils.equals(left[i][j], right[i][j]);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Computes a hashcode based on the contents of a one-dimensional byte array
+     * rather than its identity.
+     *
+     * @param array the array to compute the hashcode of
+     * @return the hashcode
+     */
+    public static int deepHashCode(byte[] array) {
+        int result = 1;
+        for (int i = 0; i < array.length; i++) {
+            result = 31 * result + array[i];
+        }
+        return result;
+    }
+
+    /**
+     * Computes a hashcode based on the contents of a two-dimensional byte array
+     * rather than its identity.
+     *
+     * @param array the array to compute the hashcode of
+     * @return the hashcode
+     */
+    public static int deepHashCode(byte[][] array) {
+        int result = 1;
+        for (int i = 0; i < array.length; i++) {
+            result = 31 * result + deepHashCode(array[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Computes a hashcode based on the contents of a three-dimensional byte
+     * array rather than its identity.
+     *
+     * @param array the array to compute the hashcode of
+     * @return the hashcode
+     */
+    public static int deepHashCode(byte[][][] array) {
+        int result = 1;
+        for (int i = 0; i < array.length; i++) {
+            result = 31 * result + deepHashCode(array[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Return a clone of the given byte array (performs null check beforehand).
+     *
+     * @param array the array to clone
+     * @return the clone of the given array, or <tt>null</tt> if the array is
+     * <tt>null</tt>
+     */
+    public static byte[] clone(byte[] array) {
+        if (array == null) {
+            return null;
+        }
+        byte[] result = new byte[array.length];
+        System.arraycopy(array, 0, result, 0, array.length);
+        return result;
+    }
+
+    /**
+     * Convert a string containing hexadecimal characters to a byte-array.
+     *
+     * @param s a hex string
+     * @return a byte array with the corresponding value
+     */
+    public static byte[] fromHexString(String s) {
+        char[] rawChars = s.toUpperCase().toCharArray();
+
+        int hexChars = 0;
+        for (int i = 0; i < rawChars.length; i++) {
+            if ((rawChars[i] >= '0' && rawChars[i] <= '9')
+                || (rawChars[i] >= 'A' && rawChars[i] <= 'F')) {
+                hexChars++;
+            }
+        }
+
+        byte[] byteString = new byte[(hexChars + 1) >> 1];
+
+        int pos = hexChars & 1;
+
+        for (int i = 0; i < rawChars.length; i++) {
+            if (rawChars[i] >= '0' && rawChars[i] <= '9') {
+                byteString[pos >> 1] <<= 4;
+                byteString[pos >> 1] |= rawChars[i] - '0';
+            } else if (rawChars[i] >= 'A' && rawChars[i] <= 'F') {
+                byteString[pos >> 1] <<= 4;
+                byteString[pos >> 1] |= rawChars[i] - 'A' + 10;
+            } else {
+                continue;
+            }
+            pos++;
+        }
+
+        return byteString;
+    }
+
+    /**
+     * Convert a byte array to the corresponding hexstring.
+     *
+     * @param input the byte array to be converted
+     * @return the corresponding hexstring
+     */
+    public static String toHexString(byte[] input) {
+        String result = "";
+        for (int i = 0; i < input.length; i++) {
+            result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
+            result += HEX_CHARS[(input[i]) & 0x0f];
+        }
+        return result;
+    }
+
+    /**
+     * Convert a byte array to the corresponding hex string.
+     *
+     * @param input the byte array to be converted
+     * @param prefix the prefix to put at the beginning of the hex string
+     * @param seperator a separator string
+     * @return the corresponding hex string
+     */
+    public static String toHexString(byte[] input, String prefix,
+        String seperator) {
+        String result = new String(prefix);
+        for (int i = 0; i < input.length; i++) {
+            result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
+            result += HEX_CHARS[(input[i]) & 0x0f];
+            if (i < input.length - 1) {
+                result += seperator;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Convert a byte array to the corresponding bit string.
+     *
+     * @param input the byte array to be converted
+     * @return the corresponding bit string
+     */
+    public static String toBinaryString(byte[] input) {
+        String result = "";
+        int i;
+        for (i = 0; i < input.length; i++) {
+            int e = input[i];
+            for (int ii = 0; ii < 8; ii++) {
+                int b = (e >>> ii) & 1;
+                result += b;
+            }
+            if (i != input.length - 1) {
+                result += " ";
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Compute the bitwise XOR of two arrays of bytes. The arrays have to be of
+     * same length. No length checking is performed.
+     *
+     * @param x1 the first array
+     * @param x2 the second array
+     * @return x1 XOR x2
+     */
+    public static byte[] xor(byte[] x1, byte[] x2) {
+        byte[] out = new byte[x1.length];
+
+        for (int i = x1.length - 1; i >= 0; i--) {
+            out[i] = (byte) (x1[i] ^ x2[i]);
+        }
+        return out;
+    }
+
+    /**
+     * Concatenate two byte arrays. No null checks are performed.
+     *
+     * @param x1 the first array
+     * @param x2 the second array
+     * @return (x2||x1) (little-endian order, i.e. x1 is at lower memory
+     * addresses)
+     */
+    public static byte[] concatenate(byte[] x1, byte[] x2) {
+        byte[] result = new byte[x1.length + x2.length];
+
+        System.arraycopy(x1, 0, result, 0, x1.length);
+        System.arraycopy(x2, 0, result, x1.length, x2.length);
+
+        return result;
+    }
+
+    /**
+     * Convert a 2-dimensional byte array into a 1-dimensional byte array by
+     * concatenating all entries.
+     *
+     * @param array a 2-dimensional byte array
+     * @return the concatenated input array
+     */
+    public static byte[] concatenate(byte[][] array) {
+        int rowLength = array[0].length;
+        byte[] result = new byte[array.length * rowLength];
+        int index = 0;
+        for (int i = 0; i < array.length; i++) {
+            System.arraycopy(array[i], 0, result, index, rowLength);
+            index += rowLength;
+        }
+        return result;
+    }
+
+    /**
+     * Split a byte array <tt>input</tt> into two arrays at <tt>index</tt>,
+     * i.e. the first array will have the lower <tt>index</tt> bytes, the
+     * second one the higher <tt>input.length - index</tt> bytes.
+     *
+     * @param input the byte array to be split
+     * @param index the index where the byte array is split
+     * @return the splitted input array as an array of two byte arrays
+     * @throws ArrayIndexOutOfBoundsException if <tt>index</tt> is out of bounds
+     */
+    public static byte[][] split(byte[] input, int index)
+        throws ArrayIndexOutOfBoundsException {
+        if (index > input.length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        byte[][] result = new byte[2][];
+        result[0] = new byte[index];
+        result[1] = new byte[input.length - index];
+        System.arraycopy(input, 0, result[0], 0, index);
+        System.arraycopy(input, index, result[1], 0, input.length - index);
+        return result;
+    }
+
+    /**
+     * Generate a subarray of a given byte array.
+     *
+     * @param input the input byte array
+     * @param start the start index
+     * @param end the end index
+     * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt>
+     * (inclusively) to <tt>end</tt> (exclusively)
+     */
+    public static byte[] subArray(byte[] input, int start, int end) {
+        byte[] result = new byte[end - start];
+        System.arraycopy(input, start, result, 0, end - start);
+        return result;
+    }
+
+    /**
+     * Generate a subarray of a given byte array.
+     *
+     * @param input the input byte array
+     * @param start the start index
+     * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
+     * the end of the array
+     */
+    public static byte[] subArray(byte[] input, int start) {
+        return subArray(input, start, input.length);
+    }
+
+    /**
+     * Rewrite a byte array as a char array
+     *
+     * @param input -
+     * the byte array
+     * @return char array
+     */
+    public static char[] toCharArray(byte[] input) {
+        char[] result = new char[input.length];
+        for (int i = 0; i < input.length; i++) {
+            result[i] = (char) input[i];
+        }
+        return result;
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ExceptionUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ExceptionUtils.java
new file mode 100644
index 0000000..6386ca0
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/ExceptionUtils.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public class ExceptionUtils {
+
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    /**
+     * <p>Gets the stack trace from a Throwable as a String.</p>
+     *
+     * <p>The result of this method vary by JDK version as this method
+     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
+     * On JDK1.3 and earlier, the cause exception will not be shown
+     * unless the specified throwable alters printStackTrace.</p>
+     *
+     * @param throwable the <code>Throwable</code> to be examined
+     * @return the stack trace as generated by the exception's
+     * <code>printStackTrace(PrintWriter)</code> method
+     */
+    public static String getStackTrace(final Throwable throwable) {
+        final StringWriter sw = new StringWriter();
+        final PrintWriter pw = new PrintWriter(sw, true);
+        throwable.printStackTrace(pw);
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * <p>Produces a <code>List</code> of stack frames - the message
+     * is not included. Only the trace of the specified exception is
+     * returned, any caused by trace is stripped.</p>
+     *
+     * <p>This works in most cases - it will only fail if the exception
+     * message contains a line that starts with:
+     * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
+     *
+     * @param t is any throwable
+     * @return List of stack frames
+     */
+    static List<String> getStackFrameList(final Throwable t) {
+        final String stackTrace = getStackTrace(t);
+        final String linebreak = LINE_SEPARATOR;
+        final StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+        final List<String> list = new ArrayList<String>();
+        boolean traceStarted = false;
+        while (frames.hasMoreTokens()) {
+            final String token = frames.nextToken();
+            // Determine if the line starts with <whitespace>at
+            final int at = token.indexOf("at");
+            if (at != -1 && token.substring(0, at).trim().isEmpty()) {
+                traceStarted = true;
+                list.add(token);
+            } else if (traceStarted) {
+                break;
+            }
+        }
+        return list;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/JvmUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/JvmUtils.java
new file mode 100644
index 0000000..fb97a14
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/JvmUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.Random;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class JvmUtils {
+    public static final String OS_NAME = System.getProperty("os.name").toLowerCase();
+    private final static Logger LOG = LoggerFactory.getLogger(JvmUtils.class);
+    //public static final String OS_VERSION = System.getProperty("os.version").toLowerCase();
+
+    /**
+     * A constructor to stop this class being constructed.
+     */
+    private JvmUtils() {
+        // Unused
+    }
+
+    public static boolean isWindows() {
+        return OS_NAME.startsWith("win");
+    }
+
+    public static boolean isWindows10() {
+        return OS_NAME.startsWith("win") && OS_NAME.endsWith("10");
+    }
+
+    public static boolean isMacOSX() {
+        return OS_NAME.contains("mac");
+    }
+
+    public static boolean isLinux() {
+        return OS_NAME.startsWith("linux");
+    }
+
+    public static boolean isUnix() {
+        return OS_NAME.contains("nix") ||
+            OS_NAME.contains("nux") ||
+            OS_NAME.contains("aix") ||
+            OS_NAME.contains("bsd") ||
+            OS_NAME.contains("sun") ||
+            OS_NAME.contains("hpux");
+    }
+
+    public static boolean isSolaris() {
+        return OS_NAME.startsWith("sun");
+    }
+
+    public static int getProcessId() {
+        String pid = null;
+        final File self = new File("/proc/self");
+        try {
+            if (self.exists()) {
+                pid = self.getCanonicalFile().getName();
+            }
+        } catch (IOException ignored) {
+            //Ignore it
+        }
+
+        if (pid == null) {
+            pid = ManagementFactory.getRuntimeMXBean().getName().split("@", 0)[0];
+        }
+
+        if (pid == null) {
+            int rpid = new Random().nextInt(1 << 16);
+            LOG.warn("Unable to determine PID, picked a random number {}", rpid);
+
+            return rpid;
+        } else {
+            return Integer.parseInt(pid);
+        }
+    }
+
+}
+
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/NetworkUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/NetworkUtils.java
new file mode 100644
index 0000000..0e8ae21
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/NetworkUtils.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+import org.jetbrains.annotations.NotNull;
+
+public final class NetworkUtils {
+
+    public static final String DEFAULT_LOCAL_ADDRESS = "127.0.0.1";
+    public static final String DEFAULT_LOCAL_HOSTNAME = "localhost";
+
+    /**
+     * A constructor to stop this class being constructed.
+     */
+    private NetworkUtils() {
+        // Unused
+    }
+
+    public static InetAddress getLoopbackAddress() {
+        try {
+            return InetAddress.getByName(null);
+        } catch (UnknownHostException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static boolean isLocalhost(@NotNull String host) {
+        return host.equalsIgnoreCase(DEFAULT_LOCAL_HOSTNAME) || host.equals(DEFAULT_LOCAL_ADDRESS);
+    }
+
+    public static String getLocalHostIp() {
+        try {
+            for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
+                NetworkInterface iface = ifaces.nextElement();
+                // Workaround for docker0 bridge
+                if ("docker0".equals(iface.getName()) || !iface.isUp()) {
+                    continue;
+                }
+                InetAddress ia;
+                for (Enumeration<InetAddress> ips = iface.getInetAddresses(); ips.hasMoreElements(); ) {
+                    ia = ips.nextElement();
+                    if (ia instanceof Inet4Address) {
+                        // Check if the address is any local or loop back(127.0.0.1 or ::1)
+                        if (!ia.isLoopbackAddress() && ia.getHostAddress().indexOf(':') == -1) {
+                            if (ia.isSiteLocalAddress()) {
+                                return ia.getHostAddress();
+                            } else if (!ia.isLinkLocalAddress() && !ia.isAnyLocalAddress()
+                                && !ia.isMulticastAddress()) {
+                                return ia.getHostAddress();
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            throw new RuntimeException("Could not get local host ip", e);
+        }
+        return DEFAULT_LOCAL_ADDRESS;
+    }
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/PropertyUtils.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/PropertyUtils.java
new file mode 100644
index 0000000..7e76a7e
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/PropertyUtils.java
@@ -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.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class PropertyUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(PropertyUtils.class);
+
+    public static String getPropertyIgnoreCase(final Properties properties, final String key) {
+        String value = null;
+        if (properties != null) {
+            for (Map.Entry<Object, Object> next : properties.entrySet()) {
+                if (next.getKey().toString().equalsIgnoreCase(key)) {
+                    return next.getValue().toString();
+                }
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Read a properties file from the given path
+     *
+     * @param filename The path of the file to read
+     * @return Property file instance
+     */
+    public static Properties loadProps(String filename) {
+        Properties props = new Properties();
+        try (InputStream propStream = new FileInputStream(filename)) {
+            props.load(propStream);
+        } catch (IOException e) {
+            LOG.error(String.format("Loading properties from file %s error !", filename), e);
+            System.exit(1);
+        }
+        return props;
+    }
+
+}
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/UIDGenerator.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/UIDGenerator.java
new file mode 100644
index 0000000..a4b1293
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/internal/UIDGenerator.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.remoting.internal;
+
+import java.nio.ByteBuffer;
+import java.util.Calendar;
+
+public class UIDGenerator {
+    private static ThreadLocal<UIDGenerator> generatorLocal = new ThreadLocal<UIDGenerator>() {
+        @Override
+        protected UIDGenerator initialValue() {
+            return new UIDGenerator();
+        }
+    };
+    private short counter;
+    private int basePos = 0;
+    private long startTime;
+    private long nextStartTime;
+    private StringBuilder sb = null;
+    private ByteBuffer buffer = ByteBuffer.allocate(6);
+
+    private UIDGenerator() {
+        int len = 4 + 2 + 4 + 4 + 2;
+
+        sb = new StringBuilder(len * 2);
+        ByteBuffer tempBuffer = ByteBuffer.allocate(len - buffer.limit());
+        tempBuffer.position(2);
+        tempBuffer.putInt(JvmUtils.getProcessId());
+        tempBuffer.position(0);
+        try {
+            tempBuffer.put((byte) 1);
+        } catch (Exception e) {
+            tempBuffer.put(createFakeIP());
+        }
+        tempBuffer.position(6);
+        tempBuffer.putInt(UIDGenerator.class.getClassLoader().hashCode());
+        sb.append(ByteUtils.toHexString(tempBuffer.array()));
+        basePos = sb.length();
+        setStartTime(System.currentTimeMillis());
+        counter = 0;
+    }
+
+    public static UIDGenerator instance() {
+        return generatorLocal.get();
+    }
+
+    public String createUID() {
+        long current = System.currentTimeMillis();
+        if (current >= nextStartTime) {
+            setStartTime(current);
+        }
+        buffer.position(0);
+        sb.setLength(basePos);
+        buffer.putInt((int) (System.currentTimeMillis() - startTime));
+        buffer.putShort(counter++);
+        sb.append(ByteUtils.toHexString(buffer.array()));
+        return sb.toString();
+    }
+
+    private void setStartTime(long millis) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(millis);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.set(Calendar.HOUR, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        startTime = cal.getTimeInMillis();
+        cal.add(Calendar.MONTH, 1);
+        nextStartTime = cal.getTimeInMillis();
+    }
+
+    public byte[] createFakeIP() {
+        ByteBuffer bb = ByteBuffer.allocate(8);
+        bb.putLong(System.currentTimeMillis());
+        bb.position(4);
+        byte[] fakeIP = new byte[4];
+        bb.get(fakeIP);
+        return fakeIP;
+    }
+}
+    
diff --git a/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/package-info.java b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/package-info.java
new file mode 100644
index 0000000..e64f66b
--- /dev/null
+++ b/remoting-core/remoting-impl/src/main/java/org/apache/rocketmq/remoting/package-info.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**
+ * This package contains all the transport classes that can be reused any times.
+ *
+ * Remoting wire-format protocol description:
+ *
+ * <pre>
+ * 2015-04-29 16:07:14 v1.0
+ * 2016-04-23 16:18:05 v2.0
+ * 2016-05-31 09:33:11 v3.0
+ * 2016-11-10 09:33:11 v3.1 remove deprecated tag field
+ *
+ *
+ * 1.Protocol Type                            1 byte
+ * 2.Total Length                             4 byte,exclude protocol type size
+ * 3.RequestID                                4 byte,used for repeatable requests,connection reuse.an requestID string
+ * representing a client-generated, globally unique for some time unit, identifier for the request
+ * 4.Serializer Type                          1 byte
+ * 5.Traffic Type                             1 byte,0-sync;1-async;2-oneway;3-response
+ * 6.OpCode Length                            2 byte
+ * 7.OpCode                                   variant length,utf8 string
+ * 8.Remark Length                            2 byte
+ * 9.Remark                                   variant length,utf8 string
+ * 10.Properties Size                         2 byte
+ * Property Length                            2 byte
+ * Property Body                              variant length,utf8,Key\nValue
+ * 11.Inbound or OutBound payload length      4 byte
+ * 12.Inbound or OutBound payload             variant length, max size limitation is 16M
+ * 13.Extra payload                           variant length
+ *
+ * </pre>
+ */
+package org.apache.rocketmq.remoting;
\ No newline at end of file
diff --git a/style/copyright/Apache.xml b/style/copyright/Apache.xml
new file mode 100644
index 0000000..7ca71b5
--- /dev/null
+++ b/style/copyright/Apache.xml
@@ -0,0 +1,24 @@
+<!--
+  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.
+  -->
+
+<component name="CopyrightManager">
+    <copyright>
+        <option name="myName" value="Apache"/>
+        <option name="notice"
+                value="Licensed to the Apache Software Foundation (ASF) under one or more&#10;contributor license agreements.  See the NOTICE file distributed with&#10;this work for additional information regarding copyright ownership.&#10;The ASF licenses this file to You under the Apache License, Version 2.0&#10;(the &quot;License&quot;); you may not use this file except in compliance with&#10;the License.  You may obtain a copy of the License at&#10;&#10;    http://www.apache.org/lice [...]
+    </copyright>
+</component>
\ No newline at end of file
diff --git a/style/copyright/profiles_settings.xml b/style/copyright/profiles_settings.xml
new file mode 100644
index 0000000..d326b8c
--- /dev/null
+++ b/style/copyright/profiles_settings.xml
@@ -0,0 +1,64 @@
+<!--
+  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.
+  -->
+
+<component name="CopyrightManager">
+    <settings default="Apache">
+        <module2copyright>
+            <element module="All" copyright="Apache"/>
+        </module2copyright>
+        <LanguageOptions name="GSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="HTML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JAVA">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="addBlankAfter" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JSPX">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="MXML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="Properties">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="SPI">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="XML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="__TEMPLATE__">
+            <option name="separateBefore" value="true"/>
+            <option name="lenBefore" value="1"/>
+        </LanguageOptions>
+    </settings>
+</component>
\ No newline at end of file
diff --git a/style/rmq_checkstyle.xml b/style/rmq_checkstyle.xml
new file mode 100644
index 0000000..e93b353
--- /dev/null
+++ b/style/rmq_checkstyle.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<!--Refer http://checkstyle.sourceforge.net/reports/google-java-style.html#s2.2-file-encoding -->
+<module name="Checker">
+
+    <property name="localeLanguage" value="en"/>
+
+    <!--To configure the check to report on the first instance in each file-->
+    <module name="FileTabCharacter"/>
+
+    <!-- header -->
+    <module name="RegexpHeader">
+        <property name="header" value="/\*\nLicensed to the Apache Software Foundation*"/>
+        <property name="fileExtensions" value="java"/>
+    </module>
+
+    <module name="RegexpHeader">
+        <property name="header" value="#[\s]*Licensed to the Apache Software Foundation*"/>
+        <property name="fileExtensions" value="properties"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="System\.out\.println"/>
+        <property name="message" value="Prohibit invoking System.out.println in source code !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//FIXME"/>
+        <property name="message" value="Recommended fix FIXME task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//TODO"/>
+        <property name="message" value="Recommended fix TODO task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="@alibaba"/>
+        <property name="message" value="Recommended remove @alibaba keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@taobao"/>
+        <property name="message" value="Recommended remove @taobao keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@author"/>
+        <property name="message" value="Recommended remove @author tag in javadoc!"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format"
+                  value=".*[\u3400-\u4DB5\u4E00-\u9FA5\u9FA6-\u9FBB\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9\uFF00-\uFFEF\u2E80-\u2EFF\u3000-\u303F\u31C0-\u31EF]+.*"/>
+        <property name="message" value="Not allow chinese character !"/>
+    </module>
+
+    <module name="FileLength">
+        <property name="max" value="3000"/>
+    </module>
+
+    <module name="TreeWalker">
+
+        <module name="UnusedImports">
+            <property name="processJavadoc" value="true"/>
+        </module>
+        <module name="RedundantImport"/>
+
+        <!--<module name="IllegalImport" />-->
+
+        <!--Checks that classes that override equals() also override hashCode()-->
+        <module name="EqualsHashCode"/>
+        <!--Checks for over-complicated boolean expressions. Currently finds code like if (topic == true), topic || true, !false, etc.-->
+        <module name="SimplifyBooleanExpression"/>
+        <module name="OneStatementPerLine"/>
+        <module name="UnnecessaryParentheses"/>
+        <!--Checks for over-complicated boolean return statements. For example the following code-->
+        <module name="SimplifyBooleanReturn"/>
+
+        <!--Check that the default is after all the cases in producerGroup switch statement-->
+        <module name="DefaultComesLast"/>
+        <!--Detects empty statements (standalone ";" semicolon)-->
+        <module name="EmptyStatement"/>
+        <!--Checks that long constants are defined with an upper ell-->
+        <module name="UpperEll"/>
+        <module name="ConstantName">
+            <property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)|(^log$)"/>
+        </module>
+        <!--Checks that local, non-final variable names conform to producerGroup format specified by the format property-->
+        <module name="LocalVariableName"/>
+        <!--Validates identifiers for local, final variables, including catch parameters-->
+        <module name="LocalFinalVariableName"/>
+        <!--Validates identifiers for non-static fields-->
+        <module name="MemberName"/>
+        <!--Validates identifiers for class type parameters-->
+        <module name="ClassTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <!--Validates identifiers for method type parameters-->
+        <module name="MethodTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+        <!--Checks that there are no import statements that use the * notation-->
+        <module name="AvoidStarImport"/>
+
+        <!--whitespace-->
+        <module name="GenericWhitespace"/>
+        <!--<module name="NoWhitespaceBefore"/>-->
+        <!--<module name="NoWhitespaceAfter"/>-->
+        <module name="WhitespaceAround">
+            <property name="allowEmptyConstructors" value="true"/>
+            <property name="allowEmptyMethods" value="true"/>
+        </module>
+        <module name="Indentation"/>
+        <module name="MethodParamPad"/>
+        <module name="ParenPad"/>
+        <module name="TypecastParenPad"/>
+    </module>
+</module>
diff --git a/style/rmq_codeStyle.xml b/style/rmq_codeStyle.xml
new file mode 100644
index 0000000..7c7ce54
--- /dev/null
+++ b/style/rmq_codeStyle.xml
@@ -0,0 +1,143 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<code_scheme name="rocketmq">
+    <option name="USE_SAME_INDENTS" value="true"/>
+    <option name="IGNORE_SAME_INDENTS_FOR_LANGUAGES" value="true"/>
+    <option name="OTHER_INDENT_OPTIONS">
+        <value>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+            <option name="USE_TAB_CHARACTER" value="false"/>
+            <option name="SMART_TABS" value="false"/>
+            <option name="LABEL_INDENT_SIZE" value="0"/>
+            <option name="LABEL_INDENT_ABSOLUTE" value="false"/>
+            <option name="USE_RELATIVE_INDENTS" value="false"/>
+        </value>
+    </option>
+    <option name="PREFER_LONGER_NAMES" value="false"/>
+    <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+        <value/>
+    </option>
+    <option name="IMPORT_LAYOUT_TABLE">
+        <value>
+            <package name="" withSubpackages="true" static="false"/>
+            <emptyLine/>
+            <package name="" withSubpackages="true" static="true"/>
+        </value>
+    </option>
+    <option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
+    <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
+    <option name="JD_P_AT_EMPTY_LINES" value="false"/>
+    <option name="JD_KEEP_INVALID_TAGS" value="false"/>
+    <option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true"/>
+    <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+    <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+    <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+    <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+    <option name="WHILE_ON_NEW_LINE" value="true"/>
+    <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+    <option name="ALIGN_MULTILINE_FOR" value="false"/>
+    <option name="SPACE_AFTER_TYPE_CAST" value="true"/>
+    <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+    <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+    <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+    <option name="LABELED_STATEMENT_WRAP" value="1"/>
+    <option name="WRAP_COMMENTS" value="true"/>
+    <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+    <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+    <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+    <JavaCodeStyleSettings>
+        <option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
+    </JavaCodeStyleSettings>
+    <XML>
+        <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
+    </XML>
+    <ADDITIONAL_INDENT_OPTIONS fileType="haml">
+        <option name="INDENT_SIZE" value="2"/>
+    </ADDITIONAL_INDENT_OPTIONS>
+    <codeStyleSettings language="Groovy">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="HOCON">
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="JAVA">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+        <option name="LABELED_STATEMENT_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="JSON">
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="Scala">
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="XML">
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+</code_scheme>
\ No newline at end of file