在我们的日常开发中,肯定会遇到很多问题。当然这些问题可能不是我们去处理了,但是一定会有人要去处理。能处理的人一般都是牛人,当然我们也想变成牛人,所以我们得不断学习。
本篇文章主要讲系统监控和排错相关的内容,希望对大家有所帮助。
现在的架构基本都是容器部署,而我们呢,也是这样的环境,我们的部署使用的是Kubernates,但是在该容器下我们怎么去做到系统排错和调优呢?
一 调优工具
当我们想到要去做该事的时候,肯定得先看看,哪些开源的工具,我们可以用上
JMH
openjdk.java.net/projects/co...
Arthas
我们选择了Arthas
为什么选择Arthas
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率 。
Arthas 的优点有:
- 不需要修改代码即可进行调试;
- 支持多种协议和多种平台;
- 支持多种命令行参数;
- 支持自定义插件;
- 支持多进程 。
但是在接入Arthas时候,感觉有点麻烦
首先我们来看一下官网的一个接入例子
1.1 Arthas接入例子
1.1.1 启动 math-game
lua
curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar
math-game
是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。
math-game
源代码:查看在新窗口打开
1.1.2 启动 arthas
在命令行下面执行(使用和目标进程一致的用户启动,否则可能 attach 失败):
arduino
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
- 执行该程序的用户需要和目标进程具有相同的权限。比如以
admin
用户来执行:sudo su admin && java -jar arthas-boot.jar
或sudo -u admin -EH java -jar arthas-boot.jar
。 - 如果 attach 不上目标进程,可以查看
~/logs/arthas/
目录下的日志。 - 如果下载速度比较慢,可以使用 aliyun 的镜像:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
java -jar arthas-boot.jar -h
打印更多参数信息。
选择应用 java 进程:
ini
$ $ java -jar arthas-boot.jar
* [1]: 35542
[2]: 71560 math-game.jar
math-game
进程是第 2 个,则输入 2,再输入回车/enter
。Arthas 会 attach 到目标进程上,并输出日志:
arduino
[INFO] Try to attach process 71560
[INFO] Attach process 71560 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki: https://arthas.aliyun.com/doc
version: 3.0.5.20181127201536
pid: 71560
time: 2018-11-28 19:16:24
$
1.1.3 查看 dashboard
输入dashboard,按回车/enter
,会展示当前进程的信息,按ctrl+c
可以中断执行。
sql
$ dashboard
ID NAME GROUP PRIORI STATE %CPU TIME INTERRU DAEMON
17 pool-2-thread-1 system 5 WAITIN 67 0:0 false false
27 Timer-for-arthas-dashb system 10 RUNNAB 32 0:0 false true
11 AsyncAppender-Worker-a system 9 WAITIN 0 0:0 false true
9 Attach Listener system 9 RUNNAB 0 0:0 false true
3 Finalizer system 8 WAITIN 0 0:0 false true
2 Reference Handler system 10 WAITIN 0 0:0 false true
4 Signal Dispatcher system 9 RUNNAB 0 0:0 false true
26 as-command-execute-dae system 10 TIMED_ 0 0:0 false true
13 job-timeout system 9 TIMED_ 0 0:0 false true
1 main main 5 TIMED_ 0 0:0 false false
14 nioEventLoopGroup-2-1 system 10 RUNNAB 0 0:0 false false
18 nioEventLoopGroup-2-2 system 10 RUNNAB 0 0:0 false false
23 nioEventLoopGroup-2-3 system 10 RUNNAB 0 0:0 false false
15 nioEventLoopGroup-3-1 system 10 RUNNAB 0 0:0 false false
Memory used total max usage GC
heap 32M 155M 1820M 1.77% gc.ps_scavenge.count 4
ps_eden_space 14M 65M 672M 2.21% gc.ps_scavenge.time(m 166
ps_survivor_space 4M 5M 5M s)
ps_old_gen 12M 85M 1365M 0.91% gc.ps_marksweep.count 0
nonheap 20M 23M -1 gc.ps_marksweep.time( 0
code_cache 3M 5M 240M 1.32% ms)
Runtime
os.name Mac OS X
os.version 10.13.4
java.version 1.8.0_162
java.home /Library/Java/JavaVir
tualMachines/jdk1.8.0
_162.jdk/Contents/Hom
e/jre
二 问题汇总
2.1 Arthas问题
看起来还是很简单的,但是我们的用的K8S容器部署,不能去每个容器里执行这些命令吧,而且K8S容器如果死了会自动重启容器,感觉没有办法进行分析,每次去登录容器执行命令也很麻烦。
2.2 管理问题
当需要查看问题的时候,每次都得去容器执行命令,执行命令前还得安装这些命令
生成的容器做为开发一般是进去不了的,因为权限在运维手里,而一般运维又不会这些
微服务那么多,即使有权限,执行起来也不太方便。一个一个容器进去,浪费时间。
三 选择Cubic一站式监控平台
3.1 Cubic是什么
Cubic
一站式问题定位平台,以agent的方式无侵入接入应用,提供各种指标,动态线程堆栈追踪,完整集成arthas功能模块,致力于应用级监控,帮助开发人员快速定位问题。
Gitee: gitee.com/dromara/cub...
Github: github.com/dromara/cub...
Demo: http://43.138.50.220:6080
特性:
- 1、兼容性:整体监控不管你是IDC、ECS、Docker部署,都可完美兼容
- 2、易用: 无需任何配置,开箱即用,基于agent无侵入接入,升级应用端无感知
- 3、强大: 支持对应用的基础监控、堆栈监控、线程池监控等等
- 4、高扩展:提供良好的扩展接口,给你自主选择
不熟悉的可以再看看官方文档
3.2 Cubic快速接入
Cubic 主要有两部分,目前UI 和proxy 是写在一起的 目前的部署方式:
- ui 页面,页面目前为了方便适合proxy 打在一起的
- proxy 独立部署
- agent 需要和应用部署在同一台机器上。
构建
获取部署包
- 在项目发行版本可直接下载
- 也可以下载源码后自己打包。先clone 项目到本地,然后进入cubic 目录执行 scripts/build.sh.运行完成后会出现agent-dist 、agent-proxy-dist两个目录,第一个存放的是agent 加载需要的,第二个就是proxy 部署包。
- 可以单独打包页面,测试启动命令 npm run dev,打包命令 npm run build:prod ,打完的包在dist 下
准备
- 目前支持mac linux 系统
- 本机已经安装了jdk1.8+
- 本机 6080 11900 端口未被占用(此端口都在proxy 配置)
- 本机安装maven和nodejs(安装方式自行脑补)
启动
-
将agent-dist整体拷贝到你要部署的机器,在启动应用时加入
-javaagent:/path/agent-dist/cubic-agent.jar (添加agent)
-Dcubic.agent.service_name=cubic-proxy (添加项目名称)
-
启动
java -jar -javaagent:/path/agent-dist/cubic-agent.jar -Dcubic.agent.service_name=cubic-proxy cubic-proxy.jar
访问
- 通过 http://ip:6080 来对 web ui进行访问 ,默认地址 http://localhost:6080
- 启动后看到如下界面
- agent 加载如下,将agent-dist整体拷贝到一个目录进行加载,里面的结构请不要进行变动,不要单独拷贝一个jar java -jar -javaagent:/xxx/agent-dist/cubic-agent.jar yyy.jar
- 启动代理服务 ,用于连接agent 和web java -jar cubic-proxy.jar
- 访问web ui localhost:6080 进入默认页面,输入ip 和 agentId(id 第一次随意输入),点击connect 进入命令交互模式
- 命令分为两部分,输入1 基础命令, 3位arthas 命令,输入1 然后输入help 可查看帮助
- 使用search 命令来查询我们项目配置的agent, 比如在agent config 我们配置了参数 agent.service_name = cubic,则进行查询并获取到应用的agentId(如果使用quick_start启动的,因为增加了-Dcubic.agent.service_name=cubic-proxy ,所以我们可以使用cubic-proxy查询ID )
- 然后将agentId 填入上面的输入框 点击connect 按钮重新加载,则进入当前应用的命令模式,输入3,切换到arthas 命令,就可以使用了
3.3 Cubic问题
按照快速接入的方案,我们也快速的看到了Cubic的效果。但是这个做到了一站式分布式集成,解决了需要去机器,在机器里去看系统的运行情况问题。但是还没有解决我们的容器部署的问题,我想容器启动后自动集成到该平台,就可以看到数据了。
四 Kubernates下如何接入Cubic
4.1 基础镜像制作
大家看到我们要使用Cubic的时候需要一些文件,这些文件在代码里已经有了,放到了agent-dist下
4.1.1 拷agent-dist相关文件
为了更好的发布,我增加了一个shell文件,start.sh
java
#!/bin/sh
java -Xms512m -Xmx1024m -Xss256k -Dnacos.url=$1 -Dnacos.namespace=$2 -Dspring.profiles.active=$3 -javaagent:/opt/agent-dist/cubic-agent.jar -Dcubic.agent.service_name=$4 -jar /opt/app.jar
我传了一些我们项目的参数 重要的后面的参数-javaagent:/opt/agent-dist/cubic-agent.jar -Dcubic.agent.service_name=$4
,用来集成的
4.1.2 修改配置文件
注意该步改的是cubic的服务地址。我这里把部署到容器里暴露是jjb-saas-cubic,所以是可以根据这个访问的
4.1.3 修改Dockerfile
docerfile
FROM registry.cn-hangzhou.aliyuncs.com/yyjx/openjdk:8-jdk-alpine
RUN mkdir /opt/agent-dist && mkdir /opt/agent-dist/arthas && mkdir /opt/agent-dist/config && mkdir /opt/agent-dist/arthas/async-profiler
COPY agent-dist/arthas/async-profiler/libasyncProfiler-linux-aarch64.so /opt/agent-dist/arthas/async-profiler
COPY agent-dist/arthas/async-profiler/libasyncProfiler-linux-arm.so /opt/agent-dist/arthas/async-profiler
COPY agent-dist/arthas/async-profiler/libasyncProfiler-linux-x64.so /opt/agent-dist/arthas/async-profiler
COPY agent-dist/arthas/async-profiler/libasyncProfiler-mac-x64.so /opt/agent-dist/arthas/async-profiler
COPY agent-dist/arthas/arthas.properties /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-agent.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-boot.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-client.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-core.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-demo.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/arthas-spy.jar /opt/agent-dist/arthas
COPY agent-dist/arthas/as.sh /opt/agent-dist/arthas
COPY agent-dist/arthas/as.bat /opt/agent-dist/arthas
COPY agent-dist/arthas/as-service.bat /opt/agent-dist/arthas
COPY agent-dist/arthas/install-local.sh /opt/agent-dist/arthas
COPY agent-dist/arthas/logback.xml /opt/agent-dist/arthas
COPY agent-dist/config/agent.config /opt/agent-dist/config
COPY agent-dist/cubic-agent.jar /opt/agent-dist
COPY agent-dist/cubic-agent-core.jar /opt/agent-dist
COPY agent-dist/apm-toolkit-logback-1.x-8.7.0.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/ext
COPY agent-dist/tools.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/ext
COPY agent-dist/start.sh /opt
4.1.4 打基础镜像
我是通过jekins打的,并上传到了我们的镜像仓库
ini
#镜像仓库
img_reg="192.168.1.100:5000"
#镜像空间
img_ns="dev-dragon"
docker build -t ${img_reg}/${img_ns}/$JOB_NAME:latest .
docker login --username=1111@q.com jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com --password='password
docker push ${img_reg}/${img_ns}/$JOB_NAME:latest
这样我的基础镜像完成了,后面发布的微服务直接使用该镜像即可。
五 发布cubic服务端
为了能更好的发布,我将cubic的源码下载下来放到我新建的项目里
然后我再jekins建发布任务,发布到容器里。这主要是运维的工作。不做详细 发布完成后,可以在容器里看到起好的服务
点进去可以看到正常的日志
说明该服务启动正常。我这里用的是rancher。
启动完成后还有最关键的一步,就是开放服务能内部访问的端口,除了服务本身的端口外,还有两个端口,11900和11901
最后检查下是否确实成功
六 启动其他微服务
cubic是无缝接入的,所以代码无需要做更多的改造,正常写代码就行了。
主要还是在发布上面做文章
6.1 使用基础镜像
我这里之前已经打好了镜像并上传到了我的镜像仓库 ${img_reg}/${img_ns}/dev-dragon-jjb-saas-baseimage:latest
6.2 启动的时候用之前写sh
shell
RUN chmod +x /opt/start.sh
ENTRYPOINT [ "sh","-c","/opt/start.sh ${nacos_url} ${nacos_namespace} ${active} ${service_name}"]
好了,我是没有改我们的代码吧,并且开发也无需关心,我已经把他集成到了我们的cubic,这个时候再去启动我们的服务
服务启动成功后就可以去后台检查是否接入了
七 测试接入情况
登录cubic的后端
我们已经看到了接入的服务,而且心跳是正常的,点击后面的进入实例
就可以看到该服务的发布情况了
我们主要还是来看Arthas是否可以正常使用,点击签前面的Arthas工具
看样子是已经连接成功了,那么再来测试下是否可以正常监控,我们来输入命令dashboard
已经正常显示了,Kubernates下如何接入Cubic一站式监控平台已经成功。