All Products
Search
Document Center

Microservices Engine:Implement an end-to-end canary release based on RocketMQ

Last Updated:Mar 26, 2025

By leveraging traffic control in asynchronous scenarios such as message queue scenarios, Microservices Engine (MSE) Microservices Governance allows you to implement an end-to-end canary release without the need to modify business code. This topic describes how to implement an end-to-end canary release in MSE based on RocketMQ.

Prerequisites

Demo architecture

In this example, applications are deployed in the ACK console. You can also use kubectl to deploy applications and simulate a real call process. The following figure shows the architecture of this demo. Application calls involve Spring Cloud service calls and Dubbo service calls. Spring Cloud and Dubbo are the two most commonly used microservices frameworks in the market. Application C produces RocketMQ messages for Application A. When the messages are consumed by Application A, new calls are initiated. The application calls comply with the standard use of Spring Cloud, Dubbo, and RocketMQ.

调用关系图

Step 1: Enable MSE Microservices Governance for applications

  • Enable Microservices Governance for microservice applications in the Container Service for Kubernetes (ACK) cluster. You can select an appropriate method based on your business requirements. For more information, see Enable Microservices Governance for Java microservice applications in an ACK or ACS cluster.

    Enable Microservices Governance for applications in an ACK namespace

    1. Log on to the MSE console, and select a region in the top navigation bar.

    2. In the left-side navigation pane, choose Microservices Governance > Application Governance.

    3. On the Application list page, click ACK Application Access.

    4. In the ACK Application Access dialog box, configure the parameters and click OK.

      image

      Parameter

      Description

      Cluster type

      Select ACK Cluster, ACK Serverless Cluster, or ACS Cluster.

      Note

      If you do not grant the cluster permissions to call MSE, you need to click the link to perform authorization.

      Cluster Name/ID

      Select the name or ID of the cluster for which Microservices Governance is enabled. You can use keywords to search for cluster names or IDs.

      ack-onepilot

      View the status of the ack-onepilot component.

      • If the ack-onepilot component is not installed, click Click Install on the right of ack-onepilot. After the installation is complete, the status of the ack-onepilot component is displayed as Installed.

      • If you perform the operation as a RAM user and a message is displayed, indicating that you have no permissions to perform the operation, you can log on to the ACK console to access the desired cluster, and choose Operations > Add-ons. Then, find ack-onepilot and click Install.

      Note
      • In this step, the ack-onepilot component is involved. You can log on to the ACK console to access the destination cluster, and choose Operations > Add-ons to view the component details.

      • After the ack-onepilot component is installed, the agent is automatically injected. In this case, the startup time of the application may be increased by up to 10s.

      • If you want to enable Microservices Governance for applications in an ACK or ACS cluster namespace and the cluster is not deployed in a supported region, you must make sure that the cluster can access the Internet and can connect to acm.aliyun.com:8080. The supported regions include China (Qingdao), China (Hangzhou), China (Beijing), China (Shanghai), China East 2 Finance, China (Shenzhen), China (Hong Kong), Singapore, Germany (Frankfurt), Australia (Sydney), US (Silicon Valley), and US (Virginia).

      Access Type

      Select Namespace Access.

      ACK Cluster Namespace

      Select an ACK cluster namespace.

      Microservices Governance Namespace

      Select the Microservices Governance namespace. Then, redeploy existing applications or create applications in the associated microservice namespace. This way, Microservices Governance is enabled for the applications.

    Enable Microservices Governance for an application

    1. Log on to the MSE console, and select a region in the top navigation bar.

    2. In the left-side navigation pane, choose Microservices Governance > Application Governance.

    3. On the Application list page, click ACK Application Access.

    4. In the ACK Application Access dialog box, configure the parameters and click OK.

      image

      Parameter

      Description

      Cluster type

      Select ACK Cluster, ACK Serverless Cluster, or ACS Cluster.

      Note

      If you do not grant the cluster permissions to call MSE, you need to click the link to perform authorization.

      Cluster Name/ID

      Select the name or ID of the cluster for which Microservices Governance is enabled. You can use keywords to search for cluster names or IDs.

      ack-onepilot

      Displays the status of the ack-onepilot component.

      • If the ack-onepilot component is not installed, click Click Install on the right of ack-onepilot. After the installation is complete, the status of the ack-onepilot component is displayed as Installed.

      • If you perform the operation as a RAM user and a message is displayed, indicating that you have no permissions to perform the operation, you can log on to the ACK console to access the desired cluster, and choose Operations > Add-ons. Then, find ack-onepilot and click Install.

      Note
      • In this step, the ack-onepilot component is involved. You can log on to the ACK console to access the destination cluster, and choose Operations > Add-ons to view the component details.

      • After the ack-onepilot component is installed, the agent is automatically injected. In this case, the startup time of the application may be increased by up to 10s.

      Access Type

      Select Single Application Access.

      Access Procedure

      Perform the following steps:

      Step 1: Go to the ACK console, and click the cluster name. In the left-side navigation pane of the page that appears, choose Workloads > Deployments. Then, select the namespace to which the application belongs.

      Step 2: Click the name of the connected application. On the page that appears, click View in YAML.

      Step 3: Edit the labels field in the following format and click Update.

      spec:
        template:
          metadata:
            labels:
              # The on value indicates that Microservices Governance is enabled. The on value must be enclosed in double quotation marks (").
              msePilotAutoEnable: "on"
              # The MSE microservice namespace where your application resides. If the namespace that you specify does not exist, a namespace with the specified name is automatically created.
              mseNamespace: 202401
              # The actual name of the application for which Microservices Governance is enabled. The name must be enclosed in double quotation marks (").
              msePilotCreateAppName: "your-deployment-name"

Step 2: Deploy applications

Deploy the spring-cloud-zuul, spring-cloud-a, spring-cloud-b, and spring-cloud-c applications, as well as the Nacos server and RocketMQ server. You can also obtain the source code from the demo link.

In the call process, spring-cloud-zuul receives a request from /A/dubbo and forwards the request to spring-cloud-a. Then, spring-cloud-a accesses spring-cloud-b by using the Dubbo protocol, and spring-cloud-b accesses spring-cloud-c in the same manner. After spring-cloud-c receives the request, a message is produced and the environment tag and IP address of spring-cloud-c are returned. spring-cloud-a consumes produced messages and calls spring-cloud-b by using Spring Cloud. Then, spring-cloud-b calls spring-cloud-c in the same manner and returns results in logs.

# When /A/dubbo is accessed, the return value is: A[10.25.xx.xx] -> B[10.25.xx.xx] -> C[10.25.xx.xx].
# At the same time, spring-cloud-a receives the message and logs the following information:

2021-12-28 10:58:50.301  INFO 1 --- [essageThread_15] c.a.mse.demo.service.MqConsumer
          : topic:TEST_MQ,producer:C[10.25.xx.xx],invoke result:A[10.25.xx.xx] -> B[10.25.xx.xx] -> C[10.25.xx.xx]
  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. On the Clusters page, find the cluster that you want to manage and click the name of the cluster or click Details in the Actions column. The details page of the cluster appears.

  3. In the left-side navigation pane of the details page, choose Workloads > Deployments.

  4. On the Deployments page, select a namespace and click Create from YAML. Use the following YAML code to deploy applications:

    Show YAML code

    # Deploy the Nacos server.
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nacos-server
    spec:
      selector:
        matchLabels:
          app: nacos-server
      template:
        metadata:
          labels:
            app: nacos-server
        spec:
          containers:
            - env:
                - name: MODE
                  value: "standalone"
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/nacos-server:v2.1.2
              imagePullPolicy: IfNotPresent
              name: nacos-server
              ports:
                - containerPort: 8848
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nacos-server
    spec:
      type: ClusterIP
      selector:
        app: nacos-server
      ports:
        - name: http
          port: 8848
          targetPort: 8848
    
    # Deploy the business applications.
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-zuul
    spec:
      selector:
        matchLabels:
          app: spring-cloud-zuul
      template:
        metadata:
          labels:
            app: spring-cloud-zuul
            msePilotCreateAppName: spring-cloud-zuul
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
                - name: enable.mq.invoke
                  value: 'true'
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-zuul:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-zuul
              ports:
                - containerPort: 20000
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.small
        service.beta.kubernetes.io/alicloud-loadbalancer-address-type: internet
      name: zuul-slb
    spec:
      ports:
        - port: 80
          protocol: TCP
          targetPort: 20000
      selector:
        app: spring-cloud-zuul
      type: LoadBalancer
    status:
      loadBalancer: {}
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-a
    spec:
      selector:
        matchLabels:
          app: spring-cloud-a
      template:
        metadata:
          labels:
            app: spring-cloud-a
            msePilotCreateAppName: spring-cloud-a
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-a
              ports:
                - containerPort: 20001
              livenessProbe:
                tcpSocket:
                  port: 20001
                initialDelaySeconds: 10
                periodSeconds: 30
    
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-b
    spec:
      selector:
        matchLabels:
          app: spring-cloud-b
      template:
        metadata:
          labels:
            app: spring-cloud-b
            msePilotCreateAppName: spring-cloud-b
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-b:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-b
              ports:
                - containerPort: 20002
              livenessProbe:
                tcpSocket:
                  port: 20002
                initialDelaySeconds: 10
                periodSeconds: 30
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-c
    spec:
      selector:
        matchLabels:
          app: spring-cloud-c
      template:
        metadata:
          labels:
            app: spring-cloud-c
            msePilotCreateAppName: spring-cloud-c
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-c
              ports:
                - containerPort: 20003
              livenessProbe:
                tcpSocket:
                  port: 20003
                initialDelaySeconds: 10
                periodSeconds: 30
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: rockectmq-broker
    spec:
      selector:
        matchLabels:
          app: rockectmq-broker
      template:
        metadata:
          labels:
            app: rockectmq-broker
        spec:
          containers:
            - command:
                - sh
                - mqbroker
                - '-n'
                - 'mqnamesrv:9876'
                - '-c /home/rocketmq/rocketmq-4.9.7/conf/broker.conf'
              env:
                - name: ROCKETMQ_HOME
                  value: /home/rocketmq/rocketmq-4.9.7
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/rocketmq:4.9.7
              imagePullPolicy: Always
              name: rockectmq-broker
              ports:
                - containerPort: 9876
                  protocol: TCP
                - containerPort: 10911
                  protocol: TCP
                - containerPort: 10912
                  protocol: TCP
                - containerPort: 10909
    
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: rocketmq-name-server
    spec:
      selector:
        matchLabels:
          app: rocketmq-name-server
      template:
        metadata:
          labels:
            app: rocketmq-name-server
        spec:
          containers:
            - command:
                - sh
                - mqnamesrv
              env:
                - name: ROCKETMQ_HOME
                  value: /home/rocketmq/rocketmq-4.9.7
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/rocketmq:4.9.7
              imagePullPolicy: Always
              name: rocketmq-name-server
              ports:
                - containerPort: 9876
                  protocol: TCP
                - containerPort: 10911
                  protocol: TCP
                - containerPort: 10912
                  protocol: TCP
                - containerPort: 10909
                  protocol: TCP
    
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: mqnamesrv
    spec:
      type: ClusterIP
      selector:
        app: rocketmq-name-server
      ports:
        - name: mqnamesrv-9876-9876
          port: 9876
          targetPort: 9876
                            
  5. Run the following command to check whether the applications are successfully deployed:

    kubectl get svc,deploy

    Expected output:

    NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
    service/kubernetes     ClusterIP      192.168.xx.xx    <none>         4xx/TCP        7d
    service/mqnamesrv      ClusterIP      192.168.xx.xx    <none>         98xx/TCP       47h
    service/nacos-server   ClusterIP      192.168.xx.xx    <none>         88xx/TCP       47h
    service/zuul-slb       LoadBalancer   192.168.xx.xx   123.56.xx.xx   80:302xxx/TCP   47h
    
    NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/nacos-server           1/1     1            1           4m
    deployment.apps/rockectmq-broker       1/1     1            1           4m
    deployment.apps/rocketmq-name-server   1/1     1            1           5m
    deployment.apps/spring-cloud-a         1/1     1            1           5m
    deployment.apps/spring-cloud-b         1/1     1            1           5m
    deployment.apps/spring-cloud-c         1/1     1            1           5m
    deployment.apps/spring-cloud-zuul      1/1     1            1           5m

Step 3: Enable the RocketMQ-based canary release feature for applications

In this example, spring-cloud-c produces messages and spring-cloud-a consumes the messages. Enable the RocketMQ-based canary release feature for the two applications.

Note
  • To enable or disable the RocketMQ-based canary release feature for an application, you must re-deploy the application in the ACK console to make the change take effect.

  • Canary release takes effect on messages only when RocketMQ-based canary release is enabled for both the producers and consumers of the messages.

  • Canary release is available for only RocketMQ messages, including Apache RocketMQ messages and ApsaraMQ for RocketMQ messages.

    • If you use Apache RocketMQ, RocketMQ Server and RocketMQ Client must be of 4.5.0 or later.

    • If you use ApsaraMQ for RocketMQ 4.x, you must use the Platinum Edition that supports SQL92 filtering. If you use client-side filtering or ApsaraMQ for RocketMQ 5.x, the Platinum Edition is not mandatory.

    • If you use the Ons client, the client must be of 1.8.0.Final or later.

  • After you enable the RocketMQ-based canary release feature, MSE changes the consumer group name of messages. For example, the consumer group name of messages is group1 and the environment tag is gray. After you enable the RocketMQ-based canary release feature, the consumer group name is changed to group1_gray. If you use ApsaraMQ for RocketMQ messages, you must create a consumer group in advance.

  • By default, MSE uses SQL92 syntax to filter messages. If you are using Apache RocketMQ, you must enable SQL92 filtering on the server side by adding the enablePropertyFilter=true configuration to the broker.conf file.

  • If SQL92 filtering is not supported, you can use the FilterMessageHook class to filter messages that are consumed by consumers. To use this method, you must enable the canary release for messaging feature for all applications and select the client filtering method. If you use this filtering method, all messages are processed in each environment. This increases the workloads of message producers and consumers. We recommend that you do not use this filtering method in the production environment.

  1. Log on to the MSE console, and select a region in the top navigation bar.

  2. In the left-side navigation pane, choose Microservices Governance > Application Governance.

  3. On the Application list page, click the resource card of the destination application. In the left-side navigation pane, click Traffic management.

  4. Click the Message grayscale tab, turn on Open message grayscale, and then click OK.

    image

  5. Log on to the ACK console and redeploy the application to make the configuration take effect.

Step 4: Deploy applications of canary versions

Deploy spring-cloud-a-gray, spring-cloud-b-gray, and spring-cloud-c-gray. spring-cloud-a-gray, spring-cloud-b-gray, and spring-cloud-c-gray are the canary versions of spring-cloud-a, spring-cloud-b, and spring-cloud-c.

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. On the Clusters page, find the cluster that you want to manage and click the name of the cluster or click Details in the Actions column. The details page of the cluster appears.

  3. In the left-side navigation pane of the details page, choose Workloads > Deployments.

  4. On the Deployments page, select a namespace and click Create from YAML. Use the following YAML code to deploy the applications:

    Show YAML code

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-a-gray
    spec:
      selector:
        matchLabels:
          app: spring-cloud-a-gray
      template:
        metadata:
          labels:
            alicloud.service.tag: gray
            app: spring-cloud-a-gray
            msePilotCreateAppName: spring-cloud-a
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-a-gray
              ports:
                - containerPort: 20001
              livenessProbe:
                tcpSocket:
                  port: 20001
                initialDelaySeconds: 10
                periodSeconds: 30
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-b-gray
    spec:
      selector:
        matchLabels:
          app: spring-cloud-b-gray
      template:
        metadata:
          labels:
            alicloud.service.tag: gray 
            app: spring-cloud-b-gray
            msePilotCreateAppName: spring-cloud-b
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-b:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-b-gray
              ports:
                - containerPort: 20002
              livenessProbe:
                tcpSocket:
                  port: 20002
                initialDelaySeconds: 10
                periodSeconds: 30
    
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-c-gray
    spec:
      selector:
        matchLabels:
          app: spring-cloud-c-gray
      template:
        metadata:
          labels:
            alicloud.service.tag: gray
            app: spring-cloud-c-gray
            msePilotCreateAppName: spring-cloud-c
        spec:
          containers:
            - env:
                - name: JAVA_HOME
                  value: /usr/lib/jvm/java-1.8-openjdk/jre
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
              imagePullPolicy: Always
              name: spring-cloud-c-gray
              ports:
                - containerPort: 20003
              livenessProbe:
                tcpSocket:
                  port: 20003
                initialDelaySeconds: 10
                periodSeconds: 30

Step 5: Introduce traffic and verify the result

  1. Log on to the MSE console, and select a region in the top navigation bar.

  2. In the left-side navigation pane, choose Microservices Governance > Application Governance.

  3. Click the resource card of the spring-cloud-a application. On the Application overview page, view the QPS data and check that all requests are routed to spring-cloud-a that is a stable version.

  4. In the left-side navigation pane, click Traffic management. Then, click the Label routing tab, find the gray tag, and then click Add in the Traffic rules column.

    image

  5. In the Create label route panel, configure a traffic rule, and click OK.

    In this example, name=xiaoming is configured as the traffic rule. For more information about how to add a routing rule, see Configure tag-based routing.

    f169c5f82eac607ce38ff7beb464e234

    After the traffic rule takes effect, you can view the traffic distribution on the Application overview page.

  6. On the Label routing tab, click the name of the rule that corresponds to the gray tag. In the Rule Details panel, click Edit. In the Modify Tag-based Routing Rule panel, turn on Whether link delivery and click OK.

    Note

    After you turn on Whether link delivery, requests that meet the name=xiaoming rule are passed through the canary environment during the entire process. You no longer need to configure other rules.

  7. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  8. On the Clusters page, find the cluster that you want to manage and click its name. In the left-side pane, choose Network > Services.

  9. Click the zuul-slb service. In the Basic Information section of the zuul-slb service, click the external IP address.

  10. On the service call page, enter /A/dubbo?name=xiaoming, and click Start Call.

    The end-to-end canary release takes effect.

    The following figure shows the request data of spring-cloud-b.

    spring cloud b应用流量曲线

Step 6: Adjust the tag-based message filtering rule and verify the result

  1. Log on to the MSE console.

  2. In the left-side navigation pane, choose Microservices Governance > Application Governance. On the Application list page, click the resource card of the spring-cloud-a application.

  3. In the left-side navigation pane, click Traffic management. On the Message Grayscale tab, find the Tags Ignored in Base Environment parameter, select gray from the tag drop-down list, and then click OK.

    If you select gray for Tags Ignored in Base Environment, messages with the gray tag can be consumed by spring-cloud-a-gray. spring-cloud-a cannot consume such messages. The Tags Ignored in Base Environment parameter dynamically takes effect after you configure the parameter. You do not need to restart the application.

    Note

    By default, base applications consume messages from all environments. If you do not want one base application to consume messages that are produced by a tagged environment, you need only to configure the Tags Ignored in Base Environment parameter.

  4. Log on to the ACK console to view the logs of spring-cloud-a and verify configurations.

    The following log shows that consumers in the base environment can consume both messages that are produced in the base and canary environments. After you select gray for the Tags Ignored in Base Environment parameter, consumers in the base environment can consume only the messages that are produced in the base environment.

    日志