add baidu-brpc-java-3.x plugin (#321)

* add baidu-brpc3 trace plugin

Co-authored-by: wangqingpeng <wangqingpeng@baidu.com>
diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml
index b6b70ba..71f9c7e 100644
--- a/.github/workflows/plugins-test.3.yaml
+++ b/.github/workflows/plugins-test.3.yaml
@@ -72,6 +72,7 @@
           - nats-2.14.x-2.15.x-scenario
           - quasar-scenario
           - baidu-brpc-scenario
+          - baidu-brpc-3.x-scenario
           - retransform-class-scenario
           - retransform-class-tomcat-scenario
           - graphql-8.x-scenario
diff --git a/CHANGES.md b/CHANGES.md
index 830f16e..7c7150f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,7 @@
 * Add plugin to support [Impala JDBC](https://www.cloudera.com/downloads/connectors/impala/jdbc/2-6-29.html) 2.6.x.
 * Update guava-cache, jedis, memcached, ehcache plugins to adopt uniform tags.
 * Fix `Apache ShenYu` plugin traceId empty string value. 
+* Add plugin to support [brpc-java-3.x](https://github.com/baidu/starlight/tree/brpc-java-v3)
 
 #### Documentation
 
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml
new file mode 100644
index 0000000..6ab48ef
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apm-sdk-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>8.13.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+
+    <artifactId>baidu-brpc-3.x-plugin</artifactId>
+    <name>baidu-brpc-3.x-plugin</name>
+
+    <properties>
+        <brpc-java.version>3.0.5</brpc-java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.baidu</groupId>
+            <artifactId>brpc-java</artifactId>
+            <version>${brpc-java.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInstrumentation.java
new file mode 100644
index 0000000..c3dc5d5
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInstrumentation.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.plugin.baidu.brpc3;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+
+/**
+ * brpc3 client instrumentation
+ */
+public class ClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.baidu.brpc3.ClientInterceptor";
+    public static final String ENHANCE_CLASS = "com.baidu.brpc.client.CommunicationClient";
+    public static final String ENHANCE_METHOD = "execute";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return NameMatch.byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[] {
+                new ConstructorInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                        return ElementMatchers.takesArguments(any());
+                    }
+
+                    @Override
+                    public String getConstructorInterceptor() {
+                        return INTERCEPTOR_CLASS;
+                    }
+                }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[] {
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(ENHANCE_METHOD);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptor.java
new file mode 100644
index 0000000..0000c81
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptor.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.plugin.baidu.brpc3;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import com.baidu.brpc.client.channel.ServiceInstance;
+import com.baidu.brpc.protocol.Request;
+import com.baidu.brpc.protocol.Response;
+
+/**
+ * brpc3 client interceptor
+ */
+public class ClientInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor {
+    @Override
+    public void onConstruct(EnhancedInstance enhancedInstance, Object[] objects) throws Throwable {
+        ServiceInstance url = (ServiceInstance) objects[0];
+        enhancedInstance.setSkyWalkingDynamicField(url.getIp() + ":" + url.getPort());
+    }
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) throws Throwable {
+        String peer = (String) objInst.getSkyWalkingDynamicField();
+        Request request = (Request) allArguments[0];
+        String operationName = generateOperationName(request);
+        final ContextCarrier contextCarrier = new ContextCarrier();
+        AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, peer);
+
+        CarrierItem next = contextCarrier.items();
+        if (request.getKvAttachment() == null) {
+            request.setKvAttachment(new HashMap<>());
+        }
+        while (next.hasNext()) {
+            next = next.next();
+            request.getKvAttachment().put(next.getHeadKey(), next.getHeadValue());
+        }
+        span.setComponent(ComponentsDefine.BRPC_JAVA);
+        SpanLayer.asRPCFramework(span);
+        Tags.URL.set(span, peer + "/" + operationName);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) throws Throwable {
+        Response response = (Response) allArguments[1];
+        if (response != null && response.getException() != null) {
+            dealException(response.getException());
+        }
+
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+        dealException(t);
+    }
+
+    private void dealException(Throwable throwable) {
+        AbstractSpan span = ContextManager.activeSpan();
+        span.log(throwable);
+    }
+
+    private String generateOperationName(Request request) {
+        StringBuilder operationName = new StringBuilder();
+        operationName.append(request.getServiceName() + "." + request.getMethodName());
+        return operationName.toString();
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInstrumentation.java
new file mode 100644
index 0000000..1ef354e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInstrumentation.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.plugin.baidu.brpc3;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * brpc3 server instrumentation
+ */
+public class ServerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.baidu.brpc3.ServerInterceptor";
+    public static final String ENHANCE_CLASS = "com.baidu.brpc.interceptor.ServerTraceInterceptor";
+    public static final String ENHANCE_METHOD = "aroundProcess";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return NameMatch.byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[] {
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(ENHANCE_METHOD);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptor.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptor.java
new file mode 100644
index 0000000..37d7aa1
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptor.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.plugin.baidu.brpc3;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import com.baidu.brpc.protocol.Request;
+import com.baidu.brpc.protocol.Response;
+
+/**
+ * brpc3 server interceptor
+ */
+public class ServerInterceptor implements InstanceMethodsAroundInterceptor {
+    private static String generateOperationName(Request request) {
+        StringBuilder operationName = new StringBuilder(request.getServiceName());
+        operationName.append(".").append(request.getMethodName());
+        return operationName.toString();
+    }
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) throws Throwable {
+        Request request = (Request) allArguments[0];
+        ContextCarrier contextCarrier = new ContextCarrier();
+        CarrierItem next = contextCarrier.items();
+        if (request.getKvAttachment() == null) {
+            request.setKvAttachment(new HashMap<>());
+        }
+        while (next.hasNext()) {
+            next = next.next();
+            next.setHeadValue((String) request.getKvAttachment().get(next.getHeadKey()));
+        }
+
+        String operationName = generateOperationName(request);
+        AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
+        SpanLayer.asRPCFramework(span);
+        span.setComponent(ComponentsDefine.BRPC_JAVA);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) throws Throwable {
+        Response response = (Response) allArguments[1];
+        if (response != null && response.getException() != null) {
+            AbstractSpan span = ContextManager.activeSpan();
+            span.log(response.getException());
+        }
+
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+        AbstractSpan activeSpan = ContextManager.activeSpan();
+        activeSpan.log(t);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000..48067a8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+brpc-java-3.x=org.apache.skywalking.apm.plugin.baidu.brpc3.ClientInstrumentation
+brpc-java-3.x=org.apache.skywalking.apm.plugin.baidu.brpc3.ServerInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptorTest.java
new file mode 100644
index 0000000..66a7687
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ClientInterceptorTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.baidu.brpc3;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.util.List;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.context.util.TagValuePair;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import com.baidu.brpc.protocol.Request;
+import com.baidu.brpc.protocol.Response;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ClientInterceptorTest {
+    @Rule
+    public AgentServiceRule agentServiceRule = new AgentServiceRule();
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+    @Mock
+    private EnhancedInstance enhancedInstance;
+
+    private ClientInterceptor clientInterceptor;
+
+    private Request request = PowerMockito.mock(Request.class);
+    private Response response = PowerMockito.mock(Response.class);
+
+    @Mock
+    private MethodInterceptResult methodInterceptResult;
+
+    private Object[] allArguments;
+    private Class[] argumentTypes;
+
+    @Before
+    public void setUp() throws Exception {
+        clientInterceptor = new ClientInterceptor();
+
+        when(request.getMethodName()).thenReturn("testMethod");
+        when(request.getServiceName()).thenReturn("testService");
+        when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:8123");
+
+        allArguments = new Object[] {request, response};
+        argumentTypes = new Class[] {request.getClass(), response.getClass()};
+        Config.Agent.SERVICE_NAME = "BRPC3-TestCases-APP";
+    }
+
+    @Test
+    public void testConsumerWithAttachment() throws Throwable {
+        clientInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
+        clientInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, response);
+
+        assertThat(segmentStorage.getTraceSegments().size(), is(1));
+        TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+        List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+        assertThat(spans.size(), is(1));
+        assertConsumerSpan(spans.get(0));
+    }
+
+    private void assertConsumerSpan(AbstractTracingSpan span) {
+        assertCommonsAttribute(span);
+        assertTrue(span.isExit());
+    }
+
+    private void assertCommonsAttribute(AbstractTracingSpan span) {
+        List<TagValuePair> tags = SpanHelper.getTags(span);
+        assertThat(tags.size(), is(1));
+        assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.RPC_FRAMEWORK));
+        assertThat(SpanHelper.getComponentId(span), is(91));
+        assertThat(tags.get(0).getValue(), is("127.0.0.1:8123/testService.testMethod"));
+        assertThat(span.getOperationName(), is("testService.testMethod"));
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptorTest.java
new file mode 100644
index 0000000..bcc4c7f
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/baidu/brpc3/ServerInterceptorTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.plugin.baidu.brpc3;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.context.SW8CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegmentRef;
+import org.apache.skywalking.apm.agent.core.context.util.TagValuePair;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.helper.SegmentRefHelper;
+import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import com.baidu.brpc.interceptor.InterceptorChain;
+import com.baidu.brpc.protocol.Request;
+import com.baidu.brpc.protocol.Response;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ServerInterceptorTest {
+    @Rule
+    public AgentServiceRule agentServiceRule = new AgentServiceRule();
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+    @Mock
+    private EnhancedInstance enhancedInstance;
+
+    private ServerInterceptor serverInterceptor;
+
+    private Request request = PowerMockito.mock(Request.class);
+    private Response response = PowerMockito.mock(Response.class);
+
+    private InterceptorChain interceptorChain = PowerMockito.mock(InterceptorChain.class);
+
+    @Mock
+    private MethodInterceptResult methodInterceptResult;
+
+    private Object[] allArguments;
+    private Class[] argumentTypes;
+
+    @Before
+    public void setUp() throws Exception {
+        serverInterceptor = new ServerInterceptor();
+
+        Map<String, Object> kvAttachment = PowerMockito.mock(Map.class);
+        when(kvAttachment.get(SW8CarrierItem.HEADER_NAME)).thenReturn("1-My40LjU=-MS4yLjM=-3-c2VydmljZQ"
+                + "==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA=");
+        when(request.getKvAttachment()).thenReturn(kvAttachment);
+
+        when(request.getMethodName()).thenReturn("testMethod");
+        when(request.getServiceName()).thenReturn("testService");
+        when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:8123");
+
+        allArguments = new Object[] {request, response, interceptorChain};
+        argumentTypes = new Class[] {request.getClass(), response.getClass(), interceptorChain.getClass()};
+        Config.Agent.SERVICE_NAME = "BRPC3-TestCases-APP";
+    }
+
+    @Test
+    public void testProviderWithAttachment() throws Throwable {
+        serverInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
+        serverInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, response);
+        assertProvider();
+    }
+
+    private void assertProvider() {
+        TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+        assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+        assertProviderSpan(SegmentHelper.getSpans(traceSegment).get(0));
+        assertTraceSegmentRef(traceSegment.getRef());
+    }
+
+    private void assertProviderSpan(AbstractTracingSpan span) {
+        assertCommonsAttribute(span);
+        assertTrue(span.isEntry());
+    }
+
+    private void assertCommonsAttribute(AbstractTracingSpan span) {
+        List<TagValuePair> tags = SpanHelper.getTags(span);
+        assertThat(tags.size(), is(0));
+        assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.RPC_FRAMEWORK));
+        assertThat(SpanHelper.getComponentId(span), is(91));
+    }
+
+    private void assertTraceSegmentRef(TraceSegmentRef actual) {
+        assertThat(SegmentRefHelper.getSpanId(actual), is(3));
+        assertThat(SegmentRefHelper.getParentServiceInstance(actual), is("instance"));
+        assertThat(SegmentRefHelper.getTraceSegmentId(actual), is("3.4.5"));
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 4188314..ac27c24 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -95,6 +95,7 @@
         <module>mariadb-2.x-plugin</module>
         <module>influxdb-2.x-plugin</module>
         <module>baidu-brpc-plugin</module>
+        <module>baidu-brpc-3.x-plugin</module>
         <module>hbase-1.x-2.x-plugin</module>
         <module>graphql-plugin</module>
         <module>xxl-job-2.x-plugin</module>
diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md
index c2f6c81..cf38780 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -7,6 +7,7 @@
 - async-http-client-2.x
 - avro-1.x
 - brpc-java
+- brpc-java-3.x
 - canal-1.x
 - cassandra-java-driver-3.x
 - dbcp-2.x
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 1660e77..2814963 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -60,7 +60,7 @@
   * [Armeria](https://github.com/line/armeria) 0.63.0 -> 0.98.0
   * [Apache Avro](http://avro.apache.org) 1.7.0 - 1.8.x
   * [Finagle](https://github.com/twitter/finagle) 6.44.0 -> 20.1.0  (6.25.0 -> 6.44.0 not tested)
-  * [Brpc-Java](https://github.com/baidu/brpc-java) 2.3.7 -> 2.5.3
+  * [Brpc-Java](https://github.com/baidu/brpc-java) 2.3.7 -> 3.0.5
   * [Thrift](https://github.com/apache/thrift/tree/master/lib/java) 0.10.0 -> 0.12.0
   * [Apache CXF](https://github.com/apache/cxf) 3.x
   * [JSONRPC4J](https://github.com/briandilley/jsonrpc4j) 1.2.0 -> 1.6
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/bin/startup.sh b/test/plugin/scenarios/baidu-brpc-3.x-scenario/bin/startup.sh
new file mode 100644
index 0000000..06a9dbf
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/bin/startup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts} ${home}/../libs/baidu-brpc-3.x-scenario.jar &
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/baidu-brpc-3.x-scenario/config/expectedData.yaml
new file mode 100644
index 0000000..13680a5
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/config/expectedData.yaml
@@ -0,0 +1,66 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+segmentItems:
+- serviceName: baidu-brpc-3.x-scenario
+  segmentSize: gt 2
+  segments:
+  - segmentId: not null
+    spans:
+    - operationName: example.EchoService.Echo
+      parentSpanId: -1
+      spanId: 0
+      spanLayer: RPCFramework
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 91
+      isError: false
+      spanType: Entry
+      peer: ''
+      refs:
+      - {parentEndpoint: GET:/baidu-brpc-3.x-scenario/case/brpc, networkAddress: '127.0.0.1:1118',
+        refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not
+          null, parentService: baidu-brpc-3.x-scenario, traceId: not null}
+      skipAnalysis: 'false'
+  - segmentId: not null
+    spans:
+    - operationName: example.EchoService.Echo
+      parentSpanId: 0
+      spanId: 1
+      spanLayer: RPCFramework
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 91
+      isError: false
+      spanType: Exit
+      peer: 127.0.0.1:1118
+      skipAnalysis: 'false'
+      tags:
+        - {key: url, value: '127.0.0.1:1118/example.EchoService.Echo'}
+    - operationName: GET:/baidu-brpc-3.x-scenario/case/brpc
+      parentSpanId: -1
+      spanId: 0
+      spanLayer: Http
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 1
+      isError: false
+      spanType: Entry
+      peer: ''
+      tags:
+      - {key: url, value: 'http://localhost:8080/baidu-brpc-3.x-scenario/case/brpc'}
+      - {key: http.method, value: GET}
+      - {key: http.status_code, value: '200'}
+      skipAnalysis: 'false'
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/configuration.yml b/test/plugin/scenarios/baidu-brpc-3.x-scenario/configuration.yml
new file mode 100644
index 0000000..920b5ee
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+type: jvm
+entryService: http://localhost:8080/baidu-brpc-3.x-scenario/case/brpc
+healthCheck: http://localhost:8080/baidu-brpc-3.x-scenario/case/healthCheck
+startScript: ./bin/startup.sh
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/pom.xml b/test/plugin/scenarios/baidu-brpc-3.x-scenario/pom.xml
new file mode 100644
index 0000000..e077507
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.skywalking</groupId>
+    <artifactId>baidu-brpc-3.x-scenario</artifactId>
+    <packaging>jar</packaging>
+    <version>5.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <compiler.version>1.8</compiler.version>
+
+        <test.framework.version>3.0.5</test.framework.version>
+
+        <spring.boot.version>2.1.6.RELEASE</spring.boot.version>
+        <test.framework>baidu-brpc-3.x</test.framework>
+    </properties>
+
+    <name>skywalking-baidu-brpc-3.x-scenario</name>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring.boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.baidu</groupId>
+            <artifactId>brpc-java</artifactId>
+            <version>${test.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>baidu-brpc-3.x-scenario</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${compiler.version}</source>
+                    <target>${compiler.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>src/main/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>./target/</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..1c53133
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<assembly
+    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>./bin</directory>
+            <fileMode>0775</fileMode>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            <source>${project.build.directory}/baidu-brpc-3.x-scenario.jar</source>
+            <outputDirectory>./libs</outputDirectory>
+            <fileMode>0775</fileMode>
+        </file>
+    </files>
+</assembly>
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/BaiduBrpcApplication.java b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/BaiduBrpcApplication.java
new file mode 100644
index 0000000..c834e9a
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/BaiduBrpcApplication.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.skywalking.apm.testcase.baidu.brpc;
+
+import org.apache.skywalking.apm.testcase.baidu.brpc.service.EchoServiceImpl;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import com.baidu.brpc.server.RpcServer;
+import com.baidu.brpc.server.RpcServerOptions;
+
+@SpringBootApplication
+public class BaiduBrpcApplication implements InitializingBean {
+
+    public static void main(String[] args) {
+        SpringApplication.run(BaiduBrpcApplication.class, args);
+    }
+
+    @Override
+    public void afterPropertiesSet() {
+        int port = 1118;
+        RpcServerOptions options = new RpcServerOptions();
+        options.setReceiveBufferSize(64 * 1024 * 1024);
+        options.setSendBufferSize(64 * 1024 * 1024);
+        options.setKeepAliveTime(20);
+        final RpcServer rpcServer = new RpcServer(port, options);
+        rpcServer.registerService(new EchoServiceImpl());
+        rpcServer.start();
+    }
+}
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/controller/CaseController.java b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/controller/CaseController.java
new file mode 100644
index 0000000..47571a9
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/controller/CaseController.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.baidu.brpc.controller;
+
+import org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo;
+import org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.EchoService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baidu.brpc.client.BrpcProxy;
+import com.baidu.brpc.client.RpcClient;
+import com.baidu.brpc.client.RpcClientOptions;
+import com.baidu.brpc.loadbalance.LoadBalanceStrategy;
+import com.baidu.brpc.protocol.Options;
+
+@RestController
+@RequestMapping("/case")
+public class CaseController {
+
+    private static final String SUCCESS = "Success";
+
+    @RequestMapping("/healthCheck")
+    @ResponseBody
+    public String healthCheck() {
+        return SUCCESS;
+    }
+
+    @RequestMapping("/brpc")
+    @ResponseBody
+    public String brpc() {
+        RpcClientOptions clientOption = new RpcClientOptions();
+        clientOption.setProtocolType(Options.ProtocolType.PROTOCOL_BAIDU_STD_VALUE);
+        clientOption.setWriteTimeoutMillis(1000);
+        clientOption.setReadTimeoutMillis(5000);
+        clientOption.setMaxTotalConnections(1000);
+        clientOption.setMinIdleConnections(10);
+        clientOption.setLoadBalanceType(LoadBalanceStrategy.LOAD_BALANCE_FAIR);
+        clientOption.setCompressType(Options.CompressType.COMPRESS_TYPE_NONE);
+
+        String serviceUrl = "list://127.0.0.1:1118";
+        Echo.EchoRequest request = Echo.EchoRequest.newBuilder()
+                .setMessage("helloooooooooooo")
+                .build();
+
+        RpcClient rpcClient = new RpcClient(serviceUrl, clientOption);
+        EchoService echoService = BrpcProxy.getProxy(rpcClient, EchoService.class);
+        echoService.echo(request);
+        rpcClient.stop();
+        return SUCCESS;
+    }
+}
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/Echo.java b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/Echo.java
new file mode 100644
index 0000000..386b8dc
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/Echo.java
@@ -0,0 +1,1166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: echo.proto
+
+package org.apache.skywalking.apm.testcase.baidu.brpc.interfaces;
+
+public final class Echo {
+    private Echo() {
+    }
+
+    public static void registerAllExtensions(
+            com.google.protobuf.ExtensionRegistry registry) {
+    }
+
+    public interface EchoRequestOrBuilder
+            extends com.google.protobuf.MessageOrBuilder {
+
+        // required string message = 1;
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        boolean hasMessage();
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        String getMessage();
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        com.google.protobuf.ByteString
+        getMessageBytes();
+    }
+
+    /**
+     * Protobuf type {@code example_for_cpp.EchoRequest}
+     */
+    public static final class EchoRequest extends
+            com.google.protobuf.GeneratedMessage
+            implements EchoRequestOrBuilder {
+        // Use EchoRequest.newBuilder() to construct.
+        private EchoRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+            super(builder);
+            this.unknownFields = builder.getUnknownFields();
+        }
+
+        private EchoRequest(boolean noInit) {
+            this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+        }
+
+        private static final EchoRequest defaultInstance;
+
+        public static EchoRequest getDefaultInstance() {
+            return defaultInstance;
+        }
+
+        public EchoRequest getDefaultInstanceForType() {
+            return defaultInstance;
+        }
+
+        private final com.google.protobuf.UnknownFieldSet unknownFields;
+
+        @Override
+        public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+            return this.unknownFields;
+        }
+
+        private EchoRequest(
+                com.google.protobuf.CodedInputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            initFields();
+            int mutable_bitField0_ = 0;
+            com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+                    com.google.protobuf.UnknownFieldSet.newBuilder();
+            try {
+                boolean done = false;
+                while (!done) {
+                    int tag = input.readTag();
+                    switch (tag) {
+                        case 0:
+                            done = true;
+                            break;
+                        default: {
+                            if (!parseUnknownField(input, unknownFields,
+                                    extensionRegistry, tag)) {
+                                done = true;
+                            }
+                            break;
+                        }
+                        case 10: {
+                            bitField0_ |= 0x00000001;
+                            message_ = input.readBytes();
+                            break;
+                        }
+                    }
+                }
+            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+                throw e.setUnfinishedMessage(this);
+            } catch (java.io.IOException e) {
+                throw new com.google.protobuf.InvalidProtocolBufferException(
+                        e.getMessage()).setUnfinishedMessage(this);
+            } finally {
+                this.unknownFields = unknownFields.build();
+                makeExtensionsImmutable();
+            }
+        }
+
+        public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+            return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoRequest_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+            return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoRequest_fieldAccessorTable
+                    .ensureFieldAccessorsInitialized(
+                            org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.class,
+                            org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.Builder.class);
+        }
+
+        public static com.google.protobuf.Parser<EchoRequest> PARSER =
+                new com.google.protobuf.AbstractParser<EchoRequest>() {
+                    public EchoRequest parsePartialFrom(
+                            com.google.protobuf.CodedInputStream input,
+                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                            throws com.google.protobuf.InvalidProtocolBufferException {
+                        return new EchoRequest(input, extensionRegistry);
+                    }
+                };
+
+        @Override
+        public com.google.protobuf.Parser<EchoRequest> getParserForType() {
+            return PARSER;
+        }
+
+        private int bitField0_;
+        // required string message = 1;
+        public static final int MESSAGE_FIELD_NUMBER = 1;
+        private Object message_;
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public boolean hasMessage() {
+            return ((bitField0_ & 0x00000001) == 0x00000001);
+        }
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public String getMessage() {
+            Object ref = message_;
+            if (ref instanceof String) {
+                return (String) ref;
+            } else {
+                com.google.protobuf.ByteString bs =
+                        (com.google.protobuf.ByteString) ref;
+                String s = bs.toStringUtf8();
+                if (bs.isValidUtf8()) {
+                    message_ = s;
+                }
+                return s;
+            }
+        }
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public com.google.protobuf.ByteString
+        getMessageBytes() {
+            Object ref = message_;
+            if (ref instanceof String) {
+                com.google.protobuf.ByteString b =
+                        com.google.protobuf.ByteString.copyFromUtf8(
+                                (String) ref);
+                message_ = b;
+                return b;
+            } else {
+                return (com.google.protobuf.ByteString) ref;
+            }
+        }
+
+        private void initFields() {
+            message_ = "";
+        }
+
+        private byte memoizedIsInitialized = -1;
+
+        public final boolean isInitialized() {
+            byte isInitialized = memoizedIsInitialized;
+          if (isInitialized != -1) {
+            return isInitialized == 1;
+          }
+
+            if (!hasMessage()) {
+                memoizedIsInitialized = 0;
+                return false;
+            }
+            memoizedIsInitialized = 1;
+            return true;
+        }
+
+        public void writeTo(com.google.protobuf.CodedOutputStream output)
+                throws java.io.IOException {
+            getSerializedSize();
+            if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                output.writeBytes(1, getMessageBytes());
+            }
+            getUnknownFields().writeTo(output);
+        }
+
+        private int memoizedSerializedSize = -1;
+
+        public int getSerializedSize() {
+            int size = memoizedSerializedSize;
+          if (size != -1) {
+            return size;
+          }
+
+            size = 0;
+            if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                size += com.google.protobuf.CodedOutputStream
+                        .computeBytesSize(1, getMessageBytes());
+            }
+            size += getUnknownFields().getSerializedSize();
+            memoizedSerializedSize = size;
+            return size;
+        }
+
+        private static final long serialVersionUID = 0L;
+
+        @Override
+        protected Object writeReplace()
+                throws java.io.ObjectStreamException {
+            return super.writeReplace();
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                com.google.protobuf.ByteString data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                com.google.protobuf.ByteString data,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(byte[] data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                byte[] data,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                java.io.InputStream input)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                java.io.InputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseDelimitedFrom(
+                java.io.InputStream input)
+                throws java.io.IOException {
+            return PARSER.parseDelimitedFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseDelimitedFrom(
+                java.io.InputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseDelimitedFrom(input, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                com.google.protobuf.CodedInputStream input)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parseFrom(
+                com.google.protobuf.CodedInputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input, extensionRegistry);
+        }
+
+        public static Builder newBuilder() {
+            return Builder.create();
+        }
+
+        public Builder newBuilderForType() {
+            return newBuilder();
+        }
+
+        public static Builder newBuilder(
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest prototype) {
+            return newBuilder().mergeFrom(prototype);
+        }
+
+        public Builder toBuilder() {
+            return newBuilder(this);
+        }
+
+        @Override
+        protected Builder newBuilderForType(
+                com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+            Builder builder = new Builder(parent);
+            return builder;
+        }
+
+        /**
+         * Protobuf type {@code example_for_cpp.EchoRequest}
+         */
+        public static final class Builder extends
+                com.google.protobuf.GeneratedMessage.Builder<Builder>
+                implements org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequestOrBuilder {
+            public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoRequest_descriptor;
+            }
+
+            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoRequest_fieldAccessorTable
+                        .ensureFieldAccessorsInitialized(
+                                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.class,
+                                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.Builder.class);
+            }
+
+            // Construct using org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.newBuilder()
+            private Builder() {
+                maybeForceBuilderInitialization();
+            }
+
+            private Builder(
+                    com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+                super(parent);
+                maybeForceBuilderInitialization();
+            }
+
+            private void maybeForceBuilderInitialization() {
+                if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+                }
+            }
+
+            private static Builder create() {
+                return new Builder();
+            }
+
+            public Builder clear() {
+                super.clear();
+                message_ = "";
+                bitField0_ = (bitField0_ & ~0x00000001);
+                return this;
+            }
+
+            public Builder clone() {
+                return create().mergeFrom(buildPartial());
+            }
+
+            public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoRequest_descriptor;
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest getDefaultInstanceForType() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.getDefaultInstance();
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest build() {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest result = buildPartial();
+                if (!result.isInitialized()) {
+                    throw newUninitializedMessageException(result);
+                }
+                return result;
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest buildPartial() {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest result =
+                        new org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest(this);
+                int from_bitField0_ = bitField0_;
+                int to_bitField0_ = 0;
+                if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+                    to_bitField0_ |= 0x00000001;
+                }
+                result.message_ = message_;
+                result.bitField0_ = to_bitField0_;
+                onBuilt();
+                return result;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.Message other) {
+                if (other instanceof org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest) {
+                    return mergeFrom((org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest) other);
+                } else {
+                    super.mergeFrom(other);
+                    return this;
+                }
+            }
+
+            public Builder mergeFrom(org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest other) {
+              if (other
+                      == org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest.getDefaultInstance()) {
+                return this;
+              }
+                if (other.hasMessage()) {
+                    bitField0_ |= 0x00000001;
+                    message_ = other.message_;
+                    onChanged();
+                }
+                this.mergeUnknownFields(other.getUnknownFields());
+                return this;
+            }
+
+            public final boolean isInitialized() {
+                if (!hasMessage()) {
+
+                    return false;
+                }
+                return true;
+            }
+
+            public Builder mergeFrom(
+                    com.google.protobuf.CodedInputStream input,
+                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                    throws java.io.IOException {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest parsedMessage = null;
+                try {
+                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+                    parsedMessage =
+                            (org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoRequest) e.getUnfinishedMessage();
+                    throw e;
+                } finally {
+                    if (parsedMessage != null) {
+                        mergeFrom(parsedMessage);
+                    }
+                }
+                return this;
+            }
+
+            private int bitField0_;
+
+            // required string message = 1;
+            private Object message_ = "";
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public boolean hasMessage() {
+                return ((bitField0_ & 0x00000001) == 0x00000001);
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public String getMessage() {
+                Object ref = message_;
+                if (!(ref instanceof String)) {
+                    String s = ((com.google.protobuf.ByteString) ref)
+                            .toStringUtf8();
+                    message_ = s;
+                    return s;
+                } else {
+                    return (String) ref;
+                }
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public com.google.protobuf.ByteString
+            getMessageBytes() {
+                Object ref = message_;
+                if (ref instanceof String) {
+                    com.google.protobuf.ByteString b =
+                            com.google.protobuf.ByteString.copyFromUtf8(
+                                    (String) ref);
+                    message_ = b;
+                    return b;
+                } else {
+                    return (com.google.protobuf.ByteString) ref;
+                }
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder setMessage(
+                    String value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                bitField0_ |= 0x00000001;
+                message_ = value;
+                onChanged();
+                return this;
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder clearMessage() {
+                bitField0_ = (bitField0_ & ~0x00000001);
+                message_ = getDefaultInstance().getMessage();
+                onChanged();
+                return this;
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder setMessageBytes(
+                    com.google.protobuf.ByteString value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                bitField0_ |= 0x00000001;
+                message_ = value;
+                onChanged();
+                return this;
+            }
+
+            // @@protoc_insertion_point(builder_scope:example_for_cpp.EchoRequest)
+        }
+
+        static {
+            defaultInstance = new EchoRequest(true);
+            defaultInstance.initFields();
+        }
+
+        // @@protoc_insertion_point(class_scope:example_for_cpp.EchoRequest)
+    }
+
+    public interface EchoResponseOrBuilder
+            extends com.google.protobuf.MessageOrBuilder {
+
+        // required string message = 1;
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        boolean hasMessage();
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        String getMessage();
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        com.google.protobuf.ByteString
+        getMessageBytes();
+    }
+
+    /**
+     * Protobuf type {@code example_for_cpp.EchoResponse}
+     */
+    public static final class EchoResponse extends
+            com.google.protobuf.GeneratedMessage
+            implements EchoResponseOrBuilder {
+        // Use EchoResponse.newBuilder() to construct.
+        private EchoResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+            super(builder);
+            this.unknownFields = builder.getUnknownFields();
+        }
+
+        private EchoResponse(boolean noInit) {
+            this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+        }
+
+        private static final EchoResponse defaultInstance;
+
+        public static EchoResponse getDefaultInstance() {
+            return defaultInstance;
+        }
+
+        public EchoResponse getDefaultInstanceForType() {
+            return defaultInstance;
+        }
+
+        private final com.google.protobuf.UnknownFieldSet unknownFields;
+
+        @Override
+        public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+            return this.unknownFields;
+        }
+
+        private EchoResponse(
+                com.google.protobuf.CodedInputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            initFields();
+            int mutable_bitField0_ = 0;
+            com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+                    com.google.protobuf.UnknownFieldSet.newBuilder();
+            try {
+                boolean done = false;
+                while (!done) {
+                    int tag = input.readTag();
+                    switch (tag) {
+                        case 0:
+                            done = true;
+                            break;
+                        default: {
+                            if (!parseUnknownField(input, unknownFields,
+                                    extensionRegistry, tag)) {
+                                done = true;
+                            }
+                            break;
+                        }
+                        case 10: {
+                            bitField0_ |= 0x00000001;
+                            message_ = input.readBytes();
+                            break;
+                        }
+                    }
+                }
+            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+                throw e.setUnfinishedMessage(this);
+            } catch (java.io.IOException e) {
+                throw new com.google.protobuf.InvalidProtocolBufferException(
+                        e.getMessage()).setUnfinishedMessage(this);
+            } finally {
+                this.unknownFields = unknownFields.build();
+                makeExtensionsImmutable();
+            }
+        }
+
+        public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+            return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoResponse_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+            return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoResponse_fieldAccessorTable
+                    .ensureFieldAccessorsInitialized(
+                            org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.class,
+                            org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.Builder.class);
+        }
+
+        public static com.google.protobuf.Parser<EchoResponse> PARSER =
+                new com.google.protobuf.AbstractParser<EchoResponse>() {
+                    public EchoResponse parsePartialFrom(
+                            com.google.protobuf.CodedInputStream input,
+                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                            throws com.google.protobuf.InvalidProtocolBufferException {
+                        return new EchoResponse(input, extensionRegistry);
+                    }
+                };
+
+        @Override
+        public com.google.protobuf.Parser<EchoResponse> getParserForType() {
+            return PARSER;
+        }
+
+        private int bitField0_;
+        // required string message = 1;
+        public static final int MESSAGE_FIELD_NUMBER = 1;
+        private Object message_;
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public boolean hasMessage() {
+            return ((bitField0_ & 0x00000001) == 0x00000001);
+        }
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public String getMessage() {
+            Object ref = message_;
+            if (ref instanceof String) {
+                return (String) ref;
+            } else {
+                com.google.protobuf.ByteString bs =
+                        (com.google.protobuf.ByteString) ref;
+                String s = bs.toStringUtf8();
+                if (bs.isValidUtf8()) {
+                    message_ = s;
+                }
+                return s;
+            }
+        }
+
+        /**
+         * <code>required string message = 1;</code>
+         */
+        public com.google.protobuf.ByteString
+        getMessageBytes() {
+            Object ref = message_;
+            if (ref instanceof String) {
+                com.google.protobuf.ByteString b =
+                        com.google.protobuf.ByteString.copyFromUtf8(
+                                (String) ref);
+                message_ = b;
+                return b;
+            } else {
+                return (com.google.protobuf.ByteString) ref;
+            }
+        }
+
+        private void initFields() {
+            message_ = "";
+        }
+
+        private byte memoizedIsInitialized = -1;
+
+        public final boolean isInitialized() {
+            byte isInitialized = memoizedIsInitialized;
+          if (isInitialized != -1) {
+            return isInitialized == 1;
+          }
+
+            if (!hasMessage()) {
+                memoizedIsInitialized = 0;
+                return false;
+            }
+            memoizedIsInitialized = 1;
+            return true;
+        }
+
+        public void writeTo(com.google.protobuf.CodedOutputStream output)
+                throws java.io.IOException {
+            getSerializedSize();
+            if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                output.writeBytes(1, getMessageBytes());
+            }
+            getUnknownFields().writeTo(output);
+        }
+
+        private int memoizedSerializedSize = -1;
+
+        public int getSerializedSize() {
+            int size = memoizedSerializedSize;
+          if (size != -1) {
+            return size;
+          }
+
+            size = 0;
+            if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                size += com.google.protobuf.CodedOutputStream
+                        .computeBytesSize(1, getMessageBytes());
+            }
+            size += getUnknownFields().getSerializedSize();
+            memoizedSerializedSize = size;
+            return size;
+        }
+
+        private static final long serialVersionUID = 0L;
+
+        @Override
+        protected Object writeReplace()
+                throws java.io.ObjectStreamException {
+            return super.writeReplace();
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                com.google.protobuf.ByteString data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                com.google.protobuf.ByteString data,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(byte[] data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                byte[] data,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+            return PARSER.parseFrom(data, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                java.io.InputStream input)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                java.io.InputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseDelimitedFrom(
+                java.io.InputStream input)
+                throws java.io.IOException {
+            return PARSER.parseDelimitedFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseDelimitedFrom(
+                java.io.InputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseDelimitedFrom(input, extensionRegistry);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                com.google.protobuf.CodedInputStream input)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input);
+        }
+
+        public static org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parseFrom(
+                com.google.protobuf.CodedInputStream input,
+                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+            return PARSER.parseFrom(input, extensionRegistry);
+        }
+
+        public static Builder newBuilder() {
+            return Builder.create();
+        }
+
+        public Builder newBuilderForType() {
+            return newBuilder();
+        }
+
+        public static Builder newBuilder(
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse prototype) {
+            return newBuilder().mergeFrom(prototype);
+        }
+
+        public Builder toBuilder() {
+            return newBuilder(this);
+        }
+
+        @Override
+        protected Builder newBuilderForType(
+                com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+            Builder builder = new Builder(parent);
+            return builder;
+        }
+
+        /**
+         * Protobuf type {@code example_for_cpp.EchoResponse}
+         */
+        public static final class Builder extends
+                com.google.protobuf.GeneratedMessage.Builder<Builder>
+                implements org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponseOrBuilder {
+            public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoResponse_descriptor;
+            }
+
+            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoResponse_fieldAccessorTable
+                        .ensureFieldAccessorsInitialized(
+                                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.class,
+                                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.Builder.class);
+            }
+
+            // Construct using org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.newBuilder()
+            private Builder() {
+                maybeForceBuilderInitialization();
+            }
+
+            private Builder(
+                    com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+                super(parent);
+                maybeForceBuilderInitialization();
+            }
+
+            private void maybeForceBuilderInitialization() {
+                if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+                }
+            }
+
+            private static Builder create() {
+                return new Builder();
+            }
+
+            public Builder clear() {
+                super.clear();
+                message_ = "";
+                bitField0_ = (bitField0_ & ~0x00000001);
+                return this;
+            }
+
+            public Builder clone() {
+                return create().mergeFrom(buildPartial());
+            }
+
+            public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.internal_static_example_for_cpp_EchoResponse_descriptor;
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse getDefaultInstanceForType() {
+                return org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.getDefaultInstance();
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse build() {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse result = buildPartial();
+                if (!result.isInitialized()) {
+                    throw newUninitializedMessageException(result);
+                }
+                return result;
+            }
+
+            public org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse buildPartial() {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse result =
+                        new org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse(this);
+                int from_bitField0_ = bitField0_;
+                int to_bitField0_ = 0;
+                if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+                    to_bitField0_ |= 0x00000001;
+                }
+                result.message_ = message_;
+                result.bitField0_ = to_bitField0_;
+                onBuilt();
+                return result;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.Message other) {
+                if (other instanceof org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse) {
+                    return mergeFrom(
+                            (org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse) other);
+                } else {
+                    super.mergeFrom(other);
+                    return this;
+                }
+            }
+
+            public Builder mergeFrom(org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse other) {
+              if (other
+                      == org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse.getDefaultInstance()) {
+                return this;
+              }
+                if (other.hasMessage()) {
+                    bitField0_ |= 0x00000001;
+                    message_ = other.message_;
+                    onChanged();
+                }
+                this.mergeUnknownFields(other.getUnknownFields());
+                return this;
+            }
+
+            public final boolean isInitialized() {
+                if (!hasMessage()) {
+
+                    return false;
+                }
+                return true;
+            }
+
+            public Builder mergeFrom(
+                    com.google.protobuf.CodedInputStream input,
+                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                    throws java.io.IOException {
+                org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse parsedMessage = null;
+                try {
+                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+                    parsedMessage =
+                            (org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo.EchoResponse) e.getUnfinishedMessage();
+                    throw e;
+                } finally {
+                    if (parsedMessage != null) {
+                        mergeFrom(parsedMessage);
+                    }
+                }
+                return this;
+            }
+
+            private int bitField0_;
+
+            // required string message = 1;
+            private Object message_ = "";
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public boolean hasMessage() {
+                return ((bitField0_ & 0x00000001) == 0x00000001);
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public String getMessage() {
+                Object ref = message_;
+                if (!(ref instanceof String)) {
+                    String s = ((com.google.protobuf.ByteString) ref)
+                            .toStringUtf8();
+                    message_ = s;
+                    return s;
+                } else {
+                    return (String) ref;
+                }
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public com.google.protobuf.ByteString
+            getMessageBytes() {
+                Object ref = message_;
+                if (ref instanceof String) {
+                    com.google.protobuf.ByteString b =
+                            com.google.protobuf.ByteString.copyFromUtf8(
+                                    (String) ref);
+                    message_ = b;
+                    return b;
+                } else {
+                    return (com.google.protobuf.ByteString) ref;
+                }
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder setMessage(
+                    String value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                bitField0_ |= 0x00000001;
+                message_ = value;
+                onChanged();
+                return this;
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder clearMessage() {
+                bitField0_ = (bitField0_ & ~0x00000001);
+                message_ = getDefaultInstance().getMessage();
+                onChanged();
+                return this;
+            }
+
+            /**
+             * <code>required string message = 1;</code>
+             */
+            public Builder setMessageBytes(
+                    com.google.protobuf.ByteString value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                bitField0_ |= 0x00000001;
+                message_ = value;
+                onChanged();
+                return this;
+            }
+
+            // @@protoc_insertion_point(builder_scope:example_for_cpp.EchoResponse)
+        }
+
+        static {
+            defaultInstance = new EchoResponse(true);
+            defaultInstance.initFields();
+        }
+
+        // @@protoc_insertion_point(class_scope:example_for_cpp.EchoResponse)
+    }
+
+    private static com.google.protobuf.Descriptors.Descriptor
+            internal_static_example_for_cpp_EchoRequest_descriptor;
+    private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internal_static_example_for_cpp_EchoRequest_fieldAccessorTable;
+    private static com.google.protobuf.Descriptors.Descriptor
+            internal_static_example_for_cpp_EchoResponse_descriptor;
+    private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internal_static_example_for_cpp_EchoResponse_fieldAccessorTable;
+
+    public static com.google.protobuf.Descriptors.FileDescriptor
+    getDescriptor() {
+        return descriptor;
+    }
+
+    private static com.google.protobuf.Descriptors.FileDescriptor
+            descriptor;
+
+    static {
+        String[] descriptorData = {
+                "\n\necho.proto\022\017example_for_cpp\"\036\n\013EchoReq" +
+                        "uest\022\017\n\007message\030\001 \002(\t\"\037\n\014EchoResponse\022\017\n" +
+                        "\007message\030\001 \002(\t2R\n\013EchoService\022C\n\004Echo\022\034." +
+                        "example_for_cpp.EchoRequest\032\035.example_fo" +
+                        "r_cpp.EchoResponseB*\n\037com.baidu.brpc.exa" +
+                        "mple.standardB\004Echo\200\001\001"
+        };
+        com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+                new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+                    public com.google.protobuf.ExtensionRegistry assignDescriptors(
+                            com.google.protobuf.Descriptors.FileDescriptor root) {
+                        descriptor = root;
+                        internal_static_example_for_cpp_EchoRequest_descriptor =
+                                getDescriptor().getMessageTypes().get(0);
+                        internal_static_example_for_cpp_EchoRequest_fieldAccessorTable = new
+                                com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+                                internal_static_example_for_cpp_EchoRequest_descriptor,
+                                new String[] {"Message",});
+                        internal_static_example_for_cpp_EchoResponse_descriptor =
+                                getDescriptor().getMessageTypes().get(1);
+                        internal_static_example_for_cpp_EchoResponse_fieldAccessorTable = new
+                                com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+                                internal_static_example_for_cpp_EchoResponse_descriptor,
+                                new String[] {"Message",});
+                        return null;
+                    }
+                };
+        com.google.protobuf.Descriptors.FileDescriptor
+                .internalBuildGeneratedFileFrom(descriptorData,
+                        new com.google.protobuf.Descriptors.FileDescriptor[] {
+                        }, assigner);
+    }
+
+    // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/EchoService.java b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/EchoService.java
new file mode 100755
index 0000000..69e4b8e
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/interfaces/EchoService.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.baidu.brpc.interfaces;
+
+import com.baidu.brpc.protocol.BrpcMeta;
+
+/**
+ * Copy from brpc-java-example
+ */
+public interface EchoService {
+
+    @BrpcMeta(serviceName = "example.EchoService", methodName = "Echo")
+    Echo.EchoResponse echo(Echo.EchoRequest request);
+}
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/service/EchoServiceImpl.java b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/service/EchoServiceImpl.java
new file mode 100755
index 0000000..3f44720
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/baidu.brpc/service/EchoServiceImpl.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.baidu.brpc.service;
+
+import org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.Echo;
+import org.apache.skywalking.apm.testcase.baidu.brpc.interfaces.EchoService;
+
+/**
+ * Copy from brpc-java-example
+ */
+public class EchoServiceImpl implements EchoService {
+    @Override
+    public Echo.EchoResponse echo(Echo.EchoRequest request) {
+        String message = request.getMessage();
+        Echo.EchoResponse response = Echo.EchoResponse.newBuilder().setMessage(message).build();
+        return response;
+    }
+}
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/resources/application.yml b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/resources/application.yml
new file mode 100644
index 0000000..6b3f830
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/src/main/resources/application.yml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+server:
+  port: 8080
+  servlet:
+    context-path: /baidu-brpc-3.x-scenario
diff --git a/test/plugin/scenarios/baidu-brpc-3.x-scenario/support-version.list b/test/plugin/scenarios/baidu-brpc-3.x-scenario/support-version.list
new file mode 100644
index 0000000..8225fd6
--- /dev/null
+++ b/test/plugin/scenarios/baidu-brpc-3.x-scenario/support-version.list
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+3.0.5