1.性能压测框架
1.1SpringBoot的云端部署
1.maven打包
2.上传centos
3.外挂配置文件
每个项目从开发到测试再到上线所需要的各种环境是不同的,这就需要维护相应的配置文件,比如properties或yml文件。有了配置文件后就要考虑如何与应用进行集成。
对于云环境来讲,项目发布需要打成镜像,再进行部署。如果把spring boot项目连同配置文件(变量)一起打入JAR包并不是一个很好的选择,我们的做法是JAR不包含配置文件,待启动镜像和JAR时将配置文件动态赋值给JAR包。
对于Spring Boot项目,有两种做法可以实现该目的:
- --spring.config.location
java -jar miaosha-1.0-SNAPSHOT.jar --spring.config.location=/usr/local/www/miaosha/application.properties
要特别注意的是,该命令指定的配置文件会使项目默认的application.properties或application.yml文件失效,换句话说该命令会用指定的配置文件替换application.properties或application.yml文件。
- --spring.config.additional-location
java -jar miaosha-1.0-SNAPSHOT.jar --spring.config.additional-location=/usr/local/www/miaosha/application.properties
顾名思义,该命令用于追加配置文件。原有的application.properties或application.yml文件均有效。
4.编写deploy脚本启动
为了避免启动服务后,关闭终端导致服务停止,我们采用依赖脚本处理deploy.sh进行处理。
nohup java -Xms400m -Xmx400m -XX:NewSize=200m -XX:MaxNewSize=200m -jar miaosha.jar --spring.config.additional-location=/usr/local/www/java/miaosha/application.properties
当前deploy.sh文件目录下,chmod -R 777 *
修改可执行权限,然后启动脚本./deploy.sh &
执行完会提示:nohup
:忽略输入并把输出追加到 nohup.out”,可以使用tail -200f ./nohup.out
查看服务启动的日志输出
注:
nohup:LINUX命令用法,不挂断地运行命令
-Xms400m:初始jvm堆栈大小
-Xmx400m:最大jvm堆栈大小
-XX:NewSize=200m:初始jvm新生代大小
-XX:MaxNewSize=200m:最大新生代大小
java -jar XXX.jar &
命令结尾没有&
,则变成 java -jar XXX.jar
,表示在当前ssh窗口,可按CTRL + C打断程序运行,或者直接关闭窗口,则程序直接退出
命令结尾添加&
,则变成 java -jar XXX.jar &
,表示在当窗口关闭时,程序才会中止运行。&
代表让该命令在后台执行。
nohup java -jar XXX.jar > Log.log &
或者
nohup java -jar XXX.jar >> Log.log &
命令 nohup java -jar XXX.jar &
部分,表示不挂断运行命令,当账户退出或终端关闭时,程序仍然运行。注意,该作业的所有输出被重定向到nohup.out的文件中。
命令 nohup java -jar XXX.jar > Log.log &
部分,表示不挂断运行命令,当账户退出或终端关闭时,程序仍然运行,并且该作业的所有输出被重定向到Log.log的文件中。“ > Log.log ” 该命令就是指定日志输出的文件。
">>"表示将输出以追加的方式重定向到Log.log中。
nohup java -jar XXX.jar > Log.log 2>&1 &
或者
nohup java -jar XXX.jar >> Log.log 2>&1 &
或者
nohup java -jar XXX.jar > /dev/null 2>&1 &
标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
屏蔽输出,起到禁止输出作用:/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
“> Log.log 2>&1” :表示将 stdout 和 stderr 合并后重定向到 Log.log
注:
输出之后,可以使用“jobs”查看一下后台运行的任务。
1.2使用JMeter发现性能问题
- 线程组
- Http请求
- 查看结果树
- 聚合报告
1.3 发现容量问题
1. 在安装完jmeter之后,对项目进行性能压测,发现server端的并发线程数上不去;
2. 采用 pstree -p 进程号|wc -l 查看线程数;采用top -H查看机器性能;
[root@localhost ~]# pstree -p 127762 | wc -l
218
[root@localhost ~]# top -H
cpu使用飙升,load average > 5
- 表象:单机cpu使用率增高,memory占用增加,网路带宽使用增加
- cpu us :用户空间的cpu使用情况(用户层代码)
- cpu y:内核空间的cpu使用情况(系统调用)
- load average:1.5,15分钟load平均值,跟着核数系数,0代表通常,1代表打满 1+代表等待阻塞
- memory:free空闲时间,used使用内存
把CPU比喻成一条(单核)马路,进程任务比喻成马路上跑着的汽车,Load则表示马路的繁忙程度:
Load < 0.7时:系统很闲,马路上没什么车,要考虑多部署一些服务
0.7 < Load < 1时:系统状态不错,马路可以轻松应对
Load == 1时:系统马上要处理不多来了,赶紧找一下原因
Load > 5时:马路已经非常繁忙了,进入马路的每辆汽车都要无法很快的运行
2.Tomcat性能优化
查看SpringBoot配置
- spring-configuration-metadata.json文件下
- 常看各个节点的配置
2.1Tomcat的作用
Tomcat是一个轻量级应用服务器,是支持运行Servlet/JSP应用程序的容器,运行在jvm上,绑定IP地址并监听TCP端口;运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能;
在做web项目时多数需要http协议,基于请求和响应,servlet就是在服务器端运行的java程序,通过配置文件拦截你的请求,并进行相应处理,然后展示给你相应界面;Tomcat就可以创建servlet,去运行web项目,相当于一个应用服务器,作为serlet的容器;
2.2Tomcat的调用过程
tomcat要能够同时接收多个客户端发来的请求,那么就需要多线程;
tomcat想要调用servlet就是得到这个servlet对象和类所在地址的映射关系;
tomcat本身并不知道客户端会访问哪一个servlet,所以tomcat必须要能够动态的去调用servlet对象,那么就需要用到java的反射机制;
定位到具体的servlet并调用get或post方法并响应客户端;
2.3Tomcat默认内嵌配置
打开Springboot项目中,双击shift,搜索spring-configuration-metadata.json文件,可以查看各个节点的配置;
tomcat默认参数是为开发环境制定,而非适合生产环境,尤其是内存和线程的配置,默认都很低,容易成为性能瓶颈;
server.tomcat.accept-count:等待队列长度。默认100;
server.tomcat.max-connections:最大可被连接数,默认10000
server.tomcat.max-threads:最大工作线程数,默认200
server.tomcat.min-spare-threads:最小线程数,默认10
默认配置下,连接超过10000后出现拒绝连接情况;
默认配置下,触发的请求超过200+100后拒绝处理;
2.4定制化内嵌Tomcat开发
keepAliveTimeout:表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且为超过过期时间,则该连接将一直保持。
maxKeepAliveRequests:表示该连接最大支持的请求数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)。
使用WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>定制化内嵌tomcat配置
@Component
public class WebServerConfiguration implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
((TomcatServletWebServerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
/**
* 定制化keepalivetimeout。设置30秒内没有请求,则服务端自动断开keepalive链接
*/
protocol.setKeepAliveTimeout(30000);
/**
* 当客户端发送超过10000个请求则自动断开keepalive链接
*/
protocol.setMaxKeepAliveRequests(10000);
}
});
}
}
为什么要设置keepAliveTimeout和maxKeepAliveRequests?
1.防止连接长时间占用访问资源,以免导致其它客户端请求无法建立连接。
2.防止DDOS攻击 以免导致服务器拥塞而无法对外提供正常服务
2.5Tomcat调优
利用缓存和压缩
对于静态页面最好是能够缓存起来,这样就不必每次从磁盘上读。这里我们采用了 Nginx 作为缓存服务器,将图片、css、js 文件都进行了缓存,有效的减少了后端 tomcat 的访问。
可以用 gzip 压缩,其实很多图片也可以用图像处理工具预先进行压缩,找到一个平衡点可以让画质损失很小而文件可以减小很多;
采用集群,实现横向扩展,那么组建 tomcat 集群是有效提升性能;
内存调优:设置JVM的一些参数
-Xmx3550m -最大可用内存;
-Xms3550m -JVM促使内存为3550m;
-Xmn2g 年轻代大小为2G;
-Xss128k -设置每个线程的堆栈大小;
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)设置为4,则年轻代与年老代所占比值为1:4;
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4;
-XX:MaxPermSize=16m:设置持久代大小为16m;
-XX:MaxTenuringThreshold=0:设置垃圾最大年龄;
Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。
以上三个参数的设置都是默认以Byte为单位的,也可以在数字后面添加[k/K]或者[m/M]来表示KB或者MB。而且,超过机器本身的内存大小也是不可以的,否则就等着机器变慢而不是程序变慢了。
发现容量问题
单个Web容器有上限;
线程数量:4核cpu 8G内存单进程调度线程数800-1000以上后即花费巨大的时间在cpu调度上;
等待队列长度:队列做缓冲池用,但也不能无限长,消耗内存,出队入队也耗cpu;
server.tomcat.accept-count=1000
server.tomcat.max-threads=800
server.tomcat.min-spare-threads=100
Mysql数据库QPS容量问题;
主键查询:千万级别数据 1-10毫秒
唯一索引查询:千万级别数据=10-100毫秒
非唯一索引查询:千万级别数据=100-1000毫秒
无索引:百万条数据=1000毫秒+
Mysql数据库TPS容量问题 ;
非插入更新删除操作:同查询
插入操作:1W~10W tps(依赖配置优化,后续讲解)