背景

某项目一个查询界面,在没有人访问情况下,接口返回时间在3s+,压测50并发平均响应时间在8s+

在没有高并发情况下,出现接口慢大概率是SQL查询效率慢问题。

排查

Arthas trace命令可以观察方法执行时间,并且记录调用其他方法所用的时间,找到接口的代码,trace其调用方法(一般在service层进行观察)

Read the rest of this entry

背景

某客户审批系统报错,界面上提示审批失败

接口没有其他错误信息,后台也没有报错,找到接口代码,代码如下:

public Map executeTaskAction(.....) throws TaskActionException {
        //....省略不关键代码
        try {
            this.activitiService.executeTaskAction(iRequest, taskId, actionRequest, false);
            stringStringHashMap.put("success", true);
            return stringStringHashMap;
        } catch (Exception e) {
            stringStringHashMap.put("success", false);
            stringStringHashMap.put("message", "发放失败");
            return stringStringHashMap;
        }
    }

Read the rest of this entry

背景

某项目需要升级kubernetes集群,考虑到原k8s版本较低,并且在部署结构上不是很合理,因此决定重新搭建一套新的k8s集群,做应用迁移。迁移过程也是非常曲折,这个后面会专门写一篇文章记录,应用迁移后有部分应用在注册中心状态为DOWN

如果服务状态为DOWN调用该服务就报404错误,因为应用配置了健康检查,怀疑是健康检查没有通过,进入后台调用接口查看检查结果

$ curl http://localhost:8080/management/health
{"description":"Remote status from Eureka server","status":"DOWN"}

服务使用jhipster框架生成,在配置文件里面有以下配置

eureka:
    client:
        enabled: true
        healthcheck:
            enabled: true
        fetch-registry: true
        register-with-eureka: true
        instance-info-replication-interval-seconds: 10
        registry-fetch-interval-seconds: 10

eureka.client.healthcheck.enabled设置为false后,注册中心恢复正常,因此可以肯定是健康检查的问题。但是在后台没有任何错误,甚至将日志级别调整到最低也未发现错误信息,这个给排查带来很大的困难。

Read the rest of this entry

,

背景

如今容器化大行其道,不懂点docker都不好意思跟人打招呼,但容器化后也给运维带来了很大的挑战,容器都讲究小而精,尽可能在最小的体积里运行应用,减少体积的结果就是要舍弃一些工具,比如ping,大部分容器都舍弃了该工具,导致在容器里需要获取一个host的ip变得麻烦很多。java应用也一样,有可能容器中就只有一个java其他什么都没有,在这种情况下如何进行问题的诊断,如何使用java诊断神器arthas。

卷挂载方式

由于Arthas免安装,只是一些jar包,所以可以在docker运行时通过卷的方式挂载到容器内部。以tomcat为例

docker run -p 8888:8080 -v /you/path/arthas-packaging-3.1.7-bin/:/arthas -d tomcat

在运行时将arthas相关jar包目录挂载到容器内/arthas目录下,进入容器环境启动arthas

Read the rest of this entry

背景

在开发bpm流程,流程流转到平行审批节点时报错,流程如下:

报错信息如下:

Caused By: java.lang.NullPointerException
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.addTaskAttributesToXml(MIUserTaskRequest.java:568)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.processInputData(MIUserTaskRequest.java:319)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.handleTaskServiceInvoke(MIUserTaskRequest.java:158)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.doExecute(MIUserTaskRequest.java:128)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MISequenceBlock.doExecute(MISequenceBlock.java:68)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callMicroInstruction(MicroInstructionContext.java:203)
        at oracle.bpm.bpmn.engine.microkernel.MICall.doExecute(MICall.java:38)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MISequenceBlock.doExecute(MISequenceBlock.java:68)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callMicroInstruction(MicroInstructionContext.java:203)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callProcedure(MicroInstructionContext.java:210)
.......

Read the rest of this entry

背景

你是否和我一样一直有个疑问,如何查看系统执行过的所有sql,之前做oracle中间件实施的时候,由于oracle产品不开放源代码,也不公开表结构设计,因此一个功能涉及到哪些表,具体表里存的数据代表什么除了oracle没人知道,如果了解哪些功能涉及到哪些表,表里的数据都分表对应哪些功能更有助于我们对产品的理解和对问题的解决。

之前曾经想过通过oracle系统表v$sql进行监控,但效果并不理想,如果用过druid连接池应该知道,druid主打的功能就是sql监控(一个数据库连接池竟然干监控的活,有点不务正业),druid的原理是提供了一套jdbc的接口,自然所有的sql都要通过它来执行,这个也给了我们一个思路,如果可以监控jdbc相关方法的执行,不就可以实现以上目的,有了arthas之后,这个事就变得很简单。

jdbc

我们知道,jdbc中负责执行sql的是PreparedStatementStatement,PreparedStatement用于参数绑定,有防注入,避免硬解析等好处,Statement执行纯sql,因此正式环境一般推荐使用PreparedStatement进行sql操作,PreparedStatement通过Connection.prepareStatement(String sql)方法创建,所以我们监控该方法就能得到sql,arthas中watch命令可以监控方法的执行,那问题来了,Connection只是jdbc的接口,并非最终的实现类,我们需要监控的是实现类,并非接口,通过查看oracle jdbc驱动包不难发现,oracle jdbc对于Connection的实现类是oracle.jdbc.OracleConnectionWrapper,执行下面命令开始监控。

Read the rest of this entry

背景

今天开始新的系列,这个系列也是我一直想写的,有几个原因迟迟没开始,一个是担心自己学艺不精,误人子弟,另一个是没有积累较多的使用案例,目前这两个问题已经不是问题,arthas大部分命令也都使用过,并且也积累了较多案例,是时候开始动笔。

要写什么内容,这个也是我一直思考的问题,官网的文档已经很详细,我觉得没有必要再写一份介绍如何使用的教程,arthas的魅力在于线上调试java的黑科技,这一点官网的几个简单示例是不足以展现的,因此我绝对本系列着重讲实战,通过具体的例子展现arthas神奇的黑科技。

既然要写实战,那为什么还要写入门篇,入门是让你知道arthas是个什么东西,怎么安装,知道这两点就够了,足以让你学习接下来的内容,入门还是很有必要的,就像你追一个妹子,再喜欢也要先了解对方的基本信息,投其所好,磨刀不误砍柴工。

Read the rest of this entry