用 Arthas “庖丁解牛”

作者 | Halimao Java、go 爱好者( https://github.com/halimao/

【Arthas 官方社区正在举行征文活动,参加即有奖品拿哦~ 点击投稿

生产环境的 bug 开发环境无法复现怎么办?关键位置没有打印日志信息不足怎么办?莫慌,骚年。让强大的 Arthas法师来 carry,带你去生产环境”遨游”闯关。

刚接触 Arthas,就被它能够 watch 方法的输入参数和返回值的功能震惊到了。这简直太酷炫了,让你可以像本地单步调试一样,跟踪到每一步的执行结果和获取当前的变量数值。以前要定位线上问题,信息不足就需要加日志打印,定位问题,可能需要反复重启应用。用了 Arthas,根本不需要加日志打印,重启应用这些操作。花了大概一个周末下午,在本地跑了下官方 demo,熟悉了下常用操作。脑子里对 Arthas 能够做什么,能解决什么,怎么解决,已经有了大概的了解。后面需要用的时候,就能派上大用场了(学了就一定有 bug 会找上门的=.=)。

下面介绍一个特意找上门的 bug。

背景:同一个聊天交友类产品,对外以一个主品牌以及多个新品牌进行发布。服务端是共用一套数据的,但是所有对外展示的信息,涉及到品牌相关的,需要进行文案替换。在同一个群组里,主品牌和新品牌的用户可以互相聊天。

问题现象:

  • 线上某个群组里面,同一条聊天消息涉及到需要替换文案的内容时,主品牌侧的用户有的显示正常,有的显示为新品牌文案;
  • 不同的群聊天消息,同一个用户有的展示正常,有的异常;
  • 新品牌侧的用户看到的群聊天消息文案替换正常。

先贴下相关的代码(用 Arthas 的 jad 直接反编译的源码):

群聊消息下发方法:

write 方法文案替换逻辑代码:

PublishMessage 是下行消息类,replaceMsgMap 是提前生成好的各个新品牌对应文案,主品牌使用原始消息文案。

乍一看,文案替换逻辑没啥毛病(但问题就在这,大家可以先思考下),感觉自己又要去面对一个扑朔迷离的玄学 bug 了(永远不要把程序 bug 归结为灵异事件)。代码看不出问题,本地单步调试鼓捣了一早上,也没复现出来,看来只能在生产环境定位了,Arthas 要登场了。

由于生产环境的消息转发量很大,直接 attach 进程风险太高,且不利于单条消息观察定位。所以选择预发布环境进行 attach,请求量可控,数据和线上一致,也只有读操作,不会影响到生产环境。

用 Arthas 的 watch 命令,观察 write 方法的输入参数。

  • -x 表示遍历深度,可以调整来打印具体的参数和结果内容,默认值是 1
  • -b 表示观察方法调用前

可以看到,publishMessage、userSession 参数的值都显示出来了。接着就可以在预发布触发消息下行进行数据观察了。

建了个测试群,除了自己一个主品牌的测试用户还有另外一个新品牌用户。最初开始发送了几条群聊消息都正常,后面又拉了一个新品牌用户以及主品牌测试用户,复现的概率就高了许多。观察了下同一条群聊消息发给每个群成员的 publishMessage 值,发现如果先遍历到了新品牌用户,再遍历到主品牌用户时,publishMessage 的文案居然是新品牌文案!!!心里猛的一惊,是了,就是这个低级错误造成的 bug,大家应该也猜到原因了。

下面揭晓下这个问题产生的原因:

  • 遍历群成员传递的 publishMessage 形参,每次改变 payload 都会影响到被传递进去的 publishMessage 实参
  • replaceMsgMap 里只存储了新品牌文案
  • 主品牌根据 appName 获取对应文案时为空,则不设置 payload,使用最传递进来的 publishMessage 的 payload
  • 遍历群组成员时,顺序是随机性的

如果某个主品牌用户在新品牌用户之后被遍历到,那么 publishMessage 的 payload 字段就会被设置为新品牌文案。而主品牌在 replaceMsgMap 里找不到对应文案,就不更新 payload了,复用了上一次被遍历用户的 payload,就会出现文案显示异常。

知道原因后就好处理了,replaceMsgMap 里把主品牌的文案也加进去,每次遍历到主品牌,也更新 payload 字段,保证文案正常显示。

整个定位过程,无需增加 log 日志,线上应用也无需重启,便能获取足够的信息进行问题排查定位,是不是贼好用了。花个半天时间,摸索鼓捣下,要用时就能省下不少工夫。详细使用文档见-> 官方文档

一键安装并启动 Arthas

  • 方式一:通过 Cloud Toolkit 实现 Arthas 一键远程诊断

Cloud Toolkit 是阿里云发布的免费本地 IDE 插件,帮助开发者更高效地开发、测试、诊断并部署应用。通过插件,可以将本地应用一键部署到任意服务器,甚至云端(ECS、EDAS、ACK、ACR 和 小程序云等);并且还内置了 Arthas 诊断、Dubbo工具、Terminal 终端、文件上传、函数计算 和 MySQL 执行器等工具。不仅仅有 IntelliJ IDEA 主流版本,还有 Eclipse、Pycharm、Maven 等其他版本。

推荐使用 IDEA 插件下载 Cloud Toolkit 来使用 Arthas: http://t.tb.cn/2A5CbHWveOXzI7sFakaCw8

  • 方式二:直接下载

地址: https://github.com/alibaba/arthas

Arthas 征文活动火热进行中

Arthas 官方正在举行征文活动,如果你有:

  • 使用 Arthas 排查过的问题
  • 对 Arthas 进行源码解读
  • 对 Arthas 提出建议
  • 不限,其它与 Arthas 有关的内容
    欢迎参加征文活动,还有奖品拿哦~ 点击投稿

阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”