1. What is MSE
Alibaba cloud MSE (Microservices Engine) microservice engine includes the following three main modules: microservice registry, microservice governance and cloud native gateway. The label routing in the microservice governance function can realize the gray function.
2. Gray demand
Except for traffic entry (such as pile service, gateway service, etc.), all back-end services shall be able to support grouping by version;
Isolate the relevant versions of the application into an independent running environment, and route the request traffic that meets the rules to the target version application by setting flow control routing rules.
Sketch Map:
- Online service version v1111;
- New version v2222, i.e. grayscale version;
- Set the traffic rules. The traffic that meets the rules will enter the gray version, and the traffic that does not meet the rules will enter the online version;
Key requirements:
- It shall be able to route accurately according to traffic rules;
- The traffic must be full link;
3.demo program
There are four services: device - > charge - > order - > base, of which charge and order have two versions.
Architecture: k8s + springcloud + eureka + feign
Registration Center:
All services accept two parameters:
- str: record the link passed and output it in the last service;
- userId: route selection based on this value;
3.1.device \ charge \ order
Accept and process STR and pass str \ userId
EchoController.java
package com.ykc.edas; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @RestController public class EchoController { @Autowired private EchoFeign echoFeign; @RequestMapping(value = "/device", method = RequestMethod.GET) public String echo(@RequestParam(value="str", required = false) String str, @RequestParam(value="userId", required = false) String userId){ return echoFeign.echo(str + "device.v1111 -> ",userId); } }
EchoFeign.java
package com.ykc.edas; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @RestController @FeignClient(name = "edas-test2.charge") public interface EchoFeign { @RequestMapping(value = "/charge", method = RequestMethod.GET) String echo(@RequestParam(value="str", required = false) String str, @RequestParam(value="userId", required = false) String userId); }
3.2.base
Return str and userId
EchoController.java
package com.ykc.edas; import org.springframework.web.bind.annotation.*; @RestController public class EchoController { @RequestMapping(value = "/base", method = RequestMethod.GET) public String echo(@RequestParam(value = "str", required = false) String str, @RequestParam(value = "userId", required = false) String userId) { return str + "base.v1111 (userId: " + userId + ")"; } }
3.3. Request and output
Request device service: http://172.16.1.192:30000/device?userId="xxx"
If the route is online version, return: device v1111 -> charge. v1111 --> order. v1111 --> base. v1111 (userId: xxx)
If the route is grayscale version, return: device v1111 -> charge. v2222 --> order. v2222 --> base. v1111 (userId: xxx)
4. Deployment and configuration
4.1. Install the pack MSE pilot
Create in the specified K8S cluster
After creation, create the namespace MSE pilot in K8S and create the MSE pilot service under the namespace
4.2. Open "microservice governance" of the namespace where the service is located
Optional: enable microservice governance for all services under the namespace;
It does not need to be executed during production implementation. Start the configuration of individual applications one by one through the next step.
4.3. Apply deployment configuration
The online version and grayscale version of the same service are independent deployment in K8S, corresponding to different deployment configurations
deployment adds three configurations
Production configuration:
Grayscale configuration:
After the application is published, run 6 independent deployment s in k8s
4.4.MSE configuration
4.4.1.MSE application list
Four applications are automatically generated in the MSE application list, and the production version and gray version of the same application are aggregated together.
4.4. 2. Create label routing rules
The service directly called by the traffic portal service needs to configure routing rules; On the contrary, it is not necessary, because routing rules can be "link delivery";
For example, the five services a, b, c, d and e have the following call chains:
a -> b -> c -> d -> e
a -> c -> d -> e
Then b and c services need to configure traffic rules, and d and e services do not need to be configured.
4.4. 3. Parameter types supported by routing rules
Routing parameter type:
- cookie
- header
- parameter
- body content
Routing parameter expression:
- =
- !=
- >
- >=
- <
- <=
- in
- percentage
- Module 100
Expressions supported by modulo 100:
- =
- !=
- >
- >=
- <
- <=
The test case uses a mixture of parameter and header types:
Condition mode: meet any condition (another option is to meet all conditions)
Specific conditions:
- parameter: userId in (111, 222, 333)
- parameter: userId modulo 100 = 1
- header parameters: MSE username in (msd01, msd02, msd03)
4.4. 4. Real time traffic comparison view
4.4. 5. Gray routing rules and percentage logic
5. Test
Requests with userids 111, 222, 333 are routed to the grayscale version
[root@iZbp1ckjqrnvsfle1x9kzdZ deployment]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId='111';echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 111) [root@iZbp1ckjqrnvsfle1x9kzdZ deployment]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId='222';echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 222) [root@iZbp1ckjqrnvsfle1x9kzdZ deployment]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId='333';echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 333)
Requests with userId modulo 100 = 1 will be routed to the grayscale version
[root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId=101;echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 101) [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId=201;echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 201) [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId=1001;echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001) device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 (userId: 1001)
Requests whose userId is not in the above range are routed to the production version
[root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId=444;echo; done device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 444) [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device?userId=1002;echo; done device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: 1002) [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device;echo; done device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null) device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 (userId: null)
Header: MSE username is in the rule range and is routed to the grayscale version
[root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl -H "mse-username:msd01" http://172.16.1.192:30000/device;echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl -H "mse-username:msd02" http://172.16.1.192:30000/device;echo; done device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111 device.v1111 -> charge.v2222 --> order.v2222 --> base.v1111
Header: MSE username is not in the above range and is routed to the production version
[root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl -H "mse-username:msd04" http://172.16.1.192:30000/device;echo; done device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 [root@iZbp1ckjqrnvsfle1x9kzdZ ~]# for i in {1..10}; do curl http://172.16.1.192:30000/device;echo; done device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111 device.v1111 -> charge.v1111 --> order.v1111 --> base.v1111
6. Implementation and risk of MSE label routing
Using Java agent technology, load the plug-in arms-bootstrap-1.7 0-SNAPSHOT. Jar to realize no intrusion into user code
In essence, Alibaba's SDK is implanted to distribute requests according to custom routing rules.
Alibaba cloud's reply on risks:
- At present, many large customers have used MSE gray function;
- As long as there is no compatibility problem in the test phase, there will be no risk in production;
- The code realizes the emergency dynamic degradation ability, and the function degradation can be triggered by deleting the gray rule.
My supplementary:
- The performance impact shall be pressure tested;
- The worst way to reveal the risk is to remove the mse configuration from the deployment and trigger the application restart (msepilotauutoenable: 'on' is changed to 'off').
7. Gray publishing function landing
The change cost of the mse scheme to the existing environment (including R & D, operation and maintenance) is very small. After the implementation of the gray scheme, if you do not want to use gray or leave Alibaba cloud, the code does not need to be changed.
7.1. Changes on operation and maintenance side
1) Create components in K8S and create a container named MSE pilot;
2) For the business container to be opened, add notes to the deployment configuration:
- msePilotAutoEnable: 'on'
- msePilotCreateAppName: device / charge / order / base
- alicloud.service.tag: prod/gray
3) For traffic entry services (such as pile service and gateway service), add environment variables to deployment configuration:
alicloud.service.header = "mse-userId,mse-userName,mse-ipAddress,mse-deviceCode"
7.2. R & D side changes
Among the four parameters provided, the header is the most convenient: Alibaba cloud supports the header specified by the automatic transparent traffic portal service (the other three parameters need to be transmitted by the service itself).
The R & D needs to set the header in the traffic portal service, and other services do not need to be changed:
For example, set MSE devicecode in the gateway service and MSE userid, MSE username, MSE IPAddress, etc. in the gateway service.