灰度背景
随着掌门用户数量,业务的快速迭代,服务发布出现的事故影响面越来越大,有可能是新业务流程与老业务流程的互相兼容的问题,或者是前后端一些较小的手误导致应用故障(中台受此风险的影响更大)。
在不断的挖坑填坑中,我们总结出以下的问题:
- 影响范围不可控。一旦发布到生产,特别是一些特别重要的服务的发布,如登录、首页、组织架构、消息中心等。这些服务一旦出问题,会导致将近90%业务不可连续。
- 发布后验证的时间节点。为了保证上线后第一时间进行生产验证,一般在非业务高峰期(半夜12点后)进行发布和回归验证。深夜发布,不仅参与发版的开发,测试和运维同学较为疲劳,而且发布过程中遇到的各种小问题导致发布完成大多在深夜2点,这个时候因为发布人员都比较疲劳,在进行线上回归验证时难以保持足够的警惕心,容易产生漏测的情况。
- 问题反馈不易,出现生产问题后,只能通过被动的投诉来发现问题,开发人员疲于奔命,产品还要遭到差评。
灰度方案
针对以上背景,测试需要对已有的两套方案分别进行压测。综合评估,选取最优方案作为公司内部使用。
- 方案一:Java Agent
- 方案二:Solar(Java SDK)
Java Agent :是运行在 main方法之前的拦截器,内定的方法名是 premain ,原理是先执行 premain 方法然后再执行 main 方法。在加载java文件之前做拦截修改字节码,实现了按流量匹配灰度和按条件匹配灰度2种方式。
Java SDK:Solar运用SDK实现了基于http header传递和规则订阅的全链路发布。采用配置中心配置路由规则映射在网关过滤器中植入Header信息,路由规则传递到全链路服务中而实现。灰度路由方式主要有:多版本匹配灰度和多版本权重匹配灰度。
Java Agent:
1.按流量匹配灰度:
支持完全随机和路径随机,通过规则中设置百分比实现。如:
参数来源 | 参数 | 流量比 |
---|---|---|
header | gray | 30 |
2.按条件匹配灰度:
支持header,param,cookie,body参数来源,通过设置equals,in,notIn,range, startWith,endWith条件,配置的key,value的值。如:
参数来源 | 参数 | 条件 | 条件值 |
---|---|---|---|
header | gray | in | 1 |
只要请求满足规则配置,则路由灰度机器,否则路由common 机器。
路由架构图:

Solar(Java SDK):
1.多版本匹配灰度
灰度和common环境分别是2个不同版本号,配置中设置某个服务路由哪个版本号,配置文件中这样配置:
2.多版本权重匹配灰度
配置中设置不同版本的权重(流量比例),配置文件中这样配置:
按服务指定版本号和权重路由对应权重到版本号。
路由架构图:
业务拓扑图
公司业务复杂度请参考下图,这是内部某业务的局部拓补图:
由于业务调用链的复杂性,为了尽可能覆盖生产场景,又要做到不冗余。测试设计选用了1个网关+2个微服务的策略进行压测,详情见下文。
压测策略
1.压测阶段:集成测试-系统测试-验收测试-回归测试-性能测试
2.压测方法:逻辑覆盖法、基本路径测试法,场景法等
3.压测机器:所有实例选用阿里云独享型机器(1个网关+2个微服务)
多核独享 | CPU | Memory | Environment | 个数(台) |
---|---|---|---|---|
压测机 | 4C | 8G | UAT | 1 |
网关 | 8C | 16G | UAT | 1 |
微服务A | 4C | 8G | UAT | 3 |
微服务B | 4C | 8G | UAT | 4 |
4.压测分类:spring cloud原生,加包无灰度,加包有灰度
5.压测链路:网关-A-B,A-B
6.压测规则:为了保持2个方案条件一致性,统一选用权重30%的灰度流量作为规则
7.压测工具:
不是大家喜闻乐见的jMeter而是wrk。由于wrk具有一个良好的特性:很少的线程能够压出很大的并发量
以下是jmeter与wrk的实现原理的对比:
-------------------------------------------------------------------------------------------------------
其次,在同等压力下,wrk占用的资源远远小于jMeter,故本次压测中我们采用了wrk
简单介绍一下wrk的用法:
wrk配合lua脚本使用,属于命令行工具。命令格式:
./wrk -c1 -t1 -d10m -T8s -s ./scripts/wrk.lua --latency "http://10.25.174.21:8080"
参数解析:
8.压测参数:
9.压测脚本:
10.压测返回:为了避免处理复杂的逻辑,设计只返回一行简单的字符串
压测数据统计
压测QPS | G-A-B | A(1台)-B |
---|---|---|
spring cloud原生 | 5434 | 7850 |
agent无灰度 | 5223 | 7652 |
agent有灰度 | 4957 | 6174 |
无灰度性能下降百分比(和spring cloud 原生比较) | -3.88% | -2.52% |
有灰度性能下降百分比(和spring cloud 原生比较) | -8.77% | -21.35% |
----- | ----- | ----- |
spring cloud 原生 | 6244 | 5529 |
solar无灰度 | 6120 | 5100 |
solar有灰度 | 5830 | 4600 |
无灰度性能下降百分比(和spring cloud 原生比较) | -1.98% | -7.75% |
有灰度性能下降百分比(和spring cloud 原生比较) | -6.63% | -16.80% |
故障分析
测试过程中发现,同样的脚本,同样的场景,同样的参数在不同时间点,timeout个数较多,QPS波动较大,且qps较低,始终达不到预期。根据问题采取如下措施逐步得以解决(以原生为例):
- 分别在源和目标主机同时抓包:
,分析比较有没有丢包。发现target没有响应SYN,想到查看TCP accept queue是否满了tcpdump -i any host x.x.x.x -w /x/x.pcap
tcp压测工具_掌门全链路灰度压测实战 - 查看接收端的系统日志
有没有报错,结果并未有error信息/var/log/message
- 使用命令:
,果然,有大量连接溢出netstat -s | egrep "listen|LISTEN"
tcp压测工具_掌门全链路灰度压测实战 - 查看网关
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
tcp压测工具_掌门全链路灰度压测实战 - 查看网关
,发现somaxconn和max_syn_backlog两个值较小,需要调整cat /proc/sys/net/core/somaxconn
tcp压测工具_掌门全链路灰度压测实战 - 登录网关调整参数,步骤:
1、vi /etc/sysctl.conf2、调整如下2个参数值:
net.core.somaxconn=128 调整为1280
net.ipv4.tcp_max_syn_backlog=1024 调整为102403、生效
sysctl -p
重新压测,发现QPS并没有明显提升。考虑可能是机器性能问题。
-
网关尝试换机器:
网关实例规格由sn1(较老规格,CPU:8c)变更至 c6(新规格,CPU:8c)
说明:
同样核数的实例,新规格一般较停售的旧规格性能好。esc.c6具有2大优良特性:开启numa,CPU更厉害。
换机器后QPS有部分提升但还是达不到预期。
-
通过grafana看板,查看tcp连接数分析到网关到微服务的有效连接数接近20,几乎等于默认值。考虑查看:zuul.host.maxTotalConnections,zuul.semaphore.max-semaphores,zuul.host.maxPerRouteConnections这三个参数的值。
说明:
zuul.host.maxTotalConnections
适用于ApacheHttpClient,如果是okhttp无效。每个服务的http客户端连接池最大连接,默认是200。
zuul.host.maxPerRouteConnections
适用于ApacheHttpClient,如果是okhttp无效。每个route可用的最大连接数,默认值是20。
zuul.semaphore.max-semaphores
Hystrix 最大的并发请求
execution.isolation.semaphore.maxConcurrentRequests,这个值并非TPS、QPS、RPS等都是相对值,指的是1秒时间窗口内的事务/查询/请求,semaphore.maxConcurrentRequests是一个绝对值,无时间窗口,相当于亚毫秒级的。当请求达到或超过该设置值后,其其余就会被拒绝。默认值是100
- 修改zuul的参数:
zuul.host.maxTotalConnections=20000
zuul.semaphore.max-semaphores=5000
MaxConnectionsPerHost=2000
再次压测,QPS大幅上升。
-
尝试将A,B各换为1台ecs.c6后,A-B QPS上升较多
测试结果数据:
压测QPS | G-B | G-A-B | A(1台)-B |
---|---|---|---|
网关:ecs.c6 1台,A:独享型3 台,B:独享型 4台 | 9012 | 8512 | 7418 |
网关:ecs.c6 1台,A:ecs.c6 1台,B:ecs.c6 1台 | 8932 | 8486 | 11115 |
采取以上措施,最终timeout个数减少,所占比例不到0.1%。QPS达到9000左右,符合预期。
压测结论
性能测试过程中,CPU运行稳定,内存没有溢出现象。综合分析以上测试数据,由于solar 性能优于agent 5%左右, 未来将选用solar作为公司灰度方案,方便业务线灰度发布。
本文作者
谢璐,多年测试经历。 Github: [email protected], 现任职掌门1对1测试架构师,负责掌门基础架构部框架测试及组件测试。 谢庆芳,5年测试经验。 Github: Enersmill ,擅长性能测试,自动化测试。 熟悉java, python。 现任职掌门1对1测试开发工程师。
元旦快乐