diff --git a/4-governance/dubbo-samples-opensergo/README.md b/4-governance/dubbo-samples-opensergo/README.md
new file mode 100644
index 0000000000..867d61e543
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/README.md
@@ -0,0 +1,42 @@
+# governance dubbo using OpenSergo Tag router
+1. step1 run `BasicProvider.java`
+
+> it will start an zookeeper and register two service with dubbo port 20880
+2. step2 run `BasicProviderOtherPort.java`
+> it will register another two service with dubbo port 20881
+3. step3 Start OpenSergoControlPlane and apply traffic config
+[First start OpenSergo control plane](https://opensergo.io/docs/quick-start/opensergo-control-plane/) , Then we publish the label routing rules through the OpenSergo control plane. We publish a TrafficRouter rule.
+```YAML
+kubectl apply -f - << EOF
+apiVersion: traffic.opensergo.io/v1alpha1
+kind: TrafficRouter
+metadata:
+ name: governance-opensergo-traffic-provider
+ namespace: default
+ labels:
+ app: governance-opensergo-traffic-provider
+spec:
+ hosts:
+ - governance-opensergo-traffic-provider
+ http:
+ - match:
+ - headers:
+ tag:
+ exact: v2
+ route:
+ - destination:
+ host: governance-opensergo-traffic-provider
+ subset: v2
+ - route:
+ - destination:
+ host: governance-opensergo-traffic-provider
+ subset: v1
+EOF
+```
+This [TrafficRouter](https://github.com/opensergo/opensergo-specification/blob/main/specification/en/traffic-routing.md)
+specifies the simplest label routing rule. Dubbo requests with the v2 header are routed to v2, and the rest of the traffic is routed to v1.
+
+4. step4 run `BasicConsumer.java`
+> it will consume service by rule defined by yml file
+> * All consumer taged by `v2` come from provider in port 20881
+> * All consumer taged by `v1` come from provider in port 20880
\ No newline at end of file
diff --git a/4-governance/dubbo-samples-opensergo/case-configuration.yml b/4-governance/dubbo-samples-opensergo/case-configuration.yml
new file mode 100644
index 0000000000..00f10ec711
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/case-configuration.yml
@@ -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.
+
+services:
+ zookeeper:
+ image: zookeeper:latest
+
+ dubbo-samples-tagrouter1:
+ type: app
+ basedir: .
+ mainClass: org.apache.dubbo.samples.governance.BasicProvider
+ systemProps:
+ - zookeeper.address=zookeeper
+ - zookeeper.port=2181
+ - dubbo.port=20880
+ waitPortsBeforeRun:
+ - zookeeper:2181
+ checkPorts:
+ - 20880
+ checkLog: "dubbo service started"
+ depends_on:
+ - zookeeper
+
+ dubbo-samples-tagrouter2:
+ type: app
+ basedir: .
+ mainClass: org.apache.dubbo.samples.governance.BasicProvider
+ systemProps:
+ - zookeeper.address=zookeeper
+ - zookeeper.port=2181
+ - dubbo.port=20881
+ waitPortsBeforeRun:
+ - zookeeper:2181
+ checkPorts:
+ - 20881
+ checkLog: "dubbo service started"
+ depends_on:
+ - zookeeper
+
+ dubbo-samples-tagrouter-test:
+ type: test
+ basedir: .
+ tests:
+ - "**/*IT.class"
+ systemProps:
+ - zookeeper.address=zookeeper
+ - zookeeper.port=2181
+ waitPortsBeforeRun:
+ - zookeeper:2181
+ - dubbo-samples-tagrouter1:20880
+ - dubbo-samples-tagrouter2:20881
+ depends_on:
+ - zookeeper
+ - dubbo-samples-tagrouter1
+ - dubbo-samples-tagrouter2
diff --git a/4-governance/dubbo-samples-opensergo/case-versions.conf b/4-governance/dubbo-samples-opensergo/case-versions.conf
new file mode 100644
index 0000000000..20c45c863f
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/case-versions.conf
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+# Supported component versions of the test case
+
+# Spring app
+dubbo.version=2.7*, 3.*
+spring.version=4.*, 5.*
+java.version= [<= 11]
diff --git a/4-governance/dubbo-samples-opensergo/pom.xml b/4-governance/dubbo-samples-opensergo/pom.xml
new file mode 100644
index 0000000000..d0150cfa15
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/pom.xml
@@ -0,0 +1,161 @@
+
+
+
+
+ * Helper class to start an embedded instance of standalone (non clustered) ZooKeeper. + *
+ * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for + * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication} + * + * @author Patrick Peralta + * @author Mark Fisher + * @author David Turanski + */ +public class EmbeddedZooKeeper implements SmartLifecycle { + + /** + * Logger. + */ + private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.class); + + /** + * ZooKeeper client port. This will be determined dynamically upon startup. + */ + private final int clientPort; + + /** + * Whether to auto-start. Default is true. + */ + private boolean autoStartup = true; + + /** + * Lifecycle phase. Default is 0. + */ + private int phase = 0; + + /** + * Thread for running the ZooKeeper server. + */ + private volatile Thread zkServerThread; + + /** + * ZooKeeper server. + */ + private volatile ZooKeeperServerMain zkServer; + + /** + * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. + */ + private ErrorHandler errorHandler; + + private boolean daemon = true; + + /** + * Construct an EmbeddedZooKeeper with a random port. + */ + public EmbeddedZooKeeper() { + clientPort = SocketUtils.findAvailableTcpPort(); + } + + /** + * Construct an EmbeddedZooKeeper with the provided port. + * + * @param clientPort port for ZooKeeper server to bind to + */ + public EmbeddedZooKeeper(int clientPort, boolean daemon) { + this.clientPort = clientPort; + this.daemon = daemon; + } + + /** + * Returns the port that clients should use to connect to this embedded server. + * + * @return dynamically determined client port + */ + public int getClientPort() { + return this.clientPort; + } + + /** + * Specify whether to start automatically. Default is true. + * + * @param autoStartup whether to start automatically + */ + public void setAutoStartup(boolean autoStartup) { + this.autoStartup = autoStartup; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAutoStartup() { + return this.autoStartup; + } + + /** + * Specify the lifecycle phase for the embedded server. + * + * @param phase the lifecycle phase + */ + public void setPhase(int phase) { + this.phase = phase; + } + + /** + * {@inheritDoc} + */ + @Override + public int getPhase() { + return this.phase; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isRunning() { + return (zkServerThread != null); + } + + /** + * Start the ZooKeeper server in a background thread. + *
+ * Register an error handler via {@link #setErrorHandler} in order to handle
+ * any exceptions thrown during startup or execution.
+ */
+ @Override
+ public synchronized void start() {
+ if (zkServerThread == null) {
+ zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
+ zkServerThread.setDaemon(daemon);
+ zkServerThread.start();
+ }
+ }
+
+ /**
+ * Shutdown the ZooKeeper server.
+ */
+ @Override
+ public synchronized void stop() {
+ if (zkServerThread != null) {
+ // The shutdown method is protected...thus this hack to invoke it.
+ // This will log an exception on shutdown; see
+ // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
+ try {
+ Method shutdown = ZooKeeperServerMain.class.getDeclaredMethod("shutdown");
+ shutdown.setAccessible(true);
+ shutdown.invoke(zkServer);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // It is expected that the thread will exit after
+ // the server is shutdown; this will block until
+ // the shutdown is complete.
+ try {
+ zkServerThread.join(5000);
+ zkServerThread = null;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
+ // abandoning zk thread
+ zkServerThread = null;
+ }
+ }
+ }
+
+ /**
+ * Stop the server if running and invoke the callback when complete.
+ */
+ @Override
+ public void stop(Runnable callback) {
+ stop();
+ callback.run();
+ }
+
+ /**
+ * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
+ * is provided, only error-level logging will occur.
+ *
+ * @param errorHandler the {@link ErrorHandler} to be invoked
+ */
+ public void setErrorHandler(ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ /**
+ * Runnable implementation that starts the ZooKeeper server.
+ */
+ private class ServerRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ Properties properties = new Properties();
+ File file = new File(System.getProperty("java.io.tmpdir")
+ + File.separator + UUID.randomUUID());
+ file.deleteOnExit();
+ properties.setProperty("dataDir", file.getAbsolutePath());
+ properties.setProperty("clientPort", String.valueOf(clientPort));
+
+ QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
+ quorumPeerConfig.parseProperties(properties);
+
+ zkServer = new ZooKeeperServerMain();
+ ServerConfig configuration = new ServerConfig();
+ configuration.readFrom(quorumPeerConfig);
+
+ zkServer.runFromConfig(configuration);
+ } catch (Exception e) {
+ if (errorHandler != null) {
+ errorHandler.handleError(e);
+ } else {
+ logger.error("Exception running embedded ZooKeeper", e);
+ }
+ }
+ }
+ }
+
+}
diff --git a/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService.java b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService.java
new file mode 100644
index 0000000000..bde5f6eb6a
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.dubbo.samples.governance.api;
+
+public interface DemoService {
+
+ String sayHello(String name);
+
+}
diff --git a/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService2.java b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService2.java
new file mode 100644
index 0000000000..828d87c919
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/api/DemoService2.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.dubbo.samples.governance.api;
+
+public interface DemoService2 {
+
+ String sayHello(String name);
+
+}
diff --git a/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl.java b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl.java
new file mode 100644
index 0000000000..87ed7417b0
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.dubbo.samples.governance.impl;
+
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.samples.governance.api.DemoService;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DemoServiceImpl implements DemoService {
+
+ @Override
+ public String sayHello(String name) {
+ System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " +
+ name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
+ return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
+ }
+}
diff --git a/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl2.java b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl2.java
new file mode 100644
index 0000000000..31fa42bff1
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/java/org/apache/dubbo/samples/governance/impl/DemoServiceImpl2.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.dubbo.samples.governance.impl;
+
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.samples.governance.api.DemoService2;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DemoServiceImpl2 implements DemoService2 {
+
+ @Override
+ public String sayHello(String name) {
+ System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name +
+ ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
+ return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
+ }
+}
diff --git a/4-governance/dubbo-samples-opensergo/src/main/resources/log4j.properties b/4-governance/dubbo-samples-opensergo/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..f30fda0d71
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/resources/log4j.properties
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to the console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
\ No newline at end of file
diff --git a/4-governance/dubbo-samples-opensergo/src/main/resources/spring/dubbo-demo-consumer.xml b/4-governance/dubbo-samples-opensergo/src/main/resources/spring/dubbo-demo-consumer.xml
new file mode 100644
index 0000000000..dd6dc1c22b
--- /dev/null
+++ b/4-governance/dubbo-samples-opensergo/src/main/resources/spring/dubbo-demo-consumer.xml
@@ -0,0 +1,41 @@
+
+
+
+