用arthas调试xwiki性能问题

由于xwiki在线上运行出现性能问题,于是在本地利用docker搭建xwiki环境,并导入与线上同等量的数据,使用阿里巴巴的开源工具arthas进行调试

构建含有arthas的xwiki-docker镜像

arthas调试工具与被调试的程序需要运行在同一个环境下,因此需要在xwiki镜像中载入arthas,arthas的运行需要在jdk环境下,而xwiki的基础镜像是jre环境,jre环境没有需要运行arthas的tools.jar包,最终的解决办法是下载完整的jdk包,直接用./jdk1.8.0_201/bin/java -jar arthas-boot.jar的方式启动arthas,还可以查看java进程pid,指定pid运行

1
2
ps -A
java -jar arthas-boot.jar 1

官方下载jdk包

Java SE Development Kit 8 Downloads

使用dockerfile构建镜像

1
2
3
4
5
6
FROM registry.saas.hand-china.com/hitoa/xwiki:10.4-mysql-tomcat-0.14.0
COPY jdk-8u201-linux-x64.tar.gz /jdk-8u201-linux-x64.tar.gz
RUN tar --extract --file /jdk-8u201-linux-x64.tar.gz; \
rm /jdk-8u201-linux-x64.tar.gz; \
java -version; \
wget https://alibaba.github.io/arthas/arthas-boot.jar

在dockerfile所在目录下运行命令

1
docker build -t hsqyz520/wiki-arthas:2.0 .

上传镜像到docker hub

先在dockerHub注册一个账号

1
2
3
4
5
6
# 登录hub
docker login
# 查看镜像信息
docker inspect hsqyz520/wiki-arthas:2.0
# 推镜像到hub
docker push hsqyz520/wiki-arthas:2.0

利用docker-compose启动xwiki

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
version: '2'
networks:
bridge:
driver: bridge
services:
web:
image: "wiki-arthas:2.0"
container_name: xwiki-mysql-tomcat-web
depends_on:
- db
ports:
- "7080:8080"
environment:
- DB_PORT=3306
- DB_USER=xwiki
- DB_PASSWORD=xwiki
- DB_HOST=xwiki-mysql-db
- JAVA_OPTS=-Xmx3072m
//...省略部分链接choerodon地址
volumes:
- ./xwiki-data:/usr/local/xwiki
networks:
- bridge
db:
image: "registry.saas.hand-china.com/tools/mysql:5.7.17"
container_name: xwiki-mysql-db
command:
- mysqld
- --character-set-server=utf8
- --collation-server=utf8_general_ci
volumes:
- ./xwiki.cnf:/etc/mysql/conf.d/xwiki.cnf
- ./mysql-data:/var/lib/mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=xwiki
- MYSQL_USER=xwiki
- MYSQL_PASSWORD=xwiki
- MYSQL_DATABASE=xwiki
networks:
- bridge
volumes:
mysql-data: {}
xwiki-data: {}

执行以下命令

1
2
3
4
5
6
7
8
# 启动
docker-compose up
# 关闭并移除卷
docker-compose down -v
# 查看所有容器
docker ps -a
# 删除所有未使用的容器
docker rm $(docker ps -a -q)

若想清空wiki数据,启动前先删除以下文件夹

image

若想关闭xwiki的choerodon认证,在xwiki-data/data/xwiki.cfg中注释掉认证类

image

数据导入

由于大数据量的sql在navicat中运行容易失败,这种情况下应该用命令行进入到mysql中执行sql源文件

1
2
3
4
5
6
7
8
# 进入容器
docker exec -it ${mysql容器Id} bash
# 进入mysql
mysql -u ${数据库用户名} -p
# 切换数据库
use ${数据库名}
# 运行sql文件
source ${文件位置/文件名}

启动监听

在用docker-compose启动容器运行wiki后,在xwiki的容器中启动arthas监听wiki

1
docker exec -it ${xwiki容器Id} bash -c "./jdk1.8.0_201/bin/java -jar arthas-boot.jar"

Arthas命令的使用

1
2
3
4
# 查看方法耗时
trace com.xpn.xwiki.web.ViewAction action
# 查看方法调用链路
stack com.xpn.xwiki.web.ViewAction action

调试结果

这次调试的主要目标是刷新页面,通过定位代码,所有的请求都会经过XWikiAction.execute()方法

1
trace com.xpn.xwiki.web.XWikiAction execute

image
image

主要耗时在parseTemplate()解析模版上,通过调试发现,xwiki采用velocity模板来渲染前端的,view.vm下面有许多子vm,下面覆盖了许多层级的vm,这样导致一个页面要渲染的模版成倍数量,可能这里就是xwiki刷新慢的原因,因此我考虑了是否可以给velocity增加缓存,我参考了velocity配置优化,于是我在配置中添加velocity.properties = file.resource.loader.cache = true

image

将刷新页面的接口取到postman去压力测试,以便观察结果,需要设置Cookie,测试结果速度似乎有从平均600~800ms缩减至500~700ms,结果不是很明显

image

后面我到XWiki官方论坛提问,作者回复的大概意思是在XWiki中使用Velocity的方式,缓存弊大于利,后续版本会对这一块进行优化

image

至此后面只能考虑在渲染这一方面每个层级引入并发Stream,以及确定是否数据库sql的问题

idea远程监听调试tomcat中运行的服务

更改tomcat配置

打开/usr/local/tomcat/bin/catalina.sh,增加如下配置,开放端口5005

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,suspend=n,server=y"

# if [ "$1" = "jpda" ] ; then
# if [ -z "$JPDA_TRANSPORT" ]; then
# JPDA_TRANSPORT="dt_socket"
# fi
# if [ -z "$JPDA_ADDRESS" ]; then
# JPDA_ADDRESS="localhost:5005"
# fi
# if [ -z "$JPDA_SUSPEND" ]; then
# JPDA_SUSPEND="n"
# fi
# if [ -z "$JPDA_OPTS" ]; then
# JPDA_OPTS="-agentlib:jdwp=transport=$JPDA_TRANSPORT,address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND"
# fi
# CATALINA_OPTS="$JPDA_OPTS $CATALINA_OPTS"
# shift
# fi

docker-compose绑定卷和开放端口

1
2
3
4
5
6
7
8
services:
...
ports:
- "7080:8080"
- "5005:5005"
volumes:
- ./catalina.sh:/usr/local/tomcat/bin/catalina.sh
...

idea配置remote监听debug

image

参考文献