记一次用Arthas线上debug实战
2020/2/6 17:23:05
本文主要是介绍记一次用Arthas线上debug实战,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
问题描述
在线上运行的项目中遇到bug。排查中怀疑是配置文件中的bean读取没有成功。通常我的做法是加一行日志,再重新上线代码。比如这样:
log.info("WxDomainProperties:{}",wxDomainProperties);
来看一下这个对象的属性到底是怎么样的。
不过这显然是一种比较低效的方式。下面介绍一种用阿里开源的arthas来实现线上debug的方式。
先看下相关的代码
被怀疑出现问题的bean就是下面这个bean,主要是用来配置域名信息。通过配置文件配置的值。在不同环境中,比如dev,local,online会有不同值。
/** * 微信第三方平台域名配置 * * @author yanghaolei * @date 2019/08/07 下午4:04 */ @Data @Component @ConfigurationProperties(prefix = WxDomainProperties.PREFIX) public class WxDomainProperties { public static final String PREFIX = "wx.domain"; /** * 请求域名 */ private List<String> requestDomainList = Lists.newArrayList(); /** * WebSocket域名 */ private List<String> wsRequestDomainList = Lists.newArrayList(); /** * 上传域名 */ private List<String> uploadDomainList = Lists.newArrayList(); /** * 下载域名 */ private List<String> downloadDomainList = Lists.newArrayList(); /** * 业务域名 */ private List<String> webviewDomainList = Lists.newArrayList(); } 复制代码
接下来我们注入这个bean到业务代码中。
@Slf4j @AllArgsConstructor @Service public class MaDomainService { private final WxService wxService; private final WxDomainProperties wxDomainProperties; 复制代码
在方法setDoamin中,bean储存的值会在默认情况下被自动载入。而我遇到的bug就是发现在默认情况下,载入的值都是null。所以我怀疑这个配置读取的值有问题。
public WxOpenMaDomainResult setDomain(MaDomainSetDTO maDomainSetDTO) { JSONObject requestJson = new JSONObject(); Integer status = maDomainSetDTO.getStatus(); String appId = maDomainSetDTO.getAppId(); // 1 启用默认配置 --> 强制覆盖成默认列表[初始化操作] if (StatusEnum.TRUE.getValue().equals(status)) { requestJson.put("action", SET_ACTION); requestJson.put("requestdomain", JSONArray.parse(JSON.toJSONString(wxDomainProperties.getRequestDomainList()))); requestJson.put("wsrequestdomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getWsRequestDomainList()))); requestJson.put("uploaddomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getUploadDomainList()))); requestJson.put("downloaddomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getDownloadDomainList()))); } // 2 未启用默认配置 --> 可以add/delete/get[不允许自定义set] else if (StatusEnum.FALSE.getValue().equals(status)) { //不允许自定义覆盖 if (SET_ACTION.equals(maDomainSetDTO.getAction())) { return new WxOpenMaDomainResult(); } requestJson.put("requestdomain", getJsonArray(maDomainSetDTO.getRequestDomainList())); requestJson.put("wsrequestdomain", getJsonArray(maDomainSetDTO.getWsRequestDomainList())); requestJson.put("uploaddomain", getJsonArray(maDomainSetDTO.getUploadDomainList())); requestJson.put("downloaddomain", getJsonArray(maDomainSetDTO.getDownloadDomainList())); } else { return new WxOpenMaDomainResult(); } try { String response = wxService.getMaService(appId).post(API_MODIFY_DOMAIN, requestJson.toJSONString()); return JSON.parseObject(response, WxOpenMaDomainResult.class); } catch (Exception e) { log.error("Error message:{},Error stackTrace:{}", e.getMessage(), e.getStackTrace()); return new WxOpenMaDomainResult(); } } 复制代码
为了验证我的怀疑没有问题,当然是需要debug去检查下这个值。但是这个是线上代码,像开始说的通过加日志重启检查值是比较麻烦的事情。所以想到了用arthas来做线上debug。
Arthas 实战
网上大部分资料对于arthas的介绍都停留于怎么安装和看一些控制台的信息。这里给出官网,Arthas 入门。我主要会讲我通过arthas验证我的怀疑和最后找到原因的过程。
我这里用到的命令是watch和trace。
watch命令执行数据观测,让我们能方便的观察到指定方法的调用情况。watch的格式是: watch + 类名表达式匹配 + 方法名 + 表达式 + 条件表达式。 我这里是想观察方法setDomain在调用过程中wxDomainProperties的值是否成功由配置文件读取。所以我的表达式是:watch + 类名[com.bjyt.bange.module.wx.middleware.MaDomainService] + 方法名[setDomain] + 表达式['target.wxDomainProperties' ]。这里target表示当前对象。条件表达式往往用来指定观察点和观察时间,这里不需要所以就没填。可以看到执行的结果:
可以看到我的怀疑是错的,这个bean是有值的。所以这也是为什么加日志效率低的原因,会浪费很多时间去验证一个错的怀疑。
接下来我用到了trace命令,希望通过跟踪方法内部到底是怎么跑的。trace命令可以跟踪方法内部调用路径,并输出方法路径上的每个节点上耗时。它与stack不一样的地方是stack输出的是当前方法的被调用路径。trace的格式同样是trace + 类名 + 方法名 + 表达式。下面是执行的结果:
这里可以明显看到倒数第二行的位置抛出了异常。经过分析发现是自己的代码写错了。。。最终根据arthas的结果我们完成了一次线上debug。
最后: 关于k8s或者docker中使用arthas
arthas是需要获取当前机器运行的jvm进程才可以工作的。在实际生产环境中,我们线上的机器应该都是部署在k8s或者docker中的。也就是说这些线上的机器同样需要安装arthas。阿里的官方指导中也特别提到了这一点,关于在容器中部署arthas。
实际上,我认为比较好的方式是开发人员在自己的本地安装arthas。然后通过arthas的webConsole连接到docker上的arthas。然后通过控制台进行远程线上的debug。关于这一点也在官方的user-case中找到了印证。记录如何使用arthas进行远程访问 #442。这样就能搭建一个更高效率的开发模式。而且还能大大减少代码中的诸如log.info这样的日志代码量。再考虑到arthas的功能远远不止于此,应该说还是值得去考虑的。
这篇关于记一次用Arthas线上debug实战的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)