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

gosonzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new 32a654b17 [INLONG-7950][DataProxy] Optimize the implementation logic 
of the Source (#8041)
32a654b17 is described below

commit 32a654b17dfcba090ab022e8359e49e5e818fc23
Author: Goson Zhang <[email protected]>
AuthorDate: Thu May 18 18:55:18 2023 +0800

    [INLONG-7950][DataProxy] Optimize the implementation logic of the Source 
(#8041)
---
 .../inlong/common/enums/DataProxyErrCode.java      |  20 +
 .../apache/inlong/dataproxy/base/SinkRspEvent.java |  12 +-
 .../inlong/dataproxy/consts/StatConstants.java     |  29 +-
 .../dataproxy/sink/mq/OrderBatchPackProfileV0.java |   6 +-
 .../dataproxy/source/ServerMessageHandler.java     |   2 +-
 .../inlong/dataproxy/source2/BaseSource.java       | 544 ++++++++++++++++
 .../dataproxy/source2/InLongMessageFactory.java    |  77 +++
 .../dataproxy/source2/InLongMessageHandler.java    | 681 +++++++++++++++++++++
 .../inlong/dataproxy/source2/SimpleTcpSource.java  | 153 +++++
 .../inlong/dataproxy/source2/SimpleUdpSource.java  |  82 +++
 .../inlong/dataproxy/source2/SourceConstants.java  | 202 ++++++
 .../dataproxy/source2/v0msg/AbsV0MsgCodec.java     | 223 +++++++
 .../dataproxy/source2/v0msg/CodecBinMsg.java       | 363 +++++++++++
 .../dataproxy/source2/v0msg/CodecTextMsg.java      | 257 ++++++++
 .../dataproxy/source2/v0msg/MsgFieldConsts.java    |  74 +++
 .../inlong/dataproxy/utils/AddressUtils.java       |  24 +-
 .../inlong/dataproxy/utils/MessageUtils.java       |   6 +-
 17 files changed, 2732 insertions(+), 23 deletions(-)

diff --git 
a/inlong-common/src/main/java/org/apache/inlong/common/enums/DataProxyErrCode.java
 
b/inlong-common/src/main/java/org/apache/inlong/common/enums/DataProxyErrCode.java
index 61953ba99..263af3678 100644
--- 
a/inlong-common/src/main/java/org/apache/inlong/common/enums/DataProxyErrCode.java
+++ 
b/inlong-common/src/main/java/org/apache/inlong/common/enums/DataProxyErrCode.java
@@ -17,6 +17,8 @@
 
 package org.apache.inlong.common.enums;
 
+import org.apache.commons.lang3.math.NumberUtils;
+
 /**
  * Enum of data proxy error code.
  */
@@ -25,13 +27,23 @@ public enum DataProxyErrCode {
     SUCCESS(0, "Ok"),
 
     SINK_SERVICE_UNREADY(1, "Service not ready"),
+    SERVICE_CLOSED(2, "Service closed"),
+    CONF_SERVICE_UNREADY(3, "Configure Service not ready"),
     ILLEGAL_VISIT_IP(10, "Illegal visit ip"),
 
+    FIELD_VALUE_NOT_EQUAL(95, "Field value not equal"),
+    UNCOMPRESS_DATA_ERROR(96, "Uncompress data error"),
+
     MISS_REQUIRED_GROUPID_ARGUMENT(100, "Parameter groupId is required"),
     MISS_REQUIRED_STREAMID_ARGUMENT(101, "Parameter streamId is required"),
     MISS_REQUIRED_DT_ARGUMENT(102, "Parameter dt is required"),
     MISS_REQUIRED_BODY_ARGUMENT(103, "Parameter body is required"),
     BODY_EXCEED_MAX_LEN(104, "Body length exceed the maximum length"),
+    BODY_LENGTH_ZERO(105, "Body length is 0"),
+    BODY_LENGTH_LESS_ZERO(106, "Body length less than 0"),
+    ATTR_LENGTH_LESS_ZERO(107, "Attribute length less than 0"),
+    ERROR_PROCESS_LOGIC(108, "Wrong data processing logic"),
+    SPLIT_ATTR_ERROR(109, "Split attributes failure"),
 
     UNSUPPORTED_MSG_TYPE(110, "Unsupported msgType"),
     EMPTY_MSG(111, "Empty message"),
@@ -46,6 +58,8 @@ public enum DataProxyErrCode {
     MQ_RETURN_ERROR(119, "MQ client return error"),
 
     DUPLICATED_MESSAGE(120, "Duplicated message"),
+    GROUPID_OR_STREAMID_NOT_CONFIGURE(121, "GroupId or StreamId not found in 
configure"),
+    GROUPID_OR_STREAMID_INCONSTANT(122, "GroupId or StreamId inconstant"),
 
     UNKNOWN_ERROR(Integer.MAX_VALUE, "Unknown error");
 
@@ -78,4 +92,10 @@ public enum DataProxyErrCode {
     public String getErrMsg() {
         return errMsg;
     }
+
+    public static String getErrMsg(String errCode) {
+        int codeVal = NumberUtils.toInt(errCode, Integer.MAX_VALUE);
+        return valueOf(codeVal).errMsg;
+    }
+
 }
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/base/SinkRspEvent.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/base/SinkRspEvent.java
index ce79f0f4e..601f60e29 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/base/SinkRspEvent.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/base/SinkRspEvent.java
@@ -17,21 +17,21 @@
 
 package org.apache.inlong.dataproxy.base;
 
-import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.Channel;
 import java.util.Map;
 import org.apache.flume.Event;
 import org.apache.inlong.common.msg.MsgType;
 
 public class SinkRspEvent implements Event {
 
-    private ChannelHandlerContext ctx;
+    private Channel channel;
     private MsgType msgType;
     private Event event;
 
-    public SinkRspEvent(Event event, MsgType msgType, ChannelHandlerContext 
ctx) {
+    public SinkRspEvent(Event event, MsgType msgType, Channel channel) {
         this.event = event;
         this.msgType = msgType;
-        this.ctx = ctx;
+        this.channel = channel;
     }
 
     @Override
@@ -59,8 +59,8 @@ public class SinkRspEvent implements Event {
      *
      * @return ctx
      */
-    public ChannelHandlerContext getCtx() {
-        return ctx;
+    public Channel getChannel() {
+        return channel;
     }
 
     /**
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/consts/StatConstants.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/consts/StatConstants.java
index b967e43f5..07b24c26b 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/consts/StatConstants.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/consts/StatConstants.java
@@ -27,11 +27,34 @@ public class StatConstants {
     public static final java.lang.String METASINK_NOSLAVE = "metasink.noslave";
     public static final java.lang.String METASINK_MSG_NOTOPIC = 
"metasink.msgnotopic";
     public static final java.lang.String METASINK_PROCESS_SPEED = 
"metasink.process.speed";
-    public static final java.lang.String EVENT_SUCCESS = "socketmsg.success";
-    public static final java.lang.String EVENT_DROPPED = "socketmsg.dropped";
-    public static final java.lang.String EVENT_EMPTY = "socketmsg.empty";
     public static final java.lang.String EVENT_OTHEREXP = "socketmsg.otherexp";
     public static final java.lang.String EVENT_INVALID = "socketmsg.invalid";
+    public static final java.lang.String EVENT_LINKS_OVERMAX = "links.overmax";
+    public static final java.lang.String EVENT_LINKS_ILLEGAL = "links.illegal";
+    public static final java.lang.String EVENT_LINKS_IN = "links.linkin";
+    public static final java.lang.String EVENT_LINKS_OUT = "links.linkout";
+    public static final java.lang.String EVENT_LINKS_EXCEPTION = 
"links.exception";
+    public static final java.lang.String EVENT_EMPTY = "socketmsg.empty";
+    public static final java.lang.String EVENT_OVERMAXLEN = 
"socketmsg.overmaxlen";
+    public static final java.lang.String EVENT_NOTEQUALLEN = 
"socketmsg.notequallen";
+    public static final java.lang.String EVENT_MSGUNKNOWN_V0 = 
"socketmsg.unknownV0";
+    public static final java.lang.String EVENT_MSGUNKNOWN_V1 = 
"socketmsg.unknownV1";
+    public static final java.lang.String EVENT_MALFORMED = 
"socketmsg.malformed";
+    public static final java.lang.String EVENT_NOBODY = "socketmsg.nobody";
+    public static final java.lang.String EVENT_NEGBODY = "socketmsg.negbody";
+    public static final java.lang.String EVENT_NEGATTR = "socketmsg.negattr";
+    public static final java.lang.String EVENT_INVALIDATTR = 
"socketmsg.invattr";
+    public static final java.lang.String EVENT_UNSUPMSG = "socketmsg.unsupmsg";
+    public static final java.lang.String EVENT_UNPRESSEXP = 
"socketmsg.upressexp";
+    public static final java.lang.String EVENT_WITHOUTGROUPID = 
"socketmsg.wogroupid";
+    public static final java.lang.String EVENT_INCONSGROUPORSTREAMID = 
"socketmsg.inconsids";
+    public static final java.lang.String EVENT_CHANNEL_NOT_WRITABLE = 
"socketch.notwritable";
+    public static final java.lang.String EVENT_SERVICE_CLOSED = 
"source.srvclosed";
+    public static final java.lang.String EVENT_SERVICE_UNREADY = 
"sink.unready";
+    public static final java.lang.String EVENT_NOTOPIC = "config.notopic";
+    public static final java.lang.String EVENT_POST_SUCCESS = 
"socketmsg.success";
+    public static final java.lang.String EVENT_POST_DROPPED = 
"socketmsg.dropped";
+
     public static final java.lang.String AGENT_MESSAGES_SENT_SUCCESS = 
"agent.messages.success";
     public static final java.lang.String AGENT_PACKAGES_SENT_SUCCESS = 
"agent.packages.success";
     public static final java.lang.String MSG_COUNTER_KEY = "msgcnt";
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/sink/mq/OrderBatchPackProfileV0.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/sink/mq/OrderBatchPackProfileV0.java
index 299a378b4..9faadf9dc 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/sink/mq/OrderBatchPackProfileV0.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/sink/mq/OrderBatchPackProfileV0.java
@@ -92,14 +92,14 @@ public class OrderBatchPackProfileV0 extends 
BatchPackProfile {
             }
             return;
         }
-        if (orderProfile.getCtx() != null && 
orderProfile.getCtx().channel().isActive()) {
-            orderProfile.getCtx().channel().eventLoop().execute(() -> {
+        if (orderProfile.getChannel() != null && 
orderProfile.getChannel().isActive()) {
+            orderProfile.getChannel().eventLoop().execute(() -> {
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("order message rsp: seqId = {}, inlongGroupId = 
{}, inlongStreamId = {}", sequenceId,
                             this.getInlongGroupId(), this.getInlongStreamId());
                 }
                 ByteBuf binBuffer = getResponsePackage("", 
MsgType.MSG_BIN_MULTI_BODY, sequenceId);
-                orderProfile.getCtx().writeAndFlush(binBuffer);
+                orderProfile.getChannel().writeAndFlush(binBuffer);
             });
         }
     }
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source/ServerMessageHandler.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source/ServerMessageHandler.java
index 085dd6258..9f4d83d97 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source/ServerMessageHandler.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source/ServerMessageHandler.java
@@ -524,7 +524,7 @@ public class ServerMessageHandler extends 
ChannelInboundHandlerAdapter {
                 Pair<Boolean, String> evenProcType =
                         MessageUtils.getEventProcType(syncSend, proxySend);
                 if (evenProcType.getLeft()) {
-                    event = new SinkRspEvent(event, msgType, ctx);
+                    event = new SinkRspEvent(event, msgType, ctx.channel());
                 }
                 // build metric data item
                 long longDataTime = Long.parseLong(strDataTime);
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/BaseSource.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/BaseSource.java
new file mode 100644
index 000000000..6fd784681
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/BaseSource.java
@@ -0,0 +1,544 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+import com.google.common.base.Preconditions;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.flume.ChannelSelector;
+import org.apache.flume.Context;
+import org.apache.flume.EventDrivenSource;
+import org.apache.flume.FlumeException;
+import org.apache.flume.conf.Configurable;
+import org.apache.flume.source.AbstractSource;
+import org.apache.inlong.common.metric.MetricRegister;
+import org.apache.inlong.common.monitor.MonitorIndex;
+import org.apache.inlong.common.monitor.MonitorIndexExt;
+import org.apache.inlong.dataproxy.admin.ProxyServiceMBean;
+import org.apache.inlong.dataproxy.channel.FailoverChannelProcessor;
+import org.apache.inlong.dataproxy.config.CommonConfigHolder;
+import org.apache.inlong.dataproxy.metrics.DataProxyMetricItemSet;
+import org.apache.inlong.dataproxy.utils.ConfStringUtils;
+import org.apache.inlong.dataproxy.utils.FailoverChannelProcessorHolder;
+import org.apache.inlong.sdk.commons.admin.AdminServiceRegister;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+import java.util.Map;
+
+/**
+ * source base class
+ *
+ */
+public abstract class BaseSource
+        extends
+            AbstractSource
+        implements
+            ProxyServiceMBean,
+            EventDrivenSource,
+            Configurable {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(BaseSource.class);
+
+    protected Context context;
+    // whether source reject service
+    protected volatile boolean isRejectService = false;
+    // source service host
+    protected String srcHost;
+    // source serviced port
+    protected int srcPort;
+    protected String strPort;
+    // message factory name
+    protected String msgFactoryName;
+    // message handler name
+    protected String messageHandlerName;
+    // source default topic
+    protected String defTopic = "";
+    // source default append attribute
+    protected String defAttr = "";
+    // allowed max message length
+    protected int maxMsgLength;
+    // whether compress message
+    protected boolean isCompressed;
+    // whether filter empty message
+    protected boolean filterEmptyMsg;
+    // whether custom channel processor
+    protected boolean customProcessor;
+    // max netty worker threads
+    protected int maxWorkerThreads;
+    // max netty accept threads
+    protected int maxAcceptThreads;
+    // max read idle time
+    protected long maxReadIdleTimeMs;
+    // max connection count
+    protected int maxConnections;
+    // netty parameters
+    protected EventLoopGroup acceptorGroup;
+    protected EventLoopGroup workerGroup;
+    protected ChannelGroup allChannels;
+    protected ChannelFuture channelFuture;
+    // receive buffer size
+    protected int maxRcvBufferSize;
+    // send buffer size
+    protected int maxSendBufferSize;
+    // file metric statistic
+    protected boolean fileMetricOn;
+    protected int monitorStatInvlSec;
+    protected int maxMonitorStatCnt;
+    protected MonitorIndex monitorIndex = null;
+    private MonitorIndexExt monitorIndexExt = null;
+    // metric set
+    protected DataProxyMetricItemSet metricItemSet;
+
+    public BaseSource() {
+        super();
+        allChannels = new DefaultChannelGroup("DefaultChannelGroup", 
GlobalEventExecutor.INSTANCE);
+    }
+
+    @Override
+    public void configure(Context context) {
+        this.context = context;
+        this.srcHost = getHostIp(context);
+        this.srcPort = getHostPort(context);
+        this.strPort = String.valueOf(this.srcPort);
+        // get message factory
+        String tmpVal = 
context.getString(SourceConstants.SRCCXT_MSG_FACTORY_NAME,
+                InLongMessageFactory.class.getName()).trim();
+        Preconditions.checkArgument(StringUtils.isNotBlank(tmpVal),
+                SourceConstants.SRCCXT_MSG_FACTORY_NAME + " config is blank");
+        this.msgFactoryName = tmpVal.trim();
+        // get message handler
+        tmpVal = context.getString(SourceConstants.SRCCXT_MESSAGE_HANDLER_NAME,
+                InLongMessageHandler.class.getName().trim());
+        Preconditions.checkArgument(StringUtils.isNotBlank(tmpVal),
+                SourceConstants.SRCCXT_MESSAGE_HANDLER_NAME + " config is 
blank");
+        this.messageHandlerName = tmpVal;
+        // get default topic
+        tmpVal = context.getString(SourceConstants.SRCCXT_DEF_TOPIC);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            this.defTopic = tmpVal.trim();
+        }
+        // get default attributes
+        tmpVal = context.getString(SourceConstants.SRCCXT_DEF_ATTR);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            this.defAttr = tmpVal.trim();
+        }
+        // get allowed max message length
+        this.maxMsgLength = getIntValue(context, 
SourceConstants.SRCCXT_MAX_MSG_LENGTH,
+                SourceConstants.VAL_DEF_MAX_MSG_LENGTH);
+        Preconditions.checkArgument((this.maxMsgLength >= 
SourceConstants.VAL_MIN_MAX_MSG_LENGTH
+                && this.maxMsgLength <= 
SourceConstants.VAL_MAX_MAX_MSG_LENGTH),
+                SourceConstants.SRCCXT_MAX_MSG_LENGTH + " must be in ["
+                        + SourceConstants.VAL_MIN_MAX_MSG_LENGTH + ", "
+                        + SourceConstants.VAL_MAX_MAX_MSG_LENGTH + "]");
+        // get whether compress message
+        this.isCompressed = 
context.getBoolean(SourceConstants.SRCCXT_MSG_COMPRESSED,
+                SourceConstants.VAL_DEF_MSG_COMPRESSED);
+        // get whether filter empty message
+        this.filterEmptyMsg = 
context.getBoolean(SourceConstants.SRCCXT_FILTER_EMPTY_MSG,
+                SourceConstants.VAL_DEF_FILTER_EMPTY_MSG);
+        // get whether custom channel processor
+        this.customProcessor = 
context.getBoolean(SourceConstants.SRCCXT_CUSTOM_CHANNEL_PROCESSOR,
+                SourceConstants.VAL_DEF_CUSTOM_CH_PROCESSOR);
+        // get max accept threads
+        this.maxAcceptThreads = getIntValue(context, 
SourceConstants.SRCCXT_MAX_ACCEPT_THREADS,
+                SourceConstants.VAL_DEF_NET_ACCEPT_THREADS);
+        Preconditions.checkArgument((this.maxAcceptThreads >= 
SourceConstants.VAL_MIN_ACCEPT_THREADS
+                && this.maxAcceptThreads <= 
SourceConstants.VAL_MAX_ACCEPT_THREADS),
+                SourceConstants.SRCCXT_MAX_ACCEPT_THREADS + " must be in ["
+                        + SourceConstants.VAL_MIN_ACCEPT_THREADS + ", "
+                        + SourceConstants.VAL_MAX_ACCEPT_THREADS + "]");
+        // get max worker threads
+        this.maxWorkerThreads = getIntValue(context, 
SourceConstants.SRCCXT_MAX_WORKER_THREADS,
+                SourceConstants.VAL_DEF_WORKER_THREADS);
+        Preconditions.checkArgument((this.maxWorkerThreads >= 
SourceConstants.VAL_MIN_WORKER_THREADS
+                && this.maxWorkerThreads <= 
SourceConstants.VAL_MAX_WORKER_THREADS),
+                SourceConstants.SRCCXT_MAX_WORKER_THREADS + " must be in ["
+                        + SourceConstants.VAL_MIN_WORKER_THREADS + ", "
+                        + SourceConstants.VAL_MAX_WORKER_THREADS + "]");
+        // get max read idle time
+        this.maxReadIdleTimeMs = getLongValue(context, 
SourceConstants.SRCCXT_MAX_READ_IDLE_TIME_MS,
+                SourceConstants.VAL_DEF_READ_IDLE_TIME_MS);
+        Preconditions.checkArgument((this.maxReadIdleTimeMs >= 
SourceConstants.VAL_MIN_READ_IDLE_TIME_MS),
+                SourceConstants.SRCCXT_MAX_READ_IDLE_TIME_MS + " must be >= "
+                        + SourceConstants.VAL_MIN_READ_IDLE_TIME_MS);
+        // get file metric statistic
+        this.monitorStatInvlSec = getIntValue(context, 
SourceConstants.SRCCXT_STAT_INTERVAL_SEC,
+                SourceConstants.VAL_DEF_STAT_INVL_SEC);
+        Preconditions.checkArgument((this.monitorStatInvlSec >= 
SourceConstants.VAL_MIN_STAT_INVL_SEC),
+                SourceConstants.SRCCXT_STAT_INTERVAL_SEC + " must be >= "
+                        + SourceConstants.VAL_MIN_STAT_INVL_SEC);
+        // get max monitor key count
+        this.maxMonitorStatCnt = getIntValue(context, 
SourceConstants.SRCCXT_MAX_MONITOR_STAT_CNT,
+                SourceConstants.VAL_DEF_MON_STAT_CNT);
+        Preconditions.checkArgument(this.maxMonitorStatCnt >= 
SourceConstants.VAL_MIN_MON_STAT_CNT,
+                SourceConstants.SRCCXT_MAX_MONITOR_STAT_CNT + " must be >= "
+                        + SourceConstants.VAL_MIN_MON_STAT_CNT);
+        // get max connect count
+        this.maxConnections = getIntValue(context, 
SourceConstants.SRCCXT_MAX_CONNECTION_CNT,
+                SourceConstants.VAL_DEF_MAX_CONNECTION_CNT);
+        Preconditions.checkArgument(this.maxConnections >= 
SourceConstants.VAL_MIN_CONNECTION_CNT,
+                SourceConstants.SRCCXT_MAX_CONNECTION_CNT + " must be >= "
+                        + SourceConstants.VAL_MIN_CONNECTION_CNT);
+        // get whether enable file metric
+        this.fileMetricOn = 
context.getBoolean(SourceConstants.SRCCXT_FILE_METRIC_ON,
+                SourceConstants.VAL_DEF_FILE_METRIC_ON);
+        // get max receive buffer size
+        this.maxRcvBufferSize = getIntValue(context, 
SourceConstants.SRCCXT_RECEIVE_BUFFER_SIZE,
+                SourceConstants.VAL_DEF_RECEIVE_BUFFER_SIZE);
+        Preconditions.checkArgument(this.maxRcvBufferSize >= 
SourceConstants.VAL_MIN_RECEIVE_BUFFER_SIZE,
+                SourceConstants.SRCCXT_RECEIVE_BUFFER_SIZE + " must be >= "
+                        + SourceConstants.VAL_MIN_RECEIVE_BUFFER_SIZE);
+        if (this.maxRcvBufferSize > 
SourceConstants.VAL_MAX_RECEIVE_BUFFER_SIZE) {
+            this.maxRcvBufferSize = 
SourceConstants.VAL_MAX_RECEIVE_BUFFER_SIZE;
+        }
+        // get max send buffer size
+        this.maxSendBufferSize = getIntValue(context, 
SourceConstants.SRCCXT_SEND_BUFFER_SIZE,
+                SourceConstants.VAL_DEF_SEND_BUFFER_SIZE);
+        Preconditions.checkArgument(this.maxSendBufferSize >= 
SourceConstants.VAL_MIN_SEND_BUFFER_SIZE,
+                SourceConstants.SRCCXT_SEND_BUFFER_SIZE + " must be >= "
+                        + SourceConstants.VAL_MIN_SEND_BUFFER_SIZE);
+        if (this.maxSendBufferSize > SourceConstants.VAL_MAX_SEND_BUFFER_SIZE) 
{
+            this.maxSendBufferSize = SourceConstants.VAL_MAX_SEND_BUFFER_SIZE;
+        }
+    }
+
+    @Override
+    public synchronized void start() {
+        if (customProcessor) {
+            ChannelSelector selector = getChannelProcessor().getSelector();
+            FailoverChannelProcessor newProcessor = new 
FailoverChannelProcessor(selector);
+            newProcessor.configure(this.context);
+            setChannelProcessor(newProcessor);
+            FailoverChannelProcessorHolder.setChannelProcessor(newProcessor);
+        }
+        super.start();
+        // initial metric item set
+        this.metricItemSet = new DataProxyMetricItemSet(
+                CommonConfigHolder.getInstance().getClusterName(), getName(), 
String.valueOf(srcPort));
+        MetricRegister.register(metricItemSet);
+        // init monitor logic
+        if (fileMetricOn) {
+            this.monitorIndex = new MonitorIndex("Source", monitorStatInvlSec, 
maxMonitorStatCnt);
+            this.monitorIndexExt = new MonitorIndexExt(
+                    "DataProxy_monitors#" + this.getProtocolName(), 
monitorStatInvlSec, maxMonitorStatCnt);
+        }
+        startSource();
+        // register
+        AdminServiceRegister.register(ProxyServiceMBean.MBEAN_TYPE, 
this.getName(), this);
+    }
+
+    @Override
+    public synchronized void stop() {
+        logger.info("[STOP {} SOURCE]{} stopping...", this.getProtocolName(), 
this.getName());
+        // close channels
+        if (!allChannels.isEmpty()) {
+            try {
+                allChannels.close().awaitUninterruptibly();
+            } catch (Exception e) {
+                logger.warn("Close {} netty channels throw exception", 
this.getName(), e);
+            } finally {
+                allChannels.clear();
+            }
+        }
+        // close channel future
+        if (channelFuture != null) {
+            try {
+                channelFuture.channel().closeFuture().sync();
+            } catch (InterruptedException e) {
+                logger.warn("Close {} channel future throw exception", 
this.getName(), e);
+            }
+        }
+        // stop super class
+        super.stop();
+        // stop file statistic index
+        if (fileMetricOn) {
+            if (monitorIndex != null) {
+                monitorIndex.shutDown();
+            }
+            if (monitorIndexExt != null) {
+                monitorIndexExt.shutDown();
+            }
+        }
+        logger.info("[STOP {} SOURCE]{} stopped", this.getProtocolName(), 
this.getName());
+    }
+
+    /**
+     * get metricItemSet
+     * @return the metricItemSet
+     */
+    public DataProxyMetricItemSet getMetricItemSet() {
+        return metricItemSet;
+    }
+
+    public Context getContext() {
+        return context;
+    }
+
+    public String getSrcHost() {
+        return srcHost;
+    }
+
+    public int getSrcPort() {
+        return srcPort;
+    }
+
+    public String getStrPort() {
+        return strPort;
+    }
+
+    public String getDefTopic() {
+        return defTopic;
+    }
+
+    public String getDefAttr() {
+        return defAttr;
+    }
+
+    public int getMaxMsgLength() {
+        return maxMsgLength;
+    }
+
+    public boolean isCompressed() {
+        return isCompressed;
+    }
+
+    public boolean isFilterEmptyMsg() {
+        return filterEmptyMsg;
+    }
+
+    public boolean isCustomProcessor() {
+        return customProcessor;
+    }
+
+    public int getMaxConnections() {
+        return maxConnections;
+    }
+
+    public ChannelGroup getAllChannels() {
+        return allChannels;
+    }
+
+    public long getMaxReadIdleTimeMs() {
+        return maxReadIdleTimeMs;
+    }
+
+    public String getMessageHandlerName() {
+        return messageHandlerName;
+    }
+
+    public int getMaxWorkerThreads() {
+        return maxWorkerThreads;
+    }
+
+    public void fileMetricEventInc(String eventKey) {
+        if (fileMetricOn) {
+            monitorIndexExt.incrementAndGet(eventKey);
+        }
+    }
+
+    public void fileMetricRecordAdd(String key, int cnt, int packCnt, long 
packSize, int failCnt) {
+        if (fileMetricOn) {
+            monitorIndex.addAndGet(key, cnt, packCnt, packSize, failCnt);
+        }
+    }
+
+    /**
+     * channel factory
+     * @return
+     */
+    public ChannelInitializer getChannelInitializerFactory() {
+        ChannelInitializer fac = null;
+        logger.info(this.getName() + " load msgFactory=" + msgFactoryName);
+        try {
+            Class<? extends ChannelInitializer> clazz =
+                    (Class<? extends ChannelInitializer>) 
Class.forName(msgFactoryName);
+            Constructor ctor = clazz.getConstructor(BaseSource.class);
+            logger.info("Using channel processor:{}", 
getChannelProcessor().getClass().getName());
+            fac = (ChannelInitializer) ctor.newInstance(this);
+        } catch (Exception e) {
+            logger.error("{} start error, fail to construct 
ChannelPipelineFactory with name {}",
+                    this.getName(), msgFactoryName, e);
+            stop();
+            throw new FlumeException(e.getMessage());
+        }
+        return fac;
+    }
+
+    public abstract String getProtocolName();
+
+    public abstract void startSource();
+
+    /**
+     * stopService
+     */
+    @Override
+    public void stopService() {
+        this.isRejectService = true;
+    }
+
+    /**
+     * recoverService
+     */
+    @Override
+    public void recoverService() {
+        this.isRejectService = false;
+    }
+
+    /**
+     * isRejectService
+     *
+     * @return
+     */
+    public boolean isRejectService() {
+        return isRejectService;
+    }
+
+    /**
+     * Get the configuration value of integer type from the context
+     *
+     * @param context  the context
+     * @param fieldKey the configure key
+     * @param defVal   the default value
+     *
+     * @return the configuration value
+     */
+    public int getIntValue(Context context, String fieldKey, int defVal) {
+        String tmpVal = context.getString(fieldKey);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            int result;
+            tmpVal = tmpVal.trim();
+            try {
+                result = Integer.parseInt(tmpVal);
+            } catch (Throwable e) {
+                throw new IllegalArgumentException(
+                        fieldKey + "(" + tmpVal + ") must specify an integer 
value!");
+            }
+            return result;
+        }
+        return defVal;
+    }
+
+    /**
+     * Get the configuration value of long type from the context
+     *
+     * @param context  the context
+     * @param fieldKey the configure key
+     * @param defVal   the default value
+     *
+     * @return the configuration value
+     */
+    public long getLongValue(Context context, String fieldKey, long defVal) {
+        String tmpVal = context.getString(fieldKey);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            long result;
+            tmpVal = tmpVal.trim();
+            try {
+                result = Long.parseLong(tmpVal);
+            } catch (Throwable e) {
+                throw new IllegalArgumentException(
+                        fieldKey + "(" + tmpVal + ") must specify an long 
value!");
+            }
+            return result;
+        }
+        return defVal;
+    }
+
+    /**
+     * getHostIp
+     *
+     * @param  context
+     * @return
+     */
+    private String getHostIp(Context context) {
+        String result = null;
+        // first get host ip from dataProxy.conf
+        String tmpVal = context.getString(SourceConstants.SRCCXT_CONFIG_HOST);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            tmpVal = tmpVal.trim();
+            Preconditions.checkArgument(ConfStringUtils.isValidIp(tmpVal),
+                    SourceConstants.SRCCXT_CONFIG_HOST + "(" + tmpVal + ") 
config in conf not valid");
+            result = tmpVal;
+        }
+        // second get host ip from system env
+        Map<String, String> envMap = System.getenv();
+        if (envMap.containsKey(SourceConstants.SYSENV_HOST_IP)) {
+            tmpVal = envMap.get(SourceConstants.SYSENV_HOST_IP);
+            Preconditions.checkArgument(ConfStringUtils.isValidIp(tmpVal),
+                    SourceConstants.SYSENV_HOST_IP + "(" + tmpVal + ") config 
in system env not valid");
+            result = tmpVal.trim();
+        }
+        if (StringUtils.isBlank(result)) {
+            result = SourceConstants.VAL_DEF_HOST_VALUE;
+        }
+        return result;
+    }
+
+    /**
+     * getHostPort
+     *
+     * @param  context
+     * @return
+     */
+    private int getHostPort(Context context) {
+        Integer result = null;
+        // first get host port from dataProxy.conf
+        String tmpVal = context.getString(SourceConstants.SRCCXT_CONFIG_PORT);
+        if (StringUtils.isNotBlank(tmpVal)) {
+            tmpVal = tmpVal.trim();
+            try {
+                result = Integer.parseInt(tmpVal);
+            } catch (Throwable e) {
+                throw new IllegalArgumentException(
+                        SourceConstants.SYSENV_HOST_PORT + "(" + tmpVal + ") 
config in conf not integer");
+            }
+        }
+        if (result != null) {
+            Preconditions.checkArgument(ConfStringUtils.isValidPort(result),
+                    SourceConstants.SRCCXT_CONFIG_PORT + "(" + result + ") 
config in conf not valid");
+        }
+        // second get host port from system env
+        Map<String, String> envMap = System.getenv();
+        if (envMap.containsKey(SourceConstants.SYSENV_HOST_PORT)) {
+            tmpVal = envMap.get(SourceConstants.SYSENV_HOST_PORT);
+            if (StringUtils.isNotBlank(tmpVal)) {
+                tmpVal = tmpVal.trim();
+                try {
+                    result = Integer.parseInt(tmpVal);
+                } catch (Throwable e) {
+                    throw new IllegalArgumentException(
+                            SourceConstants.SYSENV_HOST_PORT + "(" + tmpVal + 
") config in system env not integer");
+                }
+                
Preconditions.checkArgument(ConfStringUtils.isValidPort(result),
+                        SourceConstants.SYSENV_HOST_PORT + "(" + tmpVal + ") 
config in system env not valid");
+            }
+        }
+        if (result == null) {
+            throw new IllegalArgumentException("Required parameter " +
+                    SourceConstants.SRCCXT_CONFIG_PORT + " must exist and may 
not be null");
+        }
+        return result;
+    }
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageFactory.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageFactory.java
new file mode 100644
index 000000000..2dfe66df8
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageFactory.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.lang.reflect.Constructor;
+import java.util.concurrent.TimeUnit;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+
+public class InLongMessageFactory extends ChannelInitializer<SocketChannel> {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(InLongMessageFactory.class);
+
+    public static final int INLONG_LENGTH_FIELD_OFFSET = 0;
+    public static final int INLONG_LENGTH_FIELD_LENGTH = 4;
+    public static final int INLONG_LENGTH_ADJUSTMENT = -4;
+    public static final int INLONG_INITIAL_BYTES_TO_STRIP = 0;
+    public static final boolean DEFAULT_FAIL_FAST = true;
+
+    private BaseSource source;
+
+    /**
+     * get server factory
+     *
+     * @param source
+     */
+    public InLongMessageFactory(BaseSource source) {
+        this.source = source;
+    }
+
+    @Override
+    protected void initChannel(SocketChannel ch) throws Exception {
+
+        if (source.getProtocolName()
+                .equalsIgnoreCase(SourceConstants.SRC_PROTOCOL_TYPE_TCP)) {
+            ch.pipeline().addLast("messageDecoder", new 
LengthFieldBasedFrameDecoder(
+                    source.getMaxMsgLength(), INLONG_LENGTH_FIELD_OFFSET, 
INLONG_LENGTH_FIELD_LENGTH,
+                    INLONG_LENGTH_ADJUSTMENT, INLONG_INITIAL_BYTES_TO_STRIP, 
DEFAULT_FAIL_FAST));
+            ch.pipeline().addLast("readTimeoutHandler",
+                    new ReadTimeoutHandler(source.getMaxReadIdleTimeMs(), 
TimeUnit.MILLISECONDS));
+        }
+        // build message handler
+        if (source.getChannelProcessor() != null) {
+            try {
+                Class<? extends ChannelInboundHandlerAdapter> clazz =
+                        (Class<? extends ChannelInboundHandlerAdapter>) 
Class.forName(source.getMessageHandlerName());
+                Constructor<?> ctor = clazz.getConstructor(BaseSource.class);
+                ChannelInboundHandlerAdapter messageHandler =
+                        (ChannelInboundHandlerAdapter) 
ctor.newInstance(source);
+                ch.pipeline().addLast("messageHandler", messageHandler);
+            } catch (Exception e) {
+                LOG.error("{} newInstance {} failure!", source.getName(),
+                        source.getMessageHandlerName(), e);
+            }
+        }
+    }
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageHandler.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageHandler.java
new file mode 100644
index 000000000..e92a58b98
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/InLongMessageHandler.java
@@ -0,0 +1,681 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.flume.ChannelException;
+import org.apache.flume.Event;
+import org.apache.inlong.common.enums.DataProxyErrCode;
+import org.apache.inlong.common.monitor.LogCounter;
+import org.apache.inlong.common.msg.AttributeConstants;
+import org.apache.inlong.common.msg.MsgType;
+import org.apache.inlong.dataproxy.config.CommonConfigHolder;
+import org.apache.inlong.dataproxy.config.ConfigManager;
+import org.apache.inlong.dataproxy.consts.AttrConstants;
+import org.apache.inlong.dataproxy.consts.ConfigConstants;
+import org.apache.inlong.dataproxy.consts.StatConstants;
+import org.apache.inlong.dataproxy.metrics.DataProxyMetricItem;
+import org.apache.inlong.dataproxy.metrics.audit.AuditUtils;
+import org.apache.inlong.dataproxy.source.tcp.InlongTcpSourceCallback;
+import org.apache.inlong.dataproxy.source2.v0msg.AbsV0MsgCodec;
+import org.apache.inlong.dataproxy.source2.v0msg.CodecBinMsg;
+import org.apache.inlong.dataproxy.source2.v0msg.CodecTextMsg;
+import org.apache.inlong.dataproxy.utils.AddressUtils;
+import org.apache.inlong.dataproxy.utils.DateTimeUtils;
+import org.apache.inlong.sdk.commons.protocol.EventUtils;
+import org.apache.inlong.sdk.commons.protocol.ProxyEvent;
+import org.apache.inlong.sdk.commons.protocol.ProxyPackEvent;
+import org.apache.inlong.sdk.commons.protocol.ProxySdk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+import static 
org.apache.inlong.dataproxy.source2.InLongMessageFactory.INLONG_LENGTH_FIELD_LENGTH;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_ATTRLEN_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_BODYLEN_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_BODY_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_FIXED_CONTENT_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_FORMAT_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_TOTALLEN_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_HB_VERSION_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_FIXED_CONTENT_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_MAGIC;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.TXT_MSG_FIXED_CONTENT_SIZE;
+
+/**
+ * Server message handler
+ *
+ */
+public class InLongMessageHandler extends ChannelInboundHandlerAdapter {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(InLongMessageHandler.class);
+    // log print count
+    private static final LogCounter logCounter = new LogCounter(10, 100000, 30 
* 1000);
+
+    private static final int INLONG_MSG_V1 = 1;
+    private static final String DEFAULT_REMOTE_IDC_VALUE = "0";
+
+    private static final ConfigManager configManager = 
ConfigManager.getInstance();
+    private final BaseSource source;
+
+    /**
+     * Constructor
+     *
+     * @param source AbstractSource
+     */
+    public InLongMessageHandler(BaseSource source) {
+        this.source = source;
+    }
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws 
Exception {
+        if (msg == null) {
+            source.fileMetricEventInc(StatConstants.EVENT_EMPTY);
+            logger.debug("Get null msg, just skip!");
+            return;
+        }
+        ByteBuf cb = (ByteBuf) msg;
+        try {
+            int readableLength = cb.readableBytes();
+            if (readableLength == 0 && source.isFilterEmptyMsg()) {
+                cb.clear();
+                source.fileMetricEventInc(StatConstants.EVENT_EMPTY);
+                logger.debug("skip empty msg.");
+                return;
+            }
+            if (readableLength > source.getMaxMsgLength()) {
+                source.fileMetricEventInc(StatConstants.EVENT_OVERMAXLEN);
+                throw new Exception("Error msg, readableLength(" + 
readableLength +
+                        ") > max allowed message length (" + 
source.getMaxMsgLength() + ")");
+            }
+            // save index
+            cb.markReaderIndex();
+            // read total data length
+            int totalDataLen = cb.readInt();
+            if (readableLength < totalDataLen + INLONG_LENGTH_FIELD_LENGTH) {
+                // reset index when buffer is not satisfied.
+                cb.resetReaderIndex();
+                source.fileMetricEventInc(StatConstants.EVENT_NOTEQUALLEN);
+                throw new Exception("Error msg, channel buffer is not 
satisfied, and  readableLength="
+                        + readableLength + ", and totalPackLength=" + 
totalDataLen + " + 4");
+            }
+            // read type
+            int msgTypeValue = cb.readByte();
+            if (msgTypeValue == 0x0) {
+                // process v1 messsages
+                msgTypeValue = cb.readByte();
+                if (msgTypeValue == INLONG_MSG_V1) {
+                    // decode version 1
+                    int bodyLength = totalDataLen - 2;
+                    processV1Msg(ctx, cb, bodyLength);
+                } else {
+                    // unknown message type
+                    
source.fileMetricEventInc(StatConstants.EVENT_MSGUNKNOWN_V1);
+                    throw new Exception("Unknown V1 message version, version = 
" + msgTypeValue);
+                }
+            } else {
+                // process v0 messages
+                Channel channel = ctx.channel();
+                MsgType msgType = MsgType.valueOf(msgTypeValue);
+                final long msgRcvTime = System.currentTimeMillis();
+                if (MsgType.MSG_UNKNOWN == msgType) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_MSGUNKNOWN_V0);
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Received unknown message, channel {}", 
channel);
+                    }
+                    throw new Exception("Unknown V0 message type, type = " + 
msgTypeValue);
+                } else if (MsgType.MSG_HEARTBEAT == msgType) {
+                    // send response message
+                    flushV0MsgPackage(source, channel, 
buildHeartBeatMsgRspPackage(), MsgType.MSG_HEARTBEAT.name());
+                    return;
+                } else if (MsgType.MSG_BIN_HEARTBEAT == msgType) {
+                    procBinHeartbeatMsg(source, channel, cb, totalDataLen);
+                    return;
+                }
+                // process msgType in {2,3,4,5,6,7}
+                AbsV0MsgCodec msgCodec;
+                String strRemoteIP = AddressUtils.getChannelRemoteIP(channel);
+                // check whether totalDataLen is valid.
+                if (MsgType.MSG_BIN_MULTI_BODY == msgType) {
+                    if (totalDataLen < BIN_MSG_FIXED_CONTENT_SIZE) {
+                        
source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+                        String errMsg = String.format("Malformed msg, 
totalDataLen(%d) < min bin7-msg length(%d)",
+                                totalDataLen, BIN_MSG_FIXED_CONTENT_SIZE);
+                        if (logger.isDebugEnabled()) {
+                            logger.debug(errMsg + ", channel {}", channel);
+                        }
+                        throw new Exception(errMsg);
+                    }
+                    msgCodec = new CodecBinMsg(totalDataLen, msgTypeValue, 
msgRcvTime, strRemoteIP);
+                } else {
+                    if (totalDataLen < TXT_MSG_FIXED_CONTENT_SIZE) {
+                        
source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+                        String errMsg = String.format("Malformed msg, 
totalDataLen(%d) < min txt-msg length(%d)",
+                                totalDataLen, TXT_MSG_FIXED_CONTENT_SIZE);
+                        if (logger.isDebugEnabled()) {
+                            logger.debug(errMsg + ", channel {}", channel);
+                        }
+                        throw new Exception(errMsg);
+                    }
+                    msgCodec = new CodecTextMsg(totalDataLen, msgTypeValue, 
msgRcvTime, strRemoteIP);
+                }
+                // process request
+                processV0Msg(channel, cb, msgCodec);
+            }
+        } finally {
+            cb.release();
+        }
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        // check max allowed connection count
+        if (source.getAllChannels().size() >= source.getMaxConnections()) {
+            source.fileMetricEventInc(StatConstants.EVENT_LINKS_OVERMAX);
+            ctx.channel().disconnect();
+            ctx.channel().close();
+            logger.warn("{} refuse to connect = {} , connections = {}, 
maxConnections = {}",
+                    source.getName(), ctx.channel(), 
source.getAllChannels().size(), source.getMaxConnections());
+            return;
+        }
+        // check illegal ip
+        if (ConfigManager.getInstance().needChkIllegalIP()) {
+            String strRemoteIp = 
AddressUtils.getChannelRemoteIP(ctx.channel());
+            if (strRemoteIp != null
+                    && ConfigManager.getInstance().isIllegalIP(strRemoteIp)) {
+                source.fileMetricEventInc(StatConstants.EVENT_LINKS_ILLEGAL);
+                ctx.channel().disconnect();
+                ctx.channel().close();
+                logger.error(strRemoteIp + " is Illegal IP, so refuse it !");
+                return;
+            }
+        }
+        // add legal channel
+        source.getAllChannels().add(ctx.channel());
+        ctx.fireChannelActive();
+        source.fileMetricEventInc(StatConstants.EVENT_LINKS_IN);
+        logger.info("{} added new channel {}, current connections = {}, 
maxConnections = {}",
+                source.getName(), ctx.channel(), 
source.getAllChannels().size(), source.getMaxConnections());
+    }
+
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) {
+        logger.error("{} channel {} inactive", source.getName(), 
ctx.channel());
+        ctx.fireChannelInactive();
+        source.getAllChannels().remove(ctx.channel());
+        source.fileMetricEventInc(StatConstants.EVENT_LINKS_OUT);
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
+        logger.error("{} channel {} throw exception", source.getName(), 
ctx.channel(), cause);
+        ctx.fireExceptionCaught(cause);
+        if (ctx.channel() != null) {
+            try {
+                ctx.channel().disconnect();
+                ctx.channel().close();
+            } catch (Exception ex) {
+                //
+            }
+            source.getAllChannels().remove(ctx.channel());
+            source.fileMetricEventInc(StatConstants.EVENT_LINKS_EXCEPTION);
+        }
+        ctx.close();
+    }
+
+    private void processV0Msg(Channel channel, ByteBuf cb, AbsV0MsgCodec 
msgCodec) throws Exception {
+        final StringBuilder strBuff = new StringBuilder(512);
+        // decode the request message
+        if (!msgCodec.descMsg(source, cb)) {
+            responseV0Msg(channel, msgCodec, strBuff);
+            return;
+        }
+        // check service status.
+        if (source.isRejectService()) {
+            source.fileMetricEventInc(StatConstants.EVENT_SERVICE_CLOSED);
+            msgCodec.setFailureInfo(DataProxyErrCode.SERVICE_CLOSED);
+            responseV0Msg(channel, msgCodec, strBuff);
+            return;
+        }
+        // check if the node is linked to the Manager.
+        if (!ConfigManager.getInstance().isMqClusterReady()) {
+            source.fileMetricEventInc(StatConstants.EVENT_SERVICE_UNREADY);
+            msgCodec.setFailureInfo(DataProxyErrCode.SINK_SERVICE_UNREADY);
+            responseV0Msg(channel, msgCodec, strBuff);
+            return;
+        }
+        // valid and fill extra fields.
+        if (!msgCodec.validAndFillFields(source, strBuff)) {
+            responseV0Msg(channel, msgCodec, strBuff);
+            return;
+        }
+        // build InLong event.
+        Event event = msgCodec.encEventPackage(source, channel);
+        // build metric data item
+        long longDataTime = msgCodec.getDataTimeMs() / 1000 / 60 / 10;
+        longDataTime = longDataTime * 1000 * 60 * 10;
+        
strBuff.append(source.getProtocolName()).append(AttrConstants.SEPARATOR)
+                
.append(msgCodec.getTopicName()).append(AttrConstants.SEPARATOR)
+                .append(msgCodec.getStreamId()).append(AttrConstants.SEPARATOR)
+                
.append(msgCodec.getStrRemoteIP()).append(AttrConstants.SEPARATOR)
+                .append(source.getStrPort()).append(AttrConstants.SEPARATOR)
+                
.append(msgCodec.getMsgProcType()).append(AttrConstants.SEPARATOR)
+                .append(DateTimeUtils.ms2yyyyMMddHHmm(longDataTime))
+                .append(AttrConstants.SEPARATOR).append(
+                        
DateTimeUtils.ms2yyyyMMddHHmm(msgCodec.getMsgRcvTime()));
+        try {
+            source.getChannelProcessor().processEvent(event);
+            source.fileMetricEventInc(StatConstants.EVENT_POST_SUCCESS);
+            source.fileMetricRecordAdd(strBuff.toString(),
+                    msgCodec.getMsgCount(), 1, msgCodec.getBodyLength(), 0);
+            this.addMetric(true, event.getBody().length, event);
+            strBuff.delete(0, strBuff.length());
+        } catch (Throwable ex) {
+            logger.error("Error writting to channel, data will discard.", ex);
+            source.fileMetricEventInc(StatConstants.EVENT_POST_DROPPED);
+            source.fileMetricRecordAdd(strBuff.toString(), 0, 0, 0, 
msgCodec.getMsgCount());
+            this.addMetric(false, event.getBody().length, event);
+            strBuff.delete(0, strBuff.length());
+            throw new ChannelException("ProcessEvent error can't write event 
to channel.");
+        }
+    }
+
+    private void processV1Msg(ChannelHandlerContext ctx, ByteBuf cb, int 
bodyLength) throws Exception {
+        // read bytes
+        byte[] msgBytes = new byte[bodyLength];
+        cb.readBytes(msgBytes);
+        // decode
+        ProxySdk.MessagePack packObject = 
ProxySdk.MessagePack.parseFrom(msgBytes);
+        // reject service
+        if (source.isRejectService()) {
+            this.addMetric(false, 0, null);
+            source.fileMetricEventInc(StatConstants.EVENT_SERVICE_CLOSED);
+            this.responsePackage(ctx, ProxySdk.ResultCode.ERR_REJECT, 
packObject);
+            return;
+        }
+        // uncompress
+        List<ProxyEvent> events = EventUtils.decodeSdkPack(packObject);
+        // response success if event size is zero
+        if (events.size() == 0) {
+            this.responsePackage(ctx, ProxySdk.ResultCode.SUCCUSS, packObject);
+        }
+        // process
+        if (CommonConfigHolder.getInstance().isResponseAfterSave()) {
+            this.processAndWaitingSave(ctx, packObject, events);
+        } else {
+            this.processAndResponse(ctx, packObject, events);
+        }
+    }
+
+    /**
+     * responsePackage
+     *
+     * @param  ctx
+     * @param  code
+     * @throws Exception
+     */
+    private void responsePackage(ChannelHandlerContext ctx,
+            ProxySdk.ResultCode code,
+            ProxySdk.MessagePack packObject) throws Exception {
+        ProxySdk.ResponseInfo.Builder builder = 
ProxySdk.ResponseInfo.newBuilder();
+        builder.setResult(code);
+        ProxySdk.MessagePackHeader header = packObject.getHeader();
+        builder.setPackId(header.getPackId());
+
+        // encode
+        byte[] responseBytes = builder.build().toByteArray();
+        //
+        ByteBuf buffer = Unpooled.wrappedBuffer(responseBytes);
+        Channel remoteChannel = ctx.channel();
+        if (remoteChannel.isWritable()) {
+            remoteChannel.write(buffer);
+        } else {
+            buffer.release();
+            logger.warn("Send buffer2 is not writable, disconnect {}", 
remoteChannel);
+            throw new Exception("Send buffer2 is not writable, disconnect " + 
remoteChannel);
+        }
+    }
+
+    /**
+     * processAndWaitingSave
+     * @param ctx
+     * @param packObject
+     * @param events
+     * @throws Exception
+     */
+    private void processAndWaitingSave(ChannelHandlerContext ctx,
+            ProxySdk.MessagePack packObject,
+            List<ProxyEvent> events) throws Exception {
+        ProxySdk.MessagePackHeader header = packObject.getHeader();
+        InlongTcpSourceCallback callback = new InlongTcpSourceCallback(ctx, 
header);
+        String inlongGroupId = header.getInlongGroupId();
+        String inlongStreamId = header.getInlongStreamId();
+        ProxyPackEvent packEvent = new ProxyPackEvent(inlongGroupId, 
inlongStreamId, events, callback);
+        // put to channel
+        try {
+            source.getChannelProcessor().processEvent(packEvent);
+            events.forEach(event -> {
+                this.addMetric(true, event.getBody().length, event);
+                source.fileMetricEventInc(StatConstants.EVENT_POST_SUCCESS);
+            });
+            boolean awaitResult = callback.getLatch().await(
+                    
CommonConfigHolder.getInstance().getMaxResAfterSaveTimeout(), 
TimeUnit.MILLISECONDS);
+            if (!awaitResult) {
+                if (!callback.getHasResponsed().getAndSet(true)) {
+                    this.responsePackage(ctx, ProxySdk.ResultCode.ERR_REJECT, 
packObject);
+                }
+            }
+        } catch (Throwable ex) {
+            logger.error("Process Controller Event error can't write event to 
channel.", ex);
+            events.forEach(event -> {
+                this.addMetric(false, event.getBody().length, event);
+                source.fileMetricEventInc(StatConstants.EVENT_POST_DROPPED);
+            });
+            if (!callback.getHasResponsed().getAndSet(true)) {
+                this.responsePackage(ctx, ProxySdk.ResultCode.ERR_REJECT, 
packObject);
+            }
+        }
+    }
+
+    /**
+     * processAndResponse
+     * @param ctx
+     * @param packObject
+     * @param events
+     * @throws Exception
+     */
+    private void processAndResponse(ChannelHandlerContext ctx,
+            ProxySdk.MessagePack packObject,
+            List<ProxyEvent> events) throws Exception {
+        for (ProxyEvent event : events) {
+            // get configured topic name
+            String topic = 
configManager.getTopicName(event.getInlongGroupId(), event.getInlongStreamId());
+            if (StringUtils.isBlank(topic)) {
+                if (CommonConfigHolder.getInstance().isNoTopicAccept()) {
+                    topic = source.getDefTopic();
+                } else {
+                    source.fileMetricEventInc(StatConstants.EVENT_NOTOPIC);
+                    this.addMetric(false, event.getBody().length, event);
+                    this.responsePackage(ctx, 
ProxySdk.ResultCode.ERR_ID_ERROR, packObject);
+                    return;
+                }
+            }
+            event.setTopic(topic);
+            // put to channel
+            try {
+                source.getChannelProcessor().processEvent(event);
+                this.addMetric(true, event.getBody().length, event);
+                source.fileMetricEventInc(StatConstants.EVENT_POST_SUCCESS);
+            } catch (Throwable ex) {
+                logger.error("Process Controller Event error can't write event 
to channel.", ex);
+                this.addMetric(false, event.getBody().length, event);
+                this.responsePackage(ctx, ProxySdk.ResultCode.ERR_REJECT, 
packObject);
+                source.fileMetricEventInc(StatConstants.EVENT_POST_DROPPED);
+                return;
+            }
+        }
+        this.responsePackage(ctx, ProxySdk.ResultCode.SUCCUSS, packObject);
+    }
+
+    /**
+     *  Return response to client in source
+     */
+    private void responseV0Msg(Channel channel, AbsV0MsgCodec msgObj, 
StringBuilder strBuff) throws Exception {
+        // check channel status
+        if (channel == null || !channel.isWritable()) {
+            
source.fileMetricEventInc(StatConstants.EVENT_CHANNEL_NOT_WRITABLE);
+            if (logCounter.shouldPrint()) {
+                logger.warn("Prepare send msg but channel full, msgType={}, 
attr={}, channel={}",
+                        msgObj.getMsgType(), msgObj.getAttr(), channel);
+            }
+            throw new Exception("Prepare send msg but channel full");
+        }
+        // check whether return response message
+        if (!msgObj.isNeedResp()) {
+            return;
+        }
+        // build return attribute string
+        strBuff.append(ConfigConstants.DATAPROXY_IP_KEY)
+                
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(source.getSrcHost());
+        if (msgObj.getErrCode() != DataProxyErrCode.SUCCESS) {
+            
strBuff.append(AttributeConstants.SEPARATOR).append(AttributeConstants.MESSAGE_PROCESS_ERRCODE)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgObj.getErrCode().getErrCodeStr());
+            if (StringUtils.isNotEmpty(msgObj.getErrMsg())) {
+                
strBuff.append(AttributeConstants.SEPARATOR).append(AttributeConstants.MESSAGE_PROCESS_ERRMSG)
+                        
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgObj.getErrMsg());
+            }
+            if (StringUtils.isNotEmpty(msgObj.getAttr())) {
+                
strBuff.append(AttributeConstants.SEPARATOR).append(msgObj.getAttr());
+            }
+        }
+        // build and send response message
+        ByteBuf retData;
+        MsgType msgType = MsgType.valueOf(msgObj.getMsgType());
+        if (MsgType.MSG_BIN_MULTI_BODY.equals(msgType)) {
+            retData = buildBinMsgRspPackage(strBuff.toString(), 
msgObj.getUniq());
+        } else {
+            retData = buildTxtMsgRspPackage(msgType, strBuff.toString());
+        }
+        strBuff.delete(0, strBuff.length());
+        flushV0MsgPackage(source, channel, retData, msgObj.getAttr());
+    }
+
+    /**
+     * extract and process bin heart beat msg, message type is 8
+     */
+    private void procBinHeartbeatMsg(BaseSource source, Channel channel,
+            ByteBuf cb, int totalDataLen) throws Exception {
+        // Check if the message is complete and legal
+        if (totalDataLen < BIN_HB_FIXED_CONTENT_SIZE) {
+            source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+            String errMsg = String.format("Malformed msg, totalDataLen(%d) < 
min hb-msg length(%d)",
+                    totalDataLen, BIN_HB_FIXED_CONTENT_SIZE);
+            if (logger.isDebugEnabled()) {
+                logger.debug(errMsg + ", channel {}", channel);
+            }
+            throw new Exception(errMsg);
+        }
+        // check validation
+        int msgHeadPos = cb.readerIndex() - 5;
+        int bodyLen = cb.getInt(msgHeadPos + BIN_HB_BODYLEN_OFFSET);
+        int attrLen = cb.getShort(msgHeadPos + BIN_HB_BODY_OFFSET + bodyLen);
+        int msgMagic = cb.getUnsignedShort(msgHeadPos
+                + BIN_HB_BODY_OFFSET + bodyLen + BIN_HB_ATTRLEN_SIZE + 
attrLen);
+        if ((totalDataLen + BIN_HB_TOTALLEN_SIZE < (bodyLen + attrLen + 
BIN_HB_FORMAT_SIZE))
+                || (msgMagic != BIN_MSG_MAGIC)) {
+            source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+            String errMsg = String.format(
+                    "Malformed msg, bodyLen(%d) + attrLen(%d) > 
totalDataLen(%d) or msgMagic(%d) != %d",
+                    bodyLen, attrLen, totalDataLen, msgMagic, BIN_MSG_MAGIC);
+            if (logger.isDebugEnabled()) {
+                logger.debug(errMsg + ", channel {}", channel);
+            }
+            throw new Exception(errMsg);
+        }
+        // read message content
+        byte version = cb.getByte(msgHeadPos + BIN_HB_VERSION_OFFSET);
+        byte[] attrData = null;
+        if (attrLen > 0) {
+            attrData = new byte[attrLen];
+            cb.getBytes(msgHeadPos + BIN_HB_BODY_OFFSET
+                    + bodyLen + BIN_HB_ATTRLEN_SIZE, attrData, 0, attrLen);
+        }
+        // build and send response message
+        flushV0MsgPackage(source, channel, buildHBRspPackage(attrData, 
version, 0),
+                MsgType.MSG_BIN_HEARTBEAT.name());
+    }
+
+    /**
+     * Build bin-msg response message ByteBuf
+     *
+     * @param attrs   the return attribute
+     * @param uniqVal sequence Id
+     * @return ByteBuf
+     */
+    private ByteBuf buildBinMsgRspPackage(String attrs, long uniqVal) {
+        // calculate total length
+        // binTotalLen = mstType + uniq + attrsLen + attrs + magic
+        int binTotalLen = 1 + 4 + 2 + 2;
+        if (null != attrs) {
+            binTotalLen += attrs.length();
+        }
+        // allocate buffer and write fields
+        ByteBuf binBuffer = ByteBufAllocator.DEFAULT.buffer(4 + binTotalLen);
+        binBuffer.writeInt(binTotalLen);
+        binBuffer.writeByte(MsgType.MSG_BIN_MULTI_BODY.getValue());
+        byte[] uniq = new byte[4];
+        uniq[0] = (byte) ((uniqVal >> 24) & 0xFF);
+        uniq[1] = (byte) ((uniqVal >> 16) & 0xFF);
+        uniq[2] = (byte) ((uniqVal >> 8) & 0xFF);
+        uniq[3] = (byte) (uniqVal & 0xFF);
+        binBuffer.writeBytes(uniq);
+        if (null != attrs) {
+            binBuffer.writeShort(attrs.length());
+            binBuffer.writeBytes(attrs.getBytes(StandardCharsets.UTF_8));
+        } else {
+            binBuffer.writeShort(0x0);
+        }
+        binBuffer.writeShort(0xee01);
+        return binBuffer;
+    }
+
+    /**
+     * Build default-msg response message ByteBuf
+     *
+     * @param msgType  the message type
+     * @param attrs    the return attribute
+     * @return ByteBuf
+     */
+    private ByteBuf buildTxtMsgRspPackage(MsgType msgType, String attrs) {
+        int attrsLen = 0;
+        int bodyLen = 0;
+        if (attrs != null) {
+            attrsLen = attrs.length();
+        }
+        // backTotalLen = mstType + bodyLen + body + attrsLen + attrs
+        int backTotalLen = 1 + 4 + bodyLen + 4 + attrsLen;
+        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(4 + backTotalLen);
+        buffer.writeInt(backTotalLen);
+        buffer.writeByte(msgType.getValue());
+        buffer.writeInt(bodyLen);
+        buffer.writeInt(attrsLen);
+        if (attrsLen > 0) {
+            buffer.writeBytes(attrs.getBytes(StandardCharsets.UTF_8));
+        }
+        return buffer;
+    }
+
+    /**
+     * Build heartbeat response message ByteBuf
+     *
+     * @param attrData  the attribute data
+     * @param version   the version
+     * @param loadValue the node load value
+     * @return ByteBuf
+     */
+    private ByteBuf buildHBRspPackage(byte[] attrData, byte version, int 
loadValue) {
+        // calculate total length
+        // binTotalLen = mstType + dataTime + version + bodyLen + body + 
attrsLen + attrs + magic
+        int binTotalLen = 1 + 4 + 1 + 4 + 2 + 2 + 2;
+        if (null != attrData) {
+            binTotalLen += attrData.length;
+        }
+        // check load value
+        if (loadValue == 0 || loadValue == (-1)) {
+            loadValue = 0xffff;
+        }
+        // allocate buffer and write fields
+        ByteBuf binBuffer = ByteBufAllocator.DEFAULT.buffer(4 + binTotalLen);
+        binBuffer.writeInt(binTotalLen);
+        binBuffer.writeByte(MsgType.MSG_BIN_HEARTBEAT.getValue());
+        binBuffer.writeInt((int) (System.currentTimeMillis() / 1000));
+        binBuffer.writeByte(version);
+        binBuffer.writeInt(2);
+        binBuffer.writeShort(loadValue);
+        if (null != attrData) {
+            binBuffer.writeShort(attrData.length);
+            binBuffer.writeBytes(attrData);
+        } else {
+            binBuffer.writeShort(0x0);
+        }
+        binBuffer.writeShort(0xee01);
+        return binBuffer;
+    }
+
+    /**
+     * Build hearbeat(1)-msg response message ByteBuf
+     *
+     * @return ByteBuf
+     */
+    private ByteBuf buildHeartBeatMsgRspPackage() {
+        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(5);
+        // magic data
+        buffer.writeBytes(new byte[]{0, 0, 0, 1, 1});
+        return buffer;
+    }
+
+    private void flushV0MsgPackage(BaseSource source, Channel channel,
+            ByteBuf binBuffer, String orgAttr) throws Exception {
+        if (channel == null || !channel.isWritable()) {
+            // release allocated ByteBuf
+            binBuffer.release();
+            
source.fileMetricEventInc(StatConstants.EVENT_CHANNEL_NOT_WRITABLE);
+            if (logCounter.shouldPrint()) {
+                logger.warn("Send msg but channel full, attr={}, channel={}", 
orgAttr, channel);
+            }
+            throw new Exception("Send response but channel full");
+        }
+        channel.writeAndFlush(binBuffer);
+    }
+
+    /**
+     * addMetric
+     *
+     * @param result
+     * @param size
+     * @param event
+     */
+    private void addMetric(boolean result, long size, Event event) {
+        Map<String, String> dimensions = new HashMap<>();
+        dimensions.put(DataProxyMetricItem.KEY_CLUSTER_ID, 
CommonConfigHolder.getInstance().getClusterName());
+        dimensions.put(DataProxyMetricItem.KEY_SOURCE_ID, source.getName());
+        dimensions.put(DataProxyMetricItem.KEY_SOURCE_DATA_ID, 
source.getStrPort());
+        DataProxyMetricItem.fillInlongId(event, dimensions);
+        DataProxyMetricItem.fillAuditFormatTime(event, dimensions);
+        DataProxyMetricItem metricItem = 
source.getMetricItemSet().findMetricItem(dimensions);
+        if (result) {
+            metricItem.readSuccessCount.incrementAndGet();
+            metricItem.readSuccessSize.addAndGet(size);
+            AuditUtils.add(AuditUtils.AUDIT_ID_DATAPROXY_READ_SUCCESS, event);
+        } else {
+            metricItem.readFailCount.incrementAndGet();
+            metricItem.readFailSize.addAndGet(size);
+        }
+    }
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleTcpSource.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleTcpSource.java
new file mode 100644
index 000000000..6be918b0e
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleTcpSource.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+import com.google.common.base.Preconditions;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.util.concurrent.DefaultThreadFactory;
+import org.apache.flume.Context;
+import org.apache.flume.conf.Configurable;
+import org.apache.inlong.dataproxy.config.ConfigManager;
+import org.apache.inlong.dataproxy.config.holder.ConfigUpdateCallback;
+import org.apache.inlong.dataproxy.utils.AddressUtils;
+import org.apache.inlong.dataproxy.utils.EventLoopUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetSocketAddress;
+import java.util.Iterator;
+
+/**
+ * Simple tcp source
+ *
+ */
+public class SimpleTcpSource extends BaseSource implements Configurable, 
ConfigUpdateCallback {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(SimpleTcpSource.class);
+
+    private ServerBootstrap bootstrap;
+    private boolean tcpNoDelay;
+    private boolean tcpKeepAlive;
+    private int highWaterMark;
+    private boolean enableBusyWait;
+
+    public SimpleTcpSource() {
+        super();
+        ConfigManager.getInstance().regIPVisitConfigChgCallback(this);
+    }
+
+    @Override
+    public void configure(Context context) {
+        logger.info("Source {} context is {}", getName(), context);
+        super.configure(context);
+        // get tcp no-delay parameter
+        this.tcpNoDelay = 
context.getBoolean(SourceConstants.SRCCXT_TCP_NO_DELAY,
+                SourceConstants.VAL_DEF_TCP_NO_DELAY);
+        // get tcp keep-alive parameter
+        this.tcpKeepAlive = 
context.getBoolean(SourceConstants.SRCCXT_TCP_KEEP_ALIVE,
+                SourceConstants.VAL_DEF_TCP_KEEP_ALIVE);
+        // get tcp enable busy-wait
+        this.enableBusyWait = 
context.getBoolean(SourceConstants.SRCCXT_TCP_ENABLE_BUSY_WAIT,
+                SourceConstants.VAL_DEF_TCP_ENABLE_BUSY_WAIT);
+        // get tcp high watermark
+        this.highWaterMark = getIntValue(context, 
SourceConstants.SRCCXT_TCP_HIGH_WATER_MARK,
+                SourceConstants.VAL_DEF_TCP_HIGH_WATER_MARK);
+        Preconditions.checkArgument((this.highWaterMark >= 
SourceConstants.VAL_MIN_TCP_HIGH_WATER_MARK),
+                SourceConstants.VAL_DEF_TCP_HIGH_WATER_MARK + " must be >= "
+                        + SourceConstants.VAL_MIN_TCP_HIGH_WATER_MARK);
+    }
+
+    @Override
+    public synchronized void startSource() {
+        logger.info("start " + this.getName());
+        // build accept group
+        this.acceptorGroup = EventLoopUtil.newEventLoopGroup(maxAcceptThreads, 
enableBusyWait,
+                new DefaultThreadFactory(this.getName() + "-boss-group"));
+        // build worker group
+        this.workerGroup = EventLoopUtil.newEventLoopGroup(maxWorkerThreads, 
enableBusyWait,
+                new DefaultThreadFactory(this.getName() + "-worker-group"));
+        // init boostrap
+        bootstrap = new ServerBootstrap();
+        bootstrap.childOption(ChannelOption.ALLOCATOR, 
ByteBufAllocator.DEFAULT);
+        bootstrap.childOption(ChannelOption.TCP_NODELAY, tcpNoDelay);
+        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, tcpKeepAlive);
+        bootstrap.childOption(ChannelOption.SO_RCVBUF, maxRcvBufferSize);
+        bootstrap.childOption(ChannelOption.SO_SNDBUF, maxSendBufferSize);
+        bootstrap.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 
highWaterMark);
+        
bootstrap.channel(EventLoopUtil.getServerSocketChannelClass(workerGroup));
+        EventLoopUtil.enableTriggeredMode(bootstrap);
+        bootstrap.group(acceptorGroup, workerGroup);
+        bootstrap.childHandler(this.getChannelInitializerFactory());
+        try {
+            if (srcHost == null) {
+                channelFuture = bootstrap.bind(new 
InetSocketAddress(srcPort)).sync();
+            } else {
+                channelFuture = bootstrap.bind(new InetSocketAddress(srcHost, 
srcPort)).sync();
+            }
+        } catch (Exception e) {
+            logger.error("Source {} bind ({}:{}) error, program will exit! e = 
{}",
+                    this.getName(), srcHost, srcPort, e);
+            System.exit(-1);
+        }
+        ConfigManager.getInstance().addSourceReportInfo(
+                srcHost, String.valueOf(srcPort), 
getProtocolName().toUpperCase());
+        logger.info("Source {} started at ({}:{})!", this.getName(), srcHost, 
srcPort);
+    }
+
+    @Override
+    public synchronized void stop() {
+        super.stop();
+    }
+
+    @Override
+    public String getProtocolName() {
+        return SourceConstants.SRC_PROTOCOL_TYPE_TCP;
+    }
+
+    @Override
+    public void update() {
+        // check current all links
+        if (ConfigManager.getInstance().needChkIllegalIP()) {
+            int cnt = 0;
+            Channel channel;
+            String strRemoteIP;
+            long startTime = System.currentTimeMillis();
+            Iterator<Channel> iterator = allChannels.iterator();
+            while (iterator.hasNext()) {
+                channel = iterator.next();
+                strRemoteIP = AddressUtils.getChannelRemoteIP(channel);
+                if (strRemoteIP == null) {
+                    continue;
+                }
+                if (ConfigManager.getInstance().isIllegalIP(strRemoteIP)) {
+                    channel.disconnect();
+                    channel.close();
+                    allChannels.remove(channel);
+                    cnt++;
+                    logger.error(strRemoteIP + " is Illegal IP, so disconnect 
it !");
+                }
+            }
+            logger.info("Source {} channel check, disconnects {} Illegal 
channels, waist {} ms",
+                    getName(), cnt, (System.currentTimeMillis() - startTime));
+        }
+    }
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleUdpSource.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleUdpSource.java
new file mode 100644
index 000000000..dbe988f68
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SimpleUdpSource.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+import org.apache.flume.Context;
+import org.apache.flume.conf.Configurable;
+import org.apache.inlong.dataproxy.config.ConfigManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.net.InetSocketAddress;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+
+public class SimpleUdpSource extends BaseSource implements Configurable {
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(SimpleUdpSource.class);
+
+    private Bootstrap bootstrap;
+
+    public SimpleUdpSource() {
+        super();
+    }
+
+    @Override
+    public void configure(Context context) {
+        logger.info("Source {} context is {}", getName(), context);
+        super.configure(context);
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Override
+    public void startSource() {
+        // setup Netty server
+        logger.info("start " + this.getName());
+        bootstrap = new Bootstrap();
+        bootstrap.channel(NioDatagramChannel.class);
+        bootstrap.option(ChannelOption.SO_RCVBUF, maxRcvBufferSize);
+        bootstrap.option(ChannelOption.SO_SNDBUF, maxSendBufferSize);
+        bootstrap.handler(this.getChannelInitializerFactory());
+        try {
+            if (srcHost == null) {
+                channelFuture = bootstrap.bind(new 
InetSocketAddress(srcPort)).sync();
+            } else {
+                channelFuture = bootstrap.bind(new InetSocketAddress(srcHost, 
srcPort)).sync();
+            }
+        } catch (Exception e) {
+            logger.error("Source {} bind ({}:{}) error, program will exit! e = 
{}",
+                    this.getName(), srcHost, srcPort, e);
+            System.exit(-1);
+        }
+        ConfigManager.getInstance().addSourceReportInfo(
+                srcHost, String.valueOf(srcPort), 
getProtocolName().toUpperCase());
+        logger.info("Source {} started at ({}:{})!", this.getName(), srcHost, 
srcPort);
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+    }
+
+    @Override
+    public String getProtocolName() {
+        return SourceConstants.SRC_PROTOCOL_TYPE_UDP;
+    }
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SourceConstants.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SourceConstants.java
new file mode 100644
index 000000000..edb111dd8
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/SourceConstants.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2;
+
+public class SourceConstants {
+
+    // source host
+    public static final String SRCCXT_CONFIG_HOST = "host";
+    // system env source host
+    public static final String SYSENV_HOST_IP = "inlongHostIp";
+    // default source host
+    public static final String VAL_DEF_HOST_VALUE = "0.0.0.0";
+    // source port
+    public static final String SRCCXT_CONFIG_PORT = "port";
+    // system env source port
+    public static final String SYSENV_HOST_PORT = "inlongHostPort";
+    // message factory name
+    public static final String SRCCXT_MSG_FACTORY_NAME = "msg-factory-name";
+    // message handler name
+    public static final String SRCCXT_MESSAGE_HANDLER_NAME = 
"message-handler-name";
+    // default topic name
+    public static final String SRCCXT_DEF_TOPIC = "topic";
+    // default attributes
+    public static final String SRCCXT_DEF_ATTR = "attr";
+    // max message length
+    public static final String SRCCXT_MAX_MSG_LENGTH = "max-msg-length";
+    // allowed max message length
+    public static final int VAL_MAX_MAX_MSG_LENGTH = 20 * 1024 * 1024;
+    public static final int VAL_MIN_MAX_MSG_LENGTH = 5;
+    public static final int VAL_DEF_MAX_MSG_LENGTH = 1024 * 64;
+    // whether compress message
+    public static final String SRCCXT_MSG_COMPRESSED = "msg-compressed";
+    public static final boolean VAL_DEF_MSG_COMPRESSED = true;
+    // whether filter empty message
+    public static final String SRCCXT_FILTER_EMPTY_MSG = "filter-empty-msg";
+    public static final boolean VAL_DEF_FILTER_EMPTY_MSG = false;
+    // whether custom channel processor
+    public static final String SRCCXT_CUSTOM_CHANNEL_PROCESSOR = "custom-cp";
+    public static final boolean VAL_DEF_CUSTOM_CH_PROCESSOR = false;
+    // max net accept process threads
+    public static final String SRCCXT_MAX_ACCEPT_THREADS = 
"max-accept-threads";
+    public static final int VAL_DEF_NET_ACCEPT_THREADS = 1;
+    public static final int VAL_MIN_ACCEPT_THREADS = 1;
+    public static final int VAL_MAX_ACCEPT_THREADS = 10;
+    // max net worker process threads
+    public static final String SRCCXT_MAX_WORKER_THREADS = "max-threads";
+    public static final int VAL_DEF_WORKER_THREADS = 
Runtime.getRuntime().availableProcessors();
+    public static final int VAL_MIN_WORKER_THREADS = 1;
+    public static final int VAL_MAX_WORKER_THREADS = 
Runtime.getRuntime().availableProcessors() * 2;
+    // file metric statistic interval(second)
+    public static final String SRCCXT_STAT_INTERVAL_SEC = "stat-interval-sec";
+    public static final int VAL_DEF_STAT_INVL_SEC = 60;
+    public static final int VAL_MIN_STAT_INVL_SEC = 0;
+    // max file statistic key count
+    public static final String SRCCXT_MAX_MONITOR_STAT_CNT = "max-monitor-cnt";
+    public static final int VAL_DEF_MON_STAT_CNT = 1000000;
+    public static final int VAL_MIN_MON_STAT_CNT = 0;
+    // max file statistic key count
+    public static final String SRCCXT_FILE_METRIC_ON = "file-metric-on";
+    public static final boolean VAL_DEF_FILE_METRIC_ON = true;
+    // max connection count
+    public static final String SRCCXT_MAX_CONNECTION_CNT = "connections";
+    public static final int VAL_DEF_MAX_CONNECTION_CNT = 5000;
+    public static final int VAL_MIN_CONNECTION_CNT = 0;
+    // max receive buffer size
+    public static final String SRCCXT_RECEIVE_BUFFER_SIZE = 
"receiveBufferSize";
+    public static final int VAL_DEF_RECEIVE_BUFFER_SIZE = 64 * 1024;
+    public static final int VAL_MIN_RECEIVE_BUFFER_SIZE = 0;
+    public static final int VAL_MAX_RECEIVE_BUFFER_SIZE = 100 * 1024 * 1024;
+    // max send buffer size
+    public static final String SRCCXT_SEND_BUFFER_SIZE = "sendBufferSize";
+    public static final int VAL_DEF_SEND_BUFFER_SIZE = 64 * 1024;
+    public static final int VAL_MIN_SEND_BUFFER_SIZE = 0;
+    public static final int VAL_MAX_SEND_BUFFER_SIZE = 100 * 1024 * 1024;
+    // tcp parameter no delay
+    public static final String SRCCXT_TCP_NO_DELAY = "tcpNoDelay";
+    public static final boolean VAL_DEF_TCP_NO_DELAY = true;
+    // tcp parameter keep alive
+    public static final String SRCCXT_TCP_KEEP_ALIVE = "keepAlive";
+    public static final boolean VAL_DEF_TCP_KEEP_ALIVE = true;
+    // tcp parameter high water mark
+    public static final String SRCCXT_TCP_HIGH_WATER_MARK = "highWaterMark";
+    public static final int VAL_DEF_TCP_HIGH_WATER_MARK = 64 * 1024;
+    public static final int VAL_MIN_TCP_HIGH_WATER_MARK = 0;
+    // tcp parameter enable busy wait
+    public static final String SRCCXT_TCP_ENABLE_BUSY_WAIT = "enableBusyWait";
+    public static final boolean VAL_DEF_TCP_ENABLE_BUSY_WAIT = false;
+    // tcp parameters max read idle time
+    public static final String SRCCXT_MAX_READ_IDLE_TIME_MS = 
"maxReadIdleTime";
+    public static final long VAL_DEF_READ_IDLE_TIME_MS = 70 * 60 * 1000;
+    public static final long VAL_MIN_READ_IDLE_TIME_MS = 60 * 1000;
+    // source protocol type
+    public static final String SRC_PROTOCOL_TYPE_TCP = "tcp";
+    public static final String SRC_PROTOCOL_TYPE_UDP = "udp";
+    public static final String SRC_PROTOCOL_TYPE_HTTP = "http";
+
+    public static final String SERVICE_PROCESSOR_NAME = "service-decoder-name";
+    public static final String ENABLE_EXCEPTION_RETURN = 
"enableExceptionReturn";
+
+    public static final String TRAFFIC_CLASS = "trafficClass";
+
+    public static final String HEART_INTERVAL_SEC = "heart-interval-sec";
+
+    public static final String PACKAGE_TIMEOUT_SEC = "package-timeout-sec";
+
+    public static final String HEART_SERVERS = "heart-servers";
+
+    public static final String TOPIC_KEY = "topic";
+    public static final String REMOTE_IP_KEY = "srcIp";
+    public static final String DATAPROXY_IP_KEY = "dpIp";
+    public static final String MSG_ENCODE_VER = "msgEnType";
+    public static final String REMOTE_IDC_KEY = "idc";
+    public static final String MSG_COUNTER_KEY = "msgcnt";
+    public static final String PKG_COUNTER_KEY = "pkgcnt";
+    public static final String PKG_TIME_KEY = "msg.pkg.time";
+    public static final String TRANSFER_KEY = "transfer";
+    public static final String DEST_IP_KEY = "dstIp";
+    public static final String INTERFACE_KEY = "interface";
+    public static final String SINK_MIN_METRIC_KEY = "sink-min-metric-topic";
+    public static final String SINK_HOUR_METRIC_KEY = "sink-hour-metric-topic";
+    public static final String SINK_TEN_METRIC_KEY = "sink-ten-metric-topic";
+    public static final String SINK_QUA_METRIC_KEY = "sink-qua-metric-topic";
+    public static final String L5_MIN_METRIC_KEY = "l5-min-metric-topic";
+    public static final String L5_MIN_FAIL_METRIC_KEY = 
"l5-min-fail-metric-key";
+    public static final String L5_HOUR_METRIC_KEY = "l5-hour-metric-topic";
+    public static final String L5_ID_KEY = "l5id";
+    public static final String SET_KEY = "set";
+    public static final String CLUSTER_ID_KEY = "clusterId";
+
+    public static final String DECODER_BODY = "body";
+    public static final String DECODER_TOPICKEY = "topic_key";
+    public static final String DECODER_ATTRS = "attrs";
+    public static final String MSG_TYPE = "msg_type";
+    public static final String COMPRESS_TYPE = "compress_type";
+    public static final String EXTRA_ATTR = "extra_attr";
+    public static final String COMMON_ATTR_MAP = "common_attr_map";
+    public static final String MSG_LIST = "msg_list";
+    public static final String VERSION_TYPE = "version";
+    public static final String FILE_CHECK_DATA = "file-check-data";
+    public static final String MINUTE_CHECK_DATA = "minute-check-data";
+    public static final String SLA_METRIC_DATA = "sla-metric-data";
+    public static final String SLA_METRIC_GROUPID = "manager_sla_metric";
+
+    public static final String FILE_BODY = "file-body";
+    public static final int MSG_MAX_LENGTH_BYTES = 20 * 1024 * 1024;
+
+    public static final String SEQUENCE_ID = "sequencial_id";
+
+    public static final String TOTAL_LEN = "totalLen";
+
+    public static final String LINK_MAX_ALLOWED_DELAYED_MSG_COUNT = 
"link_max_allowed_delayed_msg_count";
+    public static final String SESSION_WARN_DELAYED_MSG_COUNT = 
"session_warn_delayed_msg_count";
+    public static final String SESSION_MAX_ALLOWED_DELAYED_MSG_COUNT = 
"session_max_allowed_delayed_msg_count";
+    public static final String NETTY_WRITE_BUFFER_HIGH_WATER_MARK = 
"netty_write_buffer_high_water_mark";
+    public static final String RECOVER_THREAD_COUNT = "recover_thread_count";
+
+    public static final String MANAGER_PATH = "/inlong/manager/openapi";
+    public static final String MANAGER_GET_CONFIG_PATH = 
"/dataproxy/getConfig";
+    public static final String MANAGER_GET_ALL_CONFIG_PATH = 
"/dataproxy/getAllConfig";
+    public static final String MANAGER_HEARTBEAT_REPORT = "/heartbeat/report";
+
+    public static final String MANAGER_AUTH_SECRET_ID = 
"manager.auth.secretId";
+    public static final String MANAGER_AUTH_SECRET_KEY = 
"manager.auth.secretKey";
+    // Pulsar config
+    public static final String KEY_TENANT = "tenant";
+    public static final String KEY_NAMESPACE = "namespace";
+
+    public static final String KEY_SERVICE_URL = "serviceUrl";
+    public static final String KEY_AUTHENTICATION = "authentication";
+    public static final String KEY_STATS_INTERVAL_SECONDS = 
"statsIntervalSeconds";
+
+    public static final String KEY_ENABLEBATCHING = "enableBatching";
+    public static final String KEY_BATCHINGMAXBYTES = "batchingMaxBytes";
+    public static final String KEY_BATCHINGMAXMESSAGES = "batchingMaxMessages";
+    public static final String KEY_BATCHINGMAXPUBLISHDELAY = 
"batchingMaxPublishDelay";
+    public static final String KEY_MAXPENDINGMESSAGES = "maxPendingMessages";
+    public static final String KEY_MAXPENDINGMESSAGESACROSSPARTITIONS = 
"maxPendingMessagesAcrossPartitions";
+    public static final String KEY_SENDTIMEOUT = "sendTimeout";
+    public static final String KEY_COMPRESSIONTYPE = "compressionType";
+    public static final String KEY_BLOCKIFQUEUEFULL = "blockIfQueueFull";
+    public static final String 
KEY_ROUNDROBINROUTERBATCHINGPARTITIONSWITCHFREQUENCY = "roundRobinRouter"
+            + "BatchingPartitionSwitchFrequency";
+
+    public static final String KEY_IOTHREADS = "ioThreads";
+    public static final String KEY_MEMORYLIMIT = "memoryLimit";
+    public static final String KEY_CONNECTIONSPERBROKER = 
"connectionsPerBroker";
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/AbsV0MsgCodec.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/AbsV0MsgCodec.java
new file mode 100644
index 000000000..200228ca8
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/AbsV0MsgCodec.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2.v0msg;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.flume.Event;
+import org.apache.inlong.common.enums.DataProxyErrCode;
+import org.apache.inlong.common.msg.AttributeConstants;
+import org.apache.inlong.dataproxy.consts.ConfigConstants;
+import org.apache.inlong.dataproxy.consts.StatConstants;
+import org.apache.inlong.dataproxy.source2.BaseSource;
+import org.apache.inlong.dataproxy.utils.DateTimeUtils;
+import org.apache.inlong.dataproxy.utils.InLongMsgVer;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+
+public abstract class AbsV0MsgCodec {
+
+    // string splitter
+    protected static final Splitter.MapSplitter mapSplitter = Splitter
+            .on(AttributeConstants.SEPARATOR).trimResults()
+            .withKeyValueSeparator(AttributeConstants.KEY_VALUE_SEPARATOR);
+    // map joiner
+    protected static final Joiner.MapJoiner mapJoiner = 
Joiner.on(AttributeConstants.SEPARATOR)
+            .withKeyValueSeparator(AttributeConstants.KEY_VALUE_SEPARATOR);
+
+    protected DataProxyErrCode errCode = DataProxyErrCode.UNKNOWN_ERROR;
+    protected String errMsg = "";
+    protected String strRemoteIP;
+    protected long msgRcvTime;
+    protected int totalDataLen;
+    protected byte msgType;
+    protected int msgCount;
+    protected String origAttr = "";
+    protected byte[] bodyData;
+    protected long dataTimeMs;
+    protected String groupId;
+    protected String streamId = "";
+    protected String topicName;
+    protected String msgSeqId = "";
+    protected long uniq = -1L;
+    protected String msgProcType = "b2b";
+    protected boolean needResp = true;
+    protected final Map<String, String> attrMap = new HashMap<>();
+
+    public AbsV0MsgCodec(int totalDataLen, int msgTypeValue,
+            long msgRcvTime, String strRemoteIP) {
+        this.totalDataLen = totalDataLen;
+        this.msgType = (byte) (msgTypeValue & 0xFF);
+        this.msgRcvTime = msgRcvTime;
+        this.strRemoteIP = strRemoteIP;
+    }
+
+    public abstract boolean descMsg(BaseSource source, ByteBuf cb) throws 
Exception;
+
+    public abstract boolean validAndFillFields(BaseSource source, 
StringBuilder strBuff);
+
+    public abstract Event encEventPackage(BaseSource source, Channel channel);
+
+    public DataProxyErrCode getErrCode() {
+        return this.errCode;
+    }
+
+    public String getErrMsg() {
+        return this.errMsg;
+    }
+
+    public boolean isNeedResp() {
+        return this.needResp;
+    }
+
+    public byte getMsgType() {
+        return this.msgType;
+    }
+
+    public String getAttr() {
+        return this.origAttr;
+    }
+
+    public Map<String, String> getAttrMap() {
+        return this.attrMap;
+    }
+
+    public long getUniq() {
+        return this.uniq;
+    }
+
+    public long getDataTimeMs() {
+        return this.dataTimeMs;
+    }
+
+    public String getGroupId() {
+        return this.groupId;
+    }
+
+    public String getStreamId() {
+        return this.streamId;
+    }
+
+    public String getTopicName() {
+        return this.topicName;
+    }
+
+    public String getMsgProcType() {
+        return this.msgProcType;
+    }
+
+    public int getBodyLength() {
+        return this.bodyData == null ? 0 : this.bodyData.length;
+    }
+
+    public int getMsgCount() {
+        return this.msgCount;
+    }
+
+    public String getStrRemoteIP() {
+        return strRemoteIP;
+    }
+
+    public long getMsgRcvTime() {
+        return msgRcvTime;
+    }
+
+    public void setFailureInfo(DataProxyErrCode errCode) {
+        setFailureInfo(errCode, "");
+    }
+
+    public void setFailureInfo(DataProxyErrCode errCode, String errMsg) {
+        this.errCode = errCode;
+        this.errMsg = errMsg;
+    }
+
+    protected boolean decAttrInfo(BaseSource source, ByteBuf cb,
+            int attrLen, int attrPos) throws Exception {
+        // get attr bytes
+        if (attrLen > 0) {
+            byte[] attrData = new byte[attrLen];
+            cb.getBytes(attrPos, attrData, 0, attrLen);
+            try {
+                this.origAttr = new String(attrData, StandardCharsets.UTF_8);
+            } catch (Throwable err) {
+                //
+            }
+        }
+        // parse attribute field
+        if (StringUtils.isNotBlank(this.origAttr)) {
+            try {
+                this.attrMap.putAll(mapSplitter.split(this.origAttr));
+            } catch (Exception e) {
+                source.fileMetricEventInc(StatConstants.EVENT_INVALIDATTR);
+                this.errCode = DataProxyErrCode.SPLIT_ATTR_ERROR;
+                this.errMsg = String.format("Parse attr (%s) failure", 
this.origAttr);
+                return false;
+            }
+        }
+        // get whether return request
+        if 
("false".equalsIgnoreCase(attrMap.get(AttributeConstants.MESSAGE_IS_ACK))) {
+            this.needResp = false;
+        }
+        return true;
+    }
+
+    protected Map<String, String> buildEventHeaders(long pkgTime) {
+        // build headers
+        Map<String, String> headers = new HashMap<>();
+        headers.put(AttributeConstants.GROUP_ID, groupId);
+        headers.put(AttributeConstants.STREAM_ID, streamId);
+        headers.put(ConfigConstants.TOPIC_KEY, topicName);
+        headers.put(AttributeConstants.DATA_TIME, String.valueOf(dataTimeMs));
+        headers.put(ConfigConstants.REMOTE_IP_KEY, strRemoteIP);
+        headers.put(ConfigConstants.MSG_COUNTER_KEY, String.valueOf(msgCount));
+        headers.put(ConfigConstants.MSG_ENCODE_VER, 
InLongMsgVer.INLONG_V0.getName());
+        headers.put(AttributeConstants.RCV_TIME, String.valueOf(msgRcvTime));
+        // add extra key-value information
+        String pkgTimeStr = attrMap.get(ConfigConstants.PKG_TIME_KEY);
+        if (StringUtils.isBlank(pkgTimeStr)) {
+            pkgTimeStr = DateTimeUtils.ms2yyyyMMddHHmm(pkgTime);
+        }
+        headers.put(ConfigConstants.PKG_TIME_KEY, pkgTimeStr);
+        if (!needResp) {
+            headers.put(AttributeConstants.MESSAGE_IS_ACK, "false");
+        }
+        String syncSend = attrMap.get(AttributeConstants.MESSAGE_SYNC_SEND);
+        if (StringUtils.isNotEmpty(syncSend)) {
+            headers.put(AttributeConstants.MESSAGE_SYNC_SEND, syncSend);
+        }
+        String proxySend = attrMap.get(AttributeConstants.MESSAGE_PROXY_SEND);
+        if (StringUtils.isNotEmpty(proxySend)) {
+            headers.put(AttributeConstants.MESSAGE_PROXY_SEND, proxySend);
+        }
+        String partitionKey = 
attrMap.get(AttributeConstants.MESSAGE_PARTITION_KEY);
+        if (StringUtils.isNotEmpty(partitionKey)) {
+            headers.put(AttributeConstants.MESSAGE_PARTITION_KEY, 
partitionKey);
+        }
+        if (StringUtils.isNotEmpty(this.msgSeqId)) {
+            headers.put(ConfigConstants.SEQUENCE_ID, this.msgSeqId);
+        }
+        return headers;
+    }
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecBinMsg.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecBinMsg.java
new file mode 100644
index 000000000..a93a4fbae
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecBinMsg.java
@@ -0,0 +1,363 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2.v0msg;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.flume.Event;
+import org.apache.flume.event.EventBuilder;
+import org.apache.inlong.common.enums.DataProxyErrCode;
+import org.apache.inlong.common.msg.AttributeConstants;
+import org.apache.inlong.common.msg.InLongMsg;
+import org.apache.inlong.common.msg.MsgType;
+import org.apache.inlong.dataproxy.base.SinkRspEvent;
+import org.apache.inlong.dataproxy.config.CommonConfigHolder;
+import org.apache.inlong.dataproxy.config.ConfigManager;
+import org.apache.inlong.dataproxy.consts.StatConstants;
+import org.apache.inlong.dataproxy.source2.BaseSource;
+import org.apache.inlong.dataproxy.utils.MessageUtils;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_ATTRLEN_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_BODYLEN_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_BODY_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_CNT_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_DT_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_EXTEND_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_FORMAT_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_GROUPIDNUM_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_MAGIC;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_MAGIC_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_MSGTYPE_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_STREAMIDNUM_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_TOTALLEN_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_TOTALLEN_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.BIN_MSG_UNIQ_OFFSET;
+
+public class CodecBinMsg extends AbsV0MsgCodec {
+
+    private int groupIdNum;
+    private int streamIdNum;
+    private int extendField;
+    private long dataTimeSec;
+    private boolean num2name = false;
+    private boolean transNum2Name = false;
+    private boolean isOrderOrProxy = false;
+    private boolean indexMsg = false;
+    private boolean fileCheckMsg = false;
+    private boolean needTraceMsg = false;
+
+    public CodecBinMsg(int totalDataLen, int msgTypeValue,
+            long msgRcvTime, String strRemoteIP) {
+        super(totalDataLen, msgTypeValue, msgRcvTime, strRemoteIP);
+    }
+
+    public boolean descMsg(BaseSource source, ByteBuf cb) throws Exception {
+        int msgHeadPos = cb.readerIndex() - 5;
+        // read fixed field value
+        this.groupIdNum = cb.getUnsignedShort(BIN_MSG_GROUPIDNUM_OFFSET);
+        this.streamIdNum = cb.getUnsignedShort(BIN_MSG_STREAMIDNUM_OFFSET);
+        this.extendField = cb.getUnsignedShort(BIN_MSG_EXTEND_OFFSET);
+        this.dataTimeSec = cb.getUnsignedInt(BIN_MSG_DT_OFFSET);
+        this.dataTimeMs = this.dataTimeSec * 1000;
+        this.msgCount = cb.getUnsignedShort(BIN_MSG_CNT_OFFSET);
+        this.msgCount = (this.msgCount != 0) ? this.msgCount : 1;
+        this.uniq = cb.getUnsignedInt(BIN_MSG_UNIQ_OFFSET);
+        // get body and attribute field length
+        int bodyLen = cb.getInt(msgHeadPos + BIN_MSG_BODYLEN_OFFSET);
+        int attrLen = cb.getShort(msgHeadPos + BIN_MSG_BODY_OFFSET + bodyLen);
+        int msgMagic = cb.getUnsignedShort(msgHeadPos + BIN_MSG_BODY_OFFSET
+                + bodyLen + BIN_MSG_ATTRLEN_SIZE + attrLen);
+        if (bodyLen <= 0) {
+            if (bodyLen == 0) {
+                source.fileMetricEventInc(StatConstants.EVENT_NOBODY);
+                this.errCode = DataProxyErrCode.BODY_LENGTH_ZERO;
+            } else {
+                source.fileMetricEventInc(StatConstants.EVENT_NEGBODY);
+                this.errCode = DataProxyErrCode.BODY_LENGTH_LESS_ZERO;
+            }
+            return false;
+        }
+        // get attribute length
+        if (attrLen < 0) {
+            source.fileMetricEventInc(StatConstants.EVENT_NEGATTR);
+            this.errCode = DataProxyErrCode.ATTR_LENGTH_LESS_ZERO;
+            return false;
+        }
+        // get msg magic
+        if ((msgMagic != BIN_MSG_MAGIC)
+                || (totalDataLen + BIN_MSG_TOTALLEN_SIZE < (bodyLen + attrLen 
+ BIN_MSG_FORMAT_SIZE))) {
+            source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+            this.errCode = DataProxyErrCode.FIELD_VALUE_NOT_EQUAL;
+            this.errMsg = String.format(
+                    "fixedLen(%d) + bodyLen(%d) + attrLen(%d) > 
totalDataLen(%d) + 4 or msgMagic(%d) != %d",
+                    BIN_MSG_FORMAT_SIZE, bodyLen, attrLen, totalDataLen, 
msgMagic, BIN_MSG_MAGIC);
+            return false;
+        }
+        // extract attr bytes
+        if (!decAttrInfo(source, cb, attrLen,
+                msgHeadPos + BIN_MSG_BODY_OFFSET + bodyLen + 
BIN_MSG_ATTRLEN_SIZE)) {
+            return false;
+        }
+        this.bodyData = new byte[bodyLen];
+        cb.getBytes(msgHeadPos + BIN_MSG_BODY_OFFSET, this.bodyData, 0, 
bodyLen);
+        // process extend field value
+        if (((this.extendField & 0x8) == 0x8) || ((this.extendField & 0x10) == 
0x10)) {
+            this.indexMsg = true;
+            this.fileCheckMsg = (this.extendField & 0x8) == 0x8;
+        }
+        if (((extendField & 0x2) >> 1) == 0x1) {
+            this.needTraceMsg = true;
+        }
+        if (((extendField & 0x4) >> 2) == 0x0) {
+            this.num2name = true;
+        }
+        // parse required fields
+        Pair<Boolean, String> evenProcType =
+                
MessageUtils.getEventProcType(attrMap.get(AttributeConstants.MESSAGE_SYNC_SEND),
+                        attrMap.get(AttributeConstants.MESSAGE_PROXY_SEND));
+        this.isOrderOrProxy = evenProcType.getLeft();
+        this.msgProcType = evenProcType.getRight();
+        return true;
+    }
+
+    public boolean validAndFillFields(BaseSource source, StringBuilder 
strBuff) {
+        // reject unsupported index messages
+        if (indexMsg) {
+            source.fileMetricEventInc(StatConstants.EVENT_UNSUPMSG);
+            this.errCode = DataProxyErrCode.UNSUPPORTED_EXTEND_FIELD_VALUE;
+            return false;
+        }
+        // valid and fill topicName
+        if (!validAndFillTopic(source)) {
+            return false;
+        }
+        // build message seqId
+        this.msgSeqId = strBuff.append(this.topicName)
+                .append(AttributeConstants.SEPARATOR).append(this.streamId)
+                .append(AttributeConstants.SEPARATOR).append(strRemoteIP)
+                
.append("#").append(dataTimeMs).append("#").append(uniq).toString();
+        strBuff.delete(0, strBuff.length());
+        // check required rtms attrs
+        if (StringUtils.isBlank(attrMap.get(AttributeConstants.MSG_RPT_TIME))) 
{
+            strBuff.append(AttributeConstants.MSG_RPT_TIME)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgRcvTime);
+            attrMap.put(AttributeConstants.MSG_RPT_TIME, 
String.valueOf(msgRcvTime));
+        }
+        // get trace requirement
+        if (this.needTraceMsg) {
+            if (strBuff.length() > 0) {
+                strBuff.append(AttributeConstants.SEPARATOR);
+            }
+            strBuff.append(AttributeConstants.DATAPROXY_NODE_IP)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(source.getStrPort())
+                    .append(AttributeConstants.SEPARATOR)
+                    .append(AttributeConstants.DATAPROXY_RCVTIME)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgRcvTime);
+            attrMap.put(AttributeConstants.DATAPROXY_NODE_IP, 
source.getSrcHost());
+            attrMap.put(AttributeConstants.DATAPROXY_RCVTIME, 
String.valueOf(msgRcvTime));
+        }
+        // trans groupId and StreamId Num 2 Name
+        if (this.transNum2Name) {
+            if (strBuff.length() > 0) {
+                strBuff.append(AttributeConstants.SEPARATOR);
+            }
+            strBuff.append(AttributeConstants.GROUP_ID)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(groupId)
+                    .append(AttributeConstants.SEPARATOR)
+                    .append(AttributeConstants.STREAM_ID)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(streamId);
+            for (Map.Entry<String, String> entry : attrMap.entrySet()) {
+                if 
(AttributeConstants.GROUP_ID.equalsIgnoreCase(entry.getKey())
+                        || 
AttributeConstants.STREAM_ID.equalsIgnoreCase(entry.getKey())) {
+                    continue;
+                }
+                strBuff.append(AttributeConstants.SEPARATOR)
+                        .append(entry.getKey())
+                        
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(entry.getValue());
+            }
+            this.groupIdNum = 0;
+            this.streamIdNum = 0;
+            this.num2name = false;
+            this.extendField = this.extendField | 0x4;
+            attrMap.put(AttributeConstants.GROUP_ID, groupId);
+            attrMap.put(AttributeConstants.STREAM_ID, streamId);
+        }
+        if (strBuff.length() > 0) {
+            if (StringUtils.isNotBlank(origAttr)) {
+                strBuff.append(AttributeConstants.SEPARATOR).append(origAttr);
+            }
+            totalDataLen += strBuff.length() - origAttr.length();
+            origAttr = strBuff.toString();
+            strBuff.delete(0, strBuff.length());
+        }
+        return true;
+    }
+
+    public Event encEventPackage(BaseSource source, Channel channel) {
+        // fill bin msg package
+        int totalPkgLength = totalDataLen + BIN_MSG_TOTALLEN_SIZE;
+        ByteBuffer dataBuf = ByteBuffer.allocate(totalPkgLength);
+        dataBuf.putInt(BIN_MSG_TOTALLEN_OFFSET, totalDataLen);
+        dataBuf.put(BIN_MSG_MSGTYPE_OFFSET, msgType);
+        dataBuf.putShort(BIN_MSG_GROUPIDNUM_OFFSET, (short) groupIdNum);
+        dataBuf.putShort(BIN_MSG_STREAMIDNUM_OFFSET, (short) streamIdNum);
+        dataBuf.putShort(BIN_MSG_EXTEND_OFFSET, (short) extendField);
+        dataBuf.putInt(BIN_MSG_DT_OFFSET, (int) dataTimeSec);
+        dataBuf.putShort(BIN_MSG_CNT_OFFSET, (short) msgCount);
+        dataBuf.putInt(BIN_MSG_UNIQ_OFFSET, (int) uniq);
+        dataBuf.putInt(BIN_MSG_BODYLEN_OFFSET, bodyData.length);
+        if (bodyData.length > 0) {
+            System.arraycopy(bodyData, 0, dataBuf.array(), 
BIN_MSG_BODY_OFFSET, bodyData.length);
+        }
+        dataBuf.putShort(totalPkgLength
+                - BIN_MSG_ATTRLEN_SIZE - BIN_MSG_MAGIC_SIZE - 
origAttr.length(), (short) origAttr.length());
+        if (origAttr.length() > 0) {
+            System.arraycopy(origAttr.getBytes(StandardCharsets.UTF_8), 0, 
dataBuf.array(),
+                    totalPkgLength - BIN_MSG_MAGIC_SIZE - origAttr.length(), 
bodyData.length);
+        }
+        dataBuf.putShort(totalPkgLength - BIN_MSG_MAGIC_SIZE, (short) 
BIN_MSG_MAGIC);
+        // build InLong message
+        InLongMsg inLongMsg = InLongMsg.newInLongMsg(source.isCompressed(), 4);
+        inLongMsg.addMsg(dataBuf.array());
+        long pkgTime = inLongMsg.getCreatetime();
+        Event event = EventBuilder.withBody(inLongMsg.buildArray(), 
buildEventHeaders(pkgTime));
+        if (isOrderOrProxy) {
+            event = new SinkRspEvent(event, MsgType.MSG_BIN_MULTI_BODY, 
channel);
+        }
+        inLongMsg.reset();
+        return event;
+    }
+
+    private boolean validAndFillTopic(BaseSource source) {
+        // valid groupId, streamId
+        ConfigManager configManager = ConfigManager.getInstance();
+        this.groupId = this.attrMap.get(AttributeConstants.GROUP_ID);
+        this.streamId = this.attrMap.get(AttributeConstants.STREAM_ID);
+        if (num2name) {
+            if (this.groupIdNum == 0) {
+                source.fileMetricEventInc(StatConstants.EVENT_WITHOUTGROUPID);
+                this.errCode = DataProxyErrCode.MISS_REQUIRED_GROUPID_ARGUMENT;
+                this.errMsg = "groupIdNum is 0 in message";
+                return false;
+            }
+            String confGroupId;
+            String confStreamId;
+            String strGroupIdNum = String.valueOf(this.groupIdNum);
+            if (configManager.getGroupIdMappingProperties() == null) {
+                source.fileMetricEventInc(StatConstants.EVENT_SERVICE_UNREADY);
+                this.errCode = DataProxyErrCode.CONF_SERVICE_UNREADY;
+                this.errMsg = "GroupId-Mapping configuration is null";
+                return false;
+            }
+            confGroupId = 
configManager.getGroupIdMappingProperties().get(strGroupIdNum);
+            if (StringUtils.isBlank(confGroupId)) {
+                source.fileMetricEventInc(StatConstants.EVENT_WITHOUTGROUPID);
+                this.errCode = 
DataProxyErrCode.GROUPID_OR_STREAMID_NOT_CONFIGURE;
+                this.errMsg = String.format("Non-existing groupIdNum(%s) 
configuration", strGroupIdNum);
+                return false;
+            }
+            if (StringUtils.isNotBlank(this.groupId) && 
!this.groupId.equalsIgnoreCase(confGroupId)) {
+                
source.fileMetricEventInc(StatConstants.EVENT_INCONSGROUPORSTREAMID);
+                this.errCode = DataProxyErrCode.GROUPID_OR_STREAMID_INCONSTANT;
+                this.errMsg = String.format(
+                        "Inconstant GroupId not equal, (%s) in attr but (%s) 
in configure by groupIdNum(%s)",
+                        this.groupId, confGroupId, strGroupIdNum);
+                return false;
+            }
+            this.groupId = confGroupId;
+            // check streamId
+            if (this.streamIdNum == 0) {
+                if (StringUtils.isNotBlank(this.streamId)) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_INCONSGROUPORSTREAMID);
+                    this.errCode = 
DataProxyErrCode.GROUPID_OR_STREAMID_INCONSTANT;
+                    this.errMsg = String.format("Inconstant streamId(%s) in 
attr but streamIdNum=0", this.streamId);
+                    return false;
+                }
+            } else {
+                if (configManager.getStreamIdMappingProperties() == null) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_SERVICE_UNREADY);
+                    this.errCode = DataProxyErrCode.CONF_SERVICE_UNREADY;
+                    this.errMsg = "StreamId-Mapping configuration is null";
+                    return false;
+                }
+                Map<String, String> confStreamIdMap =
+                        
configManager.getStreamIdMappingProperties().get(strGroupIdNum);
+                if (confStreamIdMap == null) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_SERVICE_UNREADY);
+                    this.errCode = DataProxyErrCode.CONF_SERVICE_UNREADY;
+                    this.errMsg = "GroupId in StreamId-Mapping configuration 
is null";
+                    return false;
+                }
+                String strStreamIdNum = String.valueOf(this.streamIdNum);
+                confStreamId = confStreamIdMap.get(strStreamIdNum);
+                if (StringUtils.isBlank(confStreamId)) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_WITHOUTGROUPID);
+                    this.errCode = 
DataProxyErrCode.GROUPID_OR_STREAMID_NOT_CONFIGURE;
+                    this.errMsg = String.format("Non-existing 
GroupId(%s)-StreamId(%s) configuration",
+                            strGroupIdNum, strStreamIdNum);
+                    return false;
+                }
+                if (StringUtils.isNotBlank(this.streamId) && 
!this.streamId.equalsIgnoreCase(confStreamId)) {
+                    
source.fileMetricEventInc(StatConstants.EVENT_INCONSGROUPORSTREAMID);
+                    this.errCode = 
DataProxyErrCode.GROUPID_OR_STREAMID_INCONSTANT;
+                    this.errMsg = String.format(
+                            "Inconstant StreamId, (%s) in attr but (%s) in 
configure by groupIdNum(%s), streamIdNum(%s)",
+                            this.streamId, confStreamId, strGroupIdNum, 
strStreamIdNum);
+                    return false;
+                }
+                this.streamId = confStreamId;
+            }
+            // check whether enable num 2 name translate
+            String enableTrans = 
(configManager.getGroupIdEnableMappingProperties() == null)
+                    ? null
+                    : 
configManager.getGroupIdEnableMappingProperties().get(strGroupIdNum);
+            if ("true".equalsIgnoreCase(enableTrans) && this.num2name) {
+                this.transNum2Name = true;
+            }
+        } else {
+            if (StringUtils.isBlank(groupId)) {
+                source.fileMetricEventInc(StatConstants.EVENT_WITHOUTGROUPID);
+                this.errCode = DataProxyErrCode.MISS_REQUIRED_GROUPID_ARGUMENT;
+                return false;
+            }
+        }
+        // get and check topic configure
+        this.topicName = configManager.getTopicName(this.groupId, 
this.streamId);
+        if (StringUtils.isBlank(this.topicName)) {
+            if (CommonConfigHolder.getInstance().isNoTopicAccept()) {
+                this.topicName = source.getDefTopic();
+            } else {
+                source.fileMetricEventInc(StatConstants.EVENT_NOTOPIC);
+                this.errCode = DataProxyErrCode.TOPIC_IS_BLANK;
+                this.errMsg = String.format("Topic is null for 
inlongGroupId=(%s), inlongStreamId=(%s)",
+                        this.groupId, this.streamId);
+                return false;
+            }
+        }
+        if (StringUtils.isBlank(this.streamId)) {
+            this.streamId = "";
+        }
+        return true;
+    }
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecTextMsg.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecTextMsg.java
new file mode 100644
index 000000000..9d521ccb1
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/CodecTextMsg.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2.v0msg;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.flume.Event;
+import org.apache.flume.event.EventBuilder;
+import org.apache.inlong.common.enums.DataProxyErrCode;
+import org.apache.inlong.common.msg.AttributeConstants;
+import org.apache.inlong.common.msg.InLongMsg;
+import org.apache.inlong.common.msg.MsgType;
+import org.apache.inlong.dataproxy.config.CommonConfigHolder;
+import org.apache.inlong.dataproxy.config.ConfigManager;
+import org.apache.inlong.dataproxy.consts.StatConstants;
+import org.apache.inlong.dataproxy.source2.BaseSource;
+import org.xerial.snappy.Snappy;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.TXT_MSG_BODYLEN_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.TXT_MSG_BODY_OFFSET;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.TXT_MSG_FORMAT_SIZE;
+import static 
org.apache.inlong.dataproxy.source2.v0msg.MsgFieldConsts.TXT_MSG_TOTALLEN_SIZE;
+
+public class CodecTextMsg extends AbsV0MsgCodec {
+
+    public CodecTextMsg(int totalDataLen, int msgTypeValue,
+            long msgRcvTime, String strRemoteIP) {
+        super(totalDataLen, msgTypeValue, msgRcvTime, strRemoteIP);
+    }
+
+    public boolean descMsg(BaseSource source, ByteBuf cb) throws Exception {
+        // get body length
+        int msgHeadPos = cb.readerIndex() - 5;
+        int bodyLen = cb.getInt(msgHeadPos + TXT_MSG_BODYLEN_OFFSET);
+        if (bodyLen <= 0) {
+            if (bodyLen == 0) {
+                source.fileMetricEventInc(StatConstants.EVENT_NOBODY);
+                this.errCode = DataProxyErrCode.BODY_LENGTH_ZERO;
+            } else {
+                source.fileMetricEventInc(StatConstants.EVENT_NEGBODY);
+                this.errCode = DataProxyErrCode.BODY_LENGTH_LESS_ZERO;
+            }
+            return false;
+        }
+        if (bodyLen + TXT_MSG_FORMAT_SIZE > totalDataLen + 
TXT_MSG_TOTALLEN_SIZE) {
+            this.errCode = DataProxyErrCode.BODY_EXCEED_MAX_LEN;
+            this.errMsg = String.format("Error msg, bodyLen(%d) + 
fixedLength(%d) > totalDataLen(%d) + 4",
+                    bodyLen, TXT_MSG_FORMAT_SIZE, totalDataLen);
+            return false;
+        }
+        // extract body bytes
+        this.bodyData = new byte[bodyLen];
+        cb.getBytes(msgHeadPos + TXT_MSG_BODY_OFFSET, this.bodyData, 0, 
bodyLen);
+        // get attribute length
+        int attrLen = cb.getInt(msgHeadPos + TXT_MSG_BODY_OFFSET + bodyLen);
+        if (attrLen < 0) {
+            this.errCode = DataProxyErrCode.ATTR_LENGTH_LESS_ZERO;
+            return false;
+        }
+        // check attribute length
+        if (totalDataLen + TXT_MSG_TOTALLEN_SIZE != TXT_MSG_FORMAT_SIZE + 
bodyLen + attrLen) {
+            this.errCode = DataProxyErrCode.BODY_EXCEED_MAX_LEN;
+            this.errMsg = String.format(
+                    "Error msg, totalDataLen(%d) + 4 != fixedLength(%d) + 
bodyLen(%d) + attrLen(%d)",
+                    totalDataLen, TXT_MSG_FORMAT_SIZE, bodyLen, attrLen);
+            return false;
+        }
+        // extract attr bytes
+        if (!decAttrInfo(source, cb, attrLen, msgHeadPos + TXT_MSG_FORMAT_SIZE 
+ bodyLen)) {
+            return false;
+        }
+        // decompress body data
+        if 
(StringUtils.isNotBlank(attrMap.get(AttributeConstants.COMPRESS_TYPE))) {
+            byte[] unCompressedData;
+            try {
+                int uncompressedLen = Snappy.uncompressedLength(bodyData, 0, 
bodyData.length);
+                unCompressedData = new byte[uncompressedLen];
+                Snappy.uncompress(bodyData, 0, bodyData.length, 
unCompressedData, 0);
+            } catch (IOException e) {
+                source.fileMetricEventInc(StatConstants.EVENT_UNPRESSEXP);
+                this.errCode = DataProxyErrCode.UNCOMPRESS_DATA_ERROR;
+                this.errMsg = String.format("Error to uncompress msg, compress 
type(%s), attr: (%s), error: (%s)",
+                        attrMap.get(AttributeConstants.COMPRESS_TYPE), 
origAttr, e.getCause());
+                return false;
+            }
+            if (unCompressedData.length == 0) {
+                source.fileMetricEventInc(StatConstants.EVENT_UNPRESSEXP);
+                this.errCode = DataProxyErrCode.UNCOMPRESS_DATA_ERROR;
+                this.errMsg = String.format("Error to uncompress msg, compress 
type(%s), attr: (%s), error: 2",
+                        attrMap.get(AttributeConstants.COMPRESS_TYPE), 
origAttr);
+                return false;
+            }
+            this.bodyData = unCompressedData;
+        }
+        // check body items
+        if (MsgType.MSG_MULTI_BODY.equals(MsgType.valueOf(msgType))) {
+            int readPos = 0;
+            int singleMsgLen;
+            ByteBuffer bodyBuffer = ByteBuffer.wrap(bodyData);
+            while (bodyBuffer.remaining() > 0) {
+                singleMsgLen = bodyBuffer.getInt(readPos);
+                if (singleMsgLen <= 0 || singleMsgLen > 
bodyBuffer.remaining()) {
+                    source.fileMetricEventInc(StatConstants.EVENT_MALFORMED);
+                    this.errCode = DataProxyErrCode.BODY_EXCEED_MAX_LEN;
+                    this.errMsg = String.format(
+                            "Malformed data len, singleMsgLen(%d), buffer 
remaining(%d), attr: (%s)",
+                            singleMsgLen, bodyBuffer.remaining(), origAttr);
+                    return false;
+                }
+                readPos += 4 + singleMsgLen;
+            }
+        }
+        return true;
+    }
+
+    public boolean validAndFillFields(BaseSource source, StringBuilder 
strBuff) {
+        // process topic field
+        String tmpGroupId = attrMap.get(AttributeConstants.GROUP_ID);
+        String tmpStreamId = attrMap.get(AttributeConstants.STREAM_ID);
+        if (StringUtils.isBlank(tmpGroupId)) {
+            source.fileMetricEventInc(StatConstants.EVENT_WITHOUTGROUPID);
+            this.errCode = DataProxyErrCode.MISS_REQUIRED_GROUPID_ARGUMENT;
+            return false;
+        }
+        // get and check topic configure
+        String tmpTopicName = 
ConfigManager.getInstance().getTopicName(tmpGroupId, tmpStreamId);
+        if (StringUtils.isBlank(tmpTopicName)) {
+            if (CommonConfigHolder.getInstance().isNoTopicAccept()) {
+                tmpTopicName = source.getDefTopic();
+            } else {
+                source.fileMetricEventInc(StatConstants.EVENT_NOTOPIC);
+                this.errCode = DataProxyErrCode.TOPIC_IS_BLANK;
+                this.errMsg = String.format(
+                        "Topic is null for inlongGroupId=(%s), 
inlongStreamId=(%s)", tmpGroupId, tmpStreamId);
+                return false;
+            }
+        }
+        this.groupId = tmpGroupId;
+        this.topicName = tmpTopicName;
+        if (StringUtils.isNotBlank(tmpStreamId)) {
+            this.streamId = tmpStreamId;
+        }
+        // process message count
+        this.msgCount = 1;
+        String cntStr = attrMap.get(AttributeConstants.MESSAGE_COUNT);
+        if (StringUtils.isBlank(cntStr)) {
+            attrMap.put(AttributeConstants.MESSAGE_COUNT, 
String.valueOf(this.msgCount));
+        } else {
+            try {
+                this.msgCount = Integer.parseInt(cntStr);
+            } catch (Throwable e) {
+                attrMap.put(AttributeConstants.MESSAGE_COUNT, 
String.valueOf(this.msgCount));
+            }
+        }
+        // process data-time
+        this.dataTimeMs = msgRcvTime;
+        String strDataTime = attrMap.get(AttributeConstants.DATA_TIME);
+        if (StringUtils.isBlank(strDataTime)) {
+            attrMap.put(AttributeConstants.DATA_TIME, 
String.valueOf(this.dataTimeMs));
+        } else {
+            try {
+                this.dataTimeMs = Long.parseLong(strDataTime);
+            } catch (Throwable e) {
+                attrMap.put(AttributeConstants.DATA_TIME, 
String.valueOf(this.dataTimeMs));
+            }
+        }
+        // process sequence id
+        String sequenceId = attrMap.get(AttributeConstants.SEQUENCE_ID);
+        if (StringUtils.isNotBlank(sequenceId)) {
+            
strBuff.append(topicName).append(AttributeConstants.SEPARATOR).append(streamId)
+                    .append(AttributeConstants.SEPARATOR).append(sequenceId)
+                    .append("#").append(strRemoteIP);
+            msgSeqId = strBuff.toString();
+            strBuff.delete(0, strBuff.length());
+        }
+        // append required attributes
+        if (StringUtils.isBlank(attrMap.get(AttributeConstants.RCV_TIME))) {
+            strBuff.append(AttributeConstants.RCV_TIME)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgRcvTime);
+            attrMap.put(AttributeConstants.RCV_TIME, 
String.valueOf(msgRcvTime));
+        }
+        if (StringUtils.isBlank(attrMap.get(AttributeConstants.MSG_RPT_TIME))) 
{
+            if (strBuff.length() > 0) {
+                strBuff.append(AttributeConstants.SEPARATOR);
+            }
+            strBuff.append(AttributeConstants.MSG_RPT_TIME)
+                    
.append(AttributeConstants.KEY_VALUE_SEPARATOR).append(msgRcvTime);
+            attrMap.put(AttributeConstants.MSG_RPT_TIME, 
String.valueOf(msgRcvTime));
+        }
+        // rebuild attribute string
+        if (strBuff.length() > 0) {
+            if (StringUtils.isNotBlank(origAttr)) {
+                strBuff.append(AttributeConstants.SEPARATOR).append(origAttr);
+            }
+            totalDataLen += strBuff.length() - origAttr.length();
+            origAttr = strBuff.toString();
+            strBuff.delete(0, strBuff.length());
+        }
+        return true;
+    }
+
+    public Event encEventPackage(BaseSource source, Channel channel) {
+        // build InLongMsg object
+        int inLongMsgVer = 1;
+        if (MsgType.MSG_MULTI_BODY_ATTR.equals(MsgType.valueOf(msgType))) {
+            inLongMsgVer = 3;
+        }
+        InLongMsg inLongMsg = InLongMsg.newInLongMsg(source.isCompressed(), 
inLongMsgVer);
+        if (MsgType.MSG_MULTI_BODY.equals(MsgType.valueOf(msgType))) {
+            int calcCnt = 0;
+            int singleMsgLen;
+            ByteBuffer bodyBuffer = ByteBuffer.wrap(bodyData);
+            attrMap.put(AttributeConstants.MESSAGE_COUNT, String.valueOf(1));
+            while (bodyBuffer.remaining() > 0) {
+                singleMsgLen = bodyBuffer.getInt();
+                if (singleMsgLen <= 0 || singleMsgLen > 
bodyBuffer.remaining()) {
+                    break;
+                }
+                byte[] record = new byte[singleMsgLen];
+                bodyBuffer.get(record);
+                inLongMsg.addMsg(mapJoiner.join(attrMap), bodyBuffer);
+                calcCnt++;
+            }
+            attrMap.put(AttributeConstants.MESSAGE_COUNT, 
String.valueOf(calcCnt));
+            this.msgCount = calcCnt;
+        } else if 
(MsgType.MSG_MULTI_BODY_ATTR.equals(MsgType.valueOf(msgType))) {
+            attrMap.put(AttributeConstants.MESSAGE_COUNT, String.valueOf(1));
+            inLongMsg.addMsg(mapJoiner.join(attrMap), bodyData);
+            attrMap.put(AttributeConstants.MESSAGE_COUNT, 
String.valueOf(this.msgCount));
+        } else {
+            inLongMsg.addMsg(mapJoiner.join(attrMap), bodyData);
+        }
+        long pkgTime = inLongMsg.getCreatetime();
+        Event event = EventBuilder.withBody(inLongMsg.buildArray(), 
buildEventHeaders(pkgTime));
+        inLongMsg.reset();
+        return event;
+    }
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/MsgFieldConsts.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/MsgFieldConsts.java
new file mode 100644
index 000000000..20b0e884e
--- /dev/null
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/source2/v0msg/MsgFieldConsts.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inlong.dataproxy.source2.v0msg;
+
+public class MsgFieldConsts {
+
+    public static final int BIN_MSG_FORMAT_SIZE = 29;
+    public static final int BIN_MSG_TOTALLEN_OFFSET = 0;
+    public static final int BIN_MSG_TOTALLEN_SIZE = 4;
+    public static final int BIN_MSG_FIXED_CONTENT_SIZE = BIN_MSG_FORMAT_SIZE - 
BIN_MSG_TOTALLEN_SIZE;
+    public static final int BIN_MSG_MSGTYPE_OFFSET = 4;
+    public static final int BIN_MSG_MSGTYPE_SIZE = 1;
+    public static final int BIN_MSG_GROUPIDNUM_OFFSET = 5;
+    public static final int BIN_MSG_GROUPIDNUM_SIZE = 2;
+    public static final int BIN_MSG_STREAMIDNUM_OFFSET = 7;
+    public static final int BIN_MSG_STREAMIDNUM_SIZE = 2;
+    public static final int BIN_MSG_EXTEND_OFFSET = 9;
+    public static final int BIN_MSG_EXTEND_SIZE = 2;
+    public static final int BIN_MSG_DT_OFFSET = 11;
+    public static final int BIN_MSG_DT_SIZE = 4;
+    public static final int BIN_MSG_CNT_OFFSET = 15;
+    public static final int BIN_MSG_CNT_SIZE = 2;
+    public static final int BIN_MSG_UNIQ_OFFSET = 17;
+    public static final int BIN_MSG_UNIQ_SIZE = 4;
+    public static final int BIN_MSG_SET_SNAPPY = (1 << 5);
+    public static final int BIN_MSG_BODYLEN_OFFSET = 21;
+    public static final int BIN_MSG_BODYLEN_SIZE = 4;
+    public static final int BIN_MSG_BODY_OFFSET = BIN_MSG_BODYLEN_SIZE + 
BIN_MSG_BODYLEN_OFFSET;
+    public static final int BIN_MSG_ATTRLEN_SIZE = 2;
+    public static final int BIN_MSG_MAGIC_SIZE = 2;
+    public static final int BIN_MSG_MAGIC = 0xEE01;
+
+    public static final int BIN_HB_FORMAT_SIZE = 18;
+    public static final int BIN_HB_TOTALLEN_OFFSET = 0;
+    public static final int BIN_HB_TOTALLEN_SIZE = 4;
+    public static final int BIN_HB_FIXED_CONTENT_SIZE = BIN_HB_FORMAT_SIZE - 
BIN_HB_TOTALLEN_SIZE;
+    public static final int BIN_HB_MSGTYPE_OFFSET = 4;
+    public static final int BIN_HB_MSGTYPE_SIZE = 1;
+    public static final int BIN_HB_DATATIME_OFFSET = 5;
+    public static final int BIN_HB_DATATIME_SIZE = 4;
+    public static final int BIN_HB_VERSION_OFFSET = 9;
+    public static final int BIN_HB_VERSION_SIZE = 1;
+    public static final int BIN_HB_BODYLEN_OFFSET = 10;
+    public static final int BIN_HB_BODYLEN_SIZE = 4;
+    public static final int BIN_HB_BODY_OFFSET = BIN_HB_BODYLEN_SIZE + 
BIN_HB_BODYLEN_OFFSET;
+    public static final int BIN_HB_ATTRLEN_SIZE = 2;
+
+    public static final int TXT_MSG_FORMAT_SIZE = 13;
+    public static final int TXT_MSG_TOTALLEN_OFFSET = 0;
+    public static final int TXT_MSG_TOTALLEN_SIZE = 4;
+    public static final int TXT_MSG_FIXED_CONTENT_SIZE = TXT_MSG_FORMAT_SIZE - 
TXT_MSG_TOTALLEN_SIZE;
+    public static final int TXT_MSG_MSGTYPE_OFFSET = 4;
+    public static final int TXT_MSG_MSGTYPE_SIZE = 1;
+    public static final int TXT_MSG_BODYLEN_OFFSET = 5;
+    public static final int TXT_MSG_BODYLEN_SIZE = 4;
+    public static final int TXT_MSG_BODY_OFFSET = TXT_MSG_BODYLEN_SIZE + 
TXT_MSG_BODYLEN_OFFSET;
+    public static final int TXT_MSG_ATTRLEN_SIZE = 4;
+
+}
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/AddressUtils.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/AddressUtils.java
index 5ed9eb345..073341370 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/AddressUtils.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/AddressUtils.java
@@ -26,20 +26,32 @@ public class AddressUtils {
 
     private static final Logger logger = 
LoggerFactory.getLogger(AddressUtils.class);
 
+    public static String getChannelLocalIP(Channel channel) {
+        return getChannelIP(channel, true);
+    }
+
     public static String getChannelRemoteIP(Channel channel) {
+        return getChannelIP(channel, false);
+    }
+
+    private static String getChannelIP(Channel channel, boolean isLocal) {
         if (channel == null) {
             return null;
         }
-        SocketAddress rmtAddress = channel.remoteAddress();
-        if (rmtAddress == null) {
+        SocketAddress address = isLocal ? channel.localAddress() : 
channel.remoteAddress();
+        if (address == null) {
             return null;
         }
-        String strRemoteIP = rmtAddress.toString();
+        String strAddrIP = address.toString();
         try {
-            strRemoteIP = strRemoteIP.substring(1, strRemoteIP.indexOf(':'));
-            return strRemoteIP;
+            strAddrIP = strAddrIP.substring(1, strAddrIP.indexOf(':'));
+            return strAddrIP;
         } catch (Exception ee) {
-            logger.warn("Fail to get the remote IP, rmtAddress = {}", 
rmtAddress);
+            if (isLocal) {
+                logger.warn("Fail to get the local IP, localAddress = {}", 
address);
+            } else {
+                logger.warn("Fail to get the remote IP, remoteAddress = {}", 
address);
+            }
             return null;
         }
     }
diff --git 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/MessageUtils.java
 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/MessageUtils.java
index fdb3f8d9f..74ed688ee 100644
--- 
a/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/MessageUtils.java
+++ 
b/inlong-dataproxy/dataproxy-source/src/main/java/org/apache/inlong/dataproxy/utils/MessageUtils.java
@@ -22,7 +22,6 @@ import static 
org.apache.inlong.common.util.NetworkUtils.getLocalIp;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
@@ -195,11 +194,10 @@ public class MessageUtils {
         ByteBuf binBuffer;
         final StringBuilder strBuff = new StringBuilder(512);
         // get and check channel context
-        ChannelHandlerContext ctx = event.getCtx();
-        if (ctx == null || ctx.channel() == null || !ctx.channel().isActive()) 
{
+        Channel remoteChannel = event.getChannel();
+        if (remoteChannel == null || !remoteChannel.isActive()) {
             return;
         }
-        Channel remoteChannel = ctx.channel();
         // check message type
         MsgType msgType = event.getMsgType();
         if (MsgType.MSG_UNKNOWN.equals(msgType)


Reply via email to