一、前言

我们的微服务响应生产环境出现一个功能响应时间过慢,对Prometheus监控 Http Request进行分析发下该功能调用的后端接口响应时间平均在30秒以上,分析源码接口有mysql查询、MongoDB查询操作,对慢sql进行分析首先排除了慢sql问题,但是MongoDB作为高性能数据库几乎不会查询缓慢问题,由于没有一个即时的分析工具,无法判断程序在那块耗时较长,只有采取笨办法,在程序各个关键节点输出时间戳日志,最终排查到是MongoDB问题,线上MongoDB因为某种原因导致查询商品的数据到达百万级,而程序开发者在设计时未考虑到大数据情况,因为未设置索引。

1.1 为什么选择Arthas

Arthas是Alibaba开源Java应用诊断工具,具有

  • 活跃成熟的社区,文档齐全
  • arthas的定位是诊断问题排查,不会长时间attach在进程上,也不会作用在集群,不需要太多考虑对性能的开销
  • 支持Docker镜像
  • Dashboard实时查看系统的运行状况
  • 查看入参/返回值/异常
  • 性能热点
  • 类冲突
  • WebConsole
    等特点和特性。更多细节参考 中文官网

二、使用Arthas

Arthas支持单独部署安装arthas-boot.jar和将Arthas安装到基础镜像里两种方式,我们的微服务是基于Dokcer镜像进行发布,因此我们选择将把Arthas安装到基础镜像里:

2.1 使用docker-maven-plugin + Dockerfile构建镜像

# 在pom.xml增加docker-maven-plugin配置
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>${project.artifactId}:${project.version}</imageName>
# dockerDirectory 参数表示使用Dockerfile构建镜像,${basedir}表示Dockerfile与pom.xml同级目录
<dockerDirectory>${basedir}</dockerDirectory>
<dockerHost>http://192.168.128.xxxx:2375</dockerHost>
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<forceTags>true</forceTags>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>

2.2 修改Dockerfile 添加安装arthas代码

FROM java:8
ADD /app.jar // # copy arthas
COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev","/app.jar"]

注意Docker构建应该使用完整的JDK基础包,否则会出现Docker应用中arthas无法正常运行的问题,因为Arthas依赖JAVA的命令行工具和类库

2.3 使用公开的JDK基础镜像

FROM openjdk:8-jdk
FROM openjdk:8-jdk-alpine
FROM java:8

三 诊断工具使用案例

3.1 在线实时分析接口响应缓慢问题

生产环境出现接口响应缓慢,常想到分析手段是通过日志埋点来分析接口在那块处理耗费时间长,而通过集成arthas,使用trace命令可以渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

3.1.1 启动Docker 镜像进程中arthas

docker exec -it   c86629fdc6cb /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

启动结果:

[root@localhost ~]# docker exec -it   c86629fdc6cb /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"
--2020-11-25 15:17:33-- https://arthas.aliyun.com/arthas-boot.jar
Resolving arthas.aliyun.com (arthas.aliyun.com)... 203.119.214.116
Connecting to arthas.aliyun.com (arthas.aliyun.com)|203.119.214.116|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 138711 (135K) [application/java-archive]
Saving to: ‘arthas-boot.jar’ arthas-boot.jar 100%[========================================================================================>] 135.46K 245KB/s in 0.6s 2020-11-25 15:17:34 (245 KB/s) - ‘arthas-boot.jar’ saved [138711/138711] [INFO] arthas-boot version: 3.4.4
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 1 /app.jar

3.1.2 使用trace命令 侦听方法

 trace com.myyshop.saas.dsuserserver.controller.TdDsShopController createShop

访问接口,查看侦听结果

`---ts=2020-11-25 07:32:47;thread_name=http-nio-7004-exec-5;id=4c;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4ba534b0
`---[650.100619ms] com.myyshop.saas.dsuserserver.service.impl.TdDsShopServiceImpl$$EnhancerBySpringCGLIB$$3e545494:createShop()
`---[650.007439ms] org.springframework.cglib.proxy.MethodInterceptor:intercept()
`---[646.06381ms] com.myyshop.saas.dsuserserver.service.impl.TdDsShopServiceImpl:createShop()
+---[0.018917ms] com.myyshop.saas.dsuserserver.utils.LoginUtils:chkLogin() #110
+---[0.006053ms] com.dhgate.saas.common.core.model.LoginAppUser:getUserId() #111
+---[0.015575ms] com.baomidou.mybatisplus.core.conditions.query.QueryWrapper:<init>() #114
+---[0.027124ms] com.baomidou.mybatisplus.core.conditions.query.QueryWrapper:eq() #114
+---[5.757169ms] com.myyshop.saas.dsuserserver.mapper.TdDsShopMapper:selectCount() #114
+---[0.019784ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #121
+---[0.016377ms] com.dhgate.saas.common.core.utils.StringUtils:lowerCase() #121
+---[0.008651ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:setDomain() #121
+---[0.005473ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #124
+---[1.166932ms] com.myyshop.saas.dsuserserver.utils.DomainUtils:chkIsSensitiveWord() #124
+---[0.008751ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #131
+---[3.751548ms] com.myyshop.saas.dsuserserver.utils.DomainUtils:isRegisterDomains() #131
+---[0.008372ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #138
+---[0.012716ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getShopName() #138
+---[3.482077ms] com.myyshop.saas.dsuserserver.mapper.TdDsShopMapper:getcount() #138
+---[0.064746ms] com.myyshop.saas.dsuserserver.model.TdDsShop:<init>() #145
+---[0.007541ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #146
+---[0.012804ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setDomain() #146
+---[0.009306ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getShopName() #148
+---[0.00715ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #148
+---[0.009197ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setShopName() #148
+---[0.007298ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setUserId() #149
+---[0.011004ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setTemplateId() #150
+---[0.007945ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setCreatedAt() #151
+---[0.007562ms] com.myyshop.saas.dsuserserver.model.TdDsShop:setUpdatedAt() #152
+---[4.256693ms] com.myyshop.saas.dsuserserver.mapper.TdDsShopMapper:insert() #153
+---[0.01248ms] com.myyshop.saas.dsuserserver.model.TdDsShop:getShopId() #155
+---[0.018589ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:<init>() #160
+---[0.009691ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getCurrency() #162
+---[0.009491ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:currency() #162
+---[0.007937ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getLanguage() #163
+---[0.008896ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:language() #163
+---[0.007881ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getRefundPolicyUrl() #164
+---[0.009011ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:refundPolicyUrl() #164
+---[0.008243ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getPrivacyPolicyUrl() #165
+---[0.008377ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:privacyPolicyUrl() #165
+---[0.007477ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getShippingTermsUrl() #166
+---[0.013257ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:shippingTermsUrl() #166
+---[0.025617ms] com.myyshop.saas.dsuserserver.model.TdDsShopSetting$Builder:build() #167
+---[10.906103ms] com.myyshop.saas.dsuserserver.service.TdDsShopSettingService:save() #169
+---[609.588604ms] com.myyshop.saas.dsuserserver.feign.MyyshopOrderClient:fistTimeCreateShop() #173
+---[0.024436ms] com.myyshop.saas.dsuserserver.model.dto.TdDsShopParam:getDomain() #179
+---[5.150318ms] com.myyshop.saas.dsuserserver.utils.DomainUtils:setRegisterDomains() #179
+---[0.154152ms] com.dhgate.saas.common.core.utils.CopyUtils:copyObject() #181
+---[0.013183ms] com.myyshop.saas.dsuserserver.model.vo.DsShopVo:setShopId() #182
`---[0.02153ms] com.dhgate.saas.common.core.model.Result:succeed() #184

通过调用链分析,可以看出接口处理大量时间花费到一个feign调用上,可以考虑对该接口进行优化。

 
 

Docker-maven-plugin + Dockerfile + Arthas实现应用诊断的更多相关文章

  1. 实战docker,编写Dockerfile定制tomcat8镜像,实现web应用在线部署

    最初在tomcat上部署web应用的方式,是通过maven的maven-compiler-plugin插件先打成war包,再将war包复制到tomcat的webapps目录下,后来用上了tomcat7 ...

  2. 使用Docker Maven 插件进行镜像的创建以及上传至私服

    1.在进行服务容器化部署的时候,需要将服务以及其运行的环境整个打包做成一个镜像,打包的过程有两种办法,第一种是首选通过maven打成jar包,然后再编写dockerfile,执行docker buil ...

  3. 如何在Docker容器中使用Arthas

    Arthas(阿尔萨斯) 能为你做什么? Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar ...

  4. 学习Maven之Cobertura Maven Plugin

    cobertura-maven-plugin是个什么鬼? cobertura-maven-plugin是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考. ...

  5. Maven实现Web应用集成測试自己主动化 -- 部署自己主动化(WebTest Maven Plugin)

    上篇:Maven实现Web应用集成測试自己主动化 -- 測试自己主动化(WebTest Maven Plugin) 之前介绍了怎样在maven中使用webtest插件实现web的集成測试,这里有个遗留 ...

  6. 解决Jetty Maven Plugin:Please initialize the log4j system properly(转)

    解决Jetty Maven Plugin:Please initialize the log4j system properly.Jetty Maven Plugin环境: <plugin> ...

  7. Spring Boot Maven Plugin(二):run目标

    简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...

  8. Spring Boot Maven Plugin(一):repackage目标

    简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...

  9. Docker(二):Dockerfile 使用介绍

    上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像.容器和 Dockerfile .我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dock ...

随机推荐

  1. viewpage轮播图

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com ...

  2. vue学习笔记(六) ----- vue组件

    一.模块化与组件化 模块化的定义 模块化在Node中是一个规范,定义一些模块的相关的规则,从代码角度上来说,方便做区别,如果不使用模块化,写在js文件中不利于后期维护和扩展,从代码的层面上就把相关的功 ...

  3. docker搭建redis集群

    一.简介 docker作为一个容器技术,在搭建资源隔离性服务上具有很大的优势,在一台服务器上可以启动多个docker容器,感觉每个在容器里面部署的服务就像是部署在不同的服务器上.此次基于docker以 ...

  4. vim编辑器使用简介

    使用格式 vim [option] /path/to/somefile ... option: -o水平分割 -O垂直分割 +打开后在最后一行 +Num打开后在地Num行,加号与Num之间不能有空格 ...

  5. 动态链接的PLT与GOT

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/147 最近在研究缓冲区溢出攻击的试验,发现其中有一种方法叫做re ...

  6. 对Spark硬件配置的建议

    对于Spark开发人员来说,一个比较普遍的问题就是如何合理的配置Spark的硬件?当然如何合理的对Spark集群进行硬件配置要视情况而定,在这里给出以下建议: 存储系统 在大数据领域,有一句" ...

  7. 13flask密码加密

    一,了解密码加密方式 密码具有私有性较强的特性,预测密码加密对个人隐私的保护有这非常大的作用.在用flask搭建网站时候若服务器有被攻破的风险,要是用户表中密码字段也被拿走,后果将不堪设想. 在密码保 ...

  8. vi&vim 基本使用方法

    vi/&vim 基本使用方法 本文介绍了vi (vim)的基本使用方法,但对于普通用户来说基本上够了!i/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim 是vi的升级版本,它不仅 ...

  9. mysql yyyy-MM-dd function UNIX_TIMESTAMP('yyyy-MM-dd HH:mm:ss')

    mysql yyyy-MM-dd function UNIX_TIMESTAMP('yyyy-MM-dd HH:mm:ss') select UNIX_TIMESTAMP('1997-10-04 22 ...

  10. 睿象云:为什么 Zabbix 告警如此火热?

    每当我们谈及监控工具的时候,Zabbix 总是最惹人瞩目的那一个.如同清晨荷叶上的剔透露珠,卓尔不凡:如同巷子末头的百年酒香,让人倾心.我们都知道 Zabbix 是监控工具里当仁不让的龙头大哥,却没几 ...