一、背景

在分布式架构环境下,服务间的依赖日益复杂,可能没有人能说清单个故障对整个系统的影响,构建一个高可用的分布式系统面临着很大挑战。在可控范围或环境下,使用 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

三、场景模拟

image.png

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

image.png

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

修改返回值之前:
image.png

修改返回值之后:

image.png

注意:指定类方法的返回值,仅支持基本类型、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 列表

image.png

  • CodeCache 满了的场景下

image.png

  • 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

故障注入之前:
image.png

故障注入之后:
image.png

点赞(0) 打赏

Comment list 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部