一、背景
在分布式架构环境下,服务间的依赖日益复杂,可能没有人能说清单个故障对整个系统的影响,构建一个高可用的分布式系统面临着很大挑战。在可控范围或环境下,使用 ChaosBlade 工具,对系统注入各种故障,持续提升分布式系统的容错和弹性能力,以构建高可用的分布式系统。
分布式系统高可用原则:
- 失败重试
- 实例隔离
- 流量调度
- 开关&预案
- 监控告警
- 日志跟踪
通过一系列的混沌工程试验,观察试验的结果,进一步分析分布式系统是否高可用。
二、混沌实验场景实践
2.1 准备工作:
- 执行 JAVA 实验场景必要步骤,挂载 Java agent
blade prepare jvm
-j, --javaHome string 指定 JAVA_HOME 路径,用于指定 java bin 和 tools.jar,如果不添加此参数,默认会优先获取 JAVA_HOME 环境变量,如果获取失败,会解析指定进程参数获取 JAVA_HOME,获取失败,会使用 chaosblade 自带的 tools.jar
--pid string java 进程ID
-P, --port int java agent 暴露服务的本地端口,用于下发实验命令
-p, --process string java 进程关键词,用于定位 java 进程
-d, --debug 开启 debug 模式
将 blade 挂载到 pid 为 8 的应用中
blade p jvm --pid 8
三、场景模拟
3.1 失败重试 (注入自定义异常)
- 实验场景:调用下游服务实例异常。
- 容错方案:会再次请求另外一个服务实例进行重试。
- 场景模拟:服务 A 调用 B,对 B1 注入异常故障,A 服务调用到 B1 时会出现调用失败。
- 预期方案:系统会将 A 服务的请求路由到 B2 进行重试。
blade 命令:
blade c dubbo throwCustomException --exception <EXCEPTION> --service <SERVICE> --provider
- 修复方案:添加失败检测和请求重试能力。
示例:
blade c dubbo throwCustomException --exception java.lang.Exception --service tech.yummy.devops.testss.dubboclient.chaosblade.INotifyService --provider
3.2 实例隔离 (超时)
- 演练场景:多次调用下游一个服务实例超时。
- 容错方案:会隔离或者下线此服务实例,防止请求路由到此服务实例。
- 场景模拟:服务 A 调用服务 B ,对 B1 注入延迟故障,A 服务调用到 B1 时,出现调用超时。
- 预期方案:系统会自动隔离或下线 B1 实例。
blade 命令:
blade c dubbo delay --time <DELAY> --service <SERVICE> --provider
- 修复方案:添加服务质量检查,下线不可用的服务实例。
示例:
blade c dubbo delay --time 8000 --service tech.yummy.devops.testss.dubboclient.chaosblade.INotifyService --
provider
3.3 日志跟踪 (修改方法返回值)
- 演练场景:修改应用中具体方法返回值。
- 容错方案:全链路调用日志记录。
- 场景模拟:修改服务的一个业务方法的返回值。
- blade 命令:blade c jvm return --classname <CLASS> --methodname <METHOD> --value <RETURN>
- 修复方案:添加全链路日志记录,便于排查和追溯问题。
示例:
blade c jvm return --value hello --classname
tech.yummy.devops.test.controller.chaosblade.TestReturnController --methodname testReturn
修改返回值之前:
修改返回值之后:
注意:指定类方法的返回值,仅支持基本类型、null 和 String 类型的返回值。
3.4 流量调度 ( CPU 满载)
- 演练场景:上游高并发下,扩容下游服务,在服务实例初始化时,CPU 负载高,导致上游服务受影响
- 容错方案:当服务实例机器负载高时,自动切流到正常机器
- 场景模拟:CPU 满载操作。
blade 命令:
blade c cpu fullload
- 修复方案:添加系统、应用资源监控和流量调度能力。
3.5 系统预案 (kill 实例)
- 演练场景:杀掉服务实例。
- 容错方案:快速拉起或扩容
- 场景模拟:杀掉服务 B 大部分实例。
blade 命令:
blade create process kill --process <PROCESS>
- 修复方案:添加相关系统预案。
示例:
blade c process kill --process appuser
3.6 其他场景:
- CodeCacheFilling
CodeCache主要用于存放native code,其中主要是JIT编译后的代码。被JIT编译的一般都是“热代码”,简单说就是调用频率比较高的代码,JIT编译后,代码的执行效率会变高,CodeCache满会导致JVM关闭JIT编译且不可再开启,那么CodeCache满会引起系统运行效率降低,导致系统最大负载下降,当系统流量较大时,可表现为RT增高、QPS下降等
命令: blade c jvm ccf
实例:
- 正常情况下,查询 ci 列表
- CodeCache 满了的场景下
- OutOfMemoryError
内存溢出场景,命令可以简写为:blade c jvm oom
--area string JVM 内存区,目前支持 [HEAP, NOHEAP, OFFHEAP],必填项。用Heap来表示Eden+Old,,用NOHEAP来表示metaspace,用OFFHEAP来表示堆外内存
--block string 指定对象大小,仅支持 HEAP 和 OFFHEAP 区,单位是 MB
--interval string 单位ms,默认500两次oom异常间的时间间隔,只有在非暴力模式才生效,可以减缓gc的频率,不用担心进程会无响应
--wild-mode string 默认false,是否开启暴力模式,如果是暴力模式,在OOM发生之后也不会释放之前创建的内存,可能会引起应用进程无响应
示例:
堆内存占用
blade c jvm oom --area HEAP --wild-mode true
故障注入之前:
故障注入之后:
发表评论 取消回复