Docker-maven-plugin + Dockerfile + Arthas实现应用诊断
一、前言
我们的微服务响应生产环境出现一个功能响应时间过慢,对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实现应用诊断的更多相关文章
- 实战docker,编写Dockerfile定制tomcat8镜像,实现web应用在线部署
最初在tomcat上部署web应用的方式,是通过maven的maven-compiler-plugin插件先打成war包,再将war包复制到tomcat的webapps目录下,后来用上了tomcat7 ...
- 使用Docker Maven 插件进行镜像的创建以及上传至私服
1.在进行服务容器化部署的时候,需要将服务以及其运行的环境整个打包做成一个镜像,打包的过程有两种办法,第一种是首选通过maven打成jar包,然后再编写dockerfile,执行docker buil ...
- 如何在Docker容器中使用Arthas
Arthas(阿尔萨斯) 能为你做什么? Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar ...
- 学习Maven之Cobertura Maven Plugin
cobertura-maven-plugin是个什么鬼? cobertura-maven-plugin是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考. ...
- Maven实现Web应用集成測试自己主动化 -- 部署自己主动化(WebTest Maven Plugin)
上篇:Maven实现Web应用集成測试自己主动化 -- 測试自己主动化(WebTest Maven Plugin) 之前介绍了怎样在maven中使用webtest插件实现web的集成測试,这里有个遗留 ...
- 解决Jetty Maven Plugin:Please initialize the log4j system properly(转)
解决Jetty Maven Plugin:Please initialize the log4j system properly.Jetty Maven Plugin环境: <plugin> ...
- Spring Boot Maven Plugin(二):run目标
简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...
- Spring Boot Maven Plugin(一):repackage目标
简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...
- Docker(二):Dockerfile 使用介绍
上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像.容器和 Dockerfile .我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dock ...
随机推荐
- Messenger实现进程间通信(IPC)
messenger内部也是实现aidl通信,所以可以看做一个轻量级aidl,但相对比较简单.首先开启一个服务并实现一个Handler用来处理消息,在onbind方法中返回IBinder对象,通过Ser ...
- drf 视图使用及源码分析
前言 drf视图的源码非常的绕,但是实现的功能却非常的神奇. 它能够帮你快速的解决ORM增删改查的重复代码,非常的方便好用. 下面是它源码中的一句话: class ViewSetMixin: &quo ...
- vue-cli3搭建的vue项目中使用jquery
装包:npm install jquery --save 方式一 全局使用 1)main.js中引入 // jquery import $ from 'jquery' Vue.prototype.$ ...
- ERROR: No matching distribution found for cv2
ImportError: No module named cv2和No matching distribution found for cv2的问题 原因 这个是由于没有导入opencv库导致的 解决 ...
- SAM学习笔记&AC自动机复习
形势所迫,一个对字符串深恶痛绝的鸽子又来更新了. SAM 后缀自动机就是一个对于字符串所有后缀所建立起的自动机.一些优良的性质可以使其完成很多字符串的问题. 其核心主要在于每个节点的状态和$endpo ...
- 5.MVCC
5 MVCC 全称是Multi-Version Concurrent Control,即多版本并发控制,在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读.MV ...
- php 上传音频文件并获取时长
<input type="file" name="audio" id="voice_file" style="display ...
- ssh连接客户端一段时间没响应就断掉的解决办法-保持长连接
修改(添加)server端的 /etc/ssh/sshd_config #server每隔60秒发送一次请求给client,然后client响应,从而保持连接 ClientAliveInterval ...
- 云原生haproxy 代理-ebpf
在如下网络层面下,代理(比如Envoy nginx )执行额外的L7策略(Health checks, service discovery, load balancing, mutual TLS),其 ...
- sk_buff结构--转载
套接字缓存之sk_buff结构 https://www.cnblogs.com/wanpengcoder/p/7529486.html 来此此处 sk_buff结构用来描述已接收或者待发送的数据报文信 ...