电商高并发秒杀1 Tomcat调优

1.性能压测框架

1.1SpringBoot的云端部署
1.maven打包
2.上传centos
3.外挂配置文件

每个项目从开发到测试再到上线所需要的各种环境是不同的,这就需要维护相应的配置文件,比如properties或yml文件。有了配置文件后就要考虑如何与应用进行集成。

对于云环境来讲,项目发布需要打成镜像,再进行部署。如果把spring boot项目连同配置文件(变量)一起打入JAR包并不是一个很好的选择,我们的做法是JAR不包含配置文件,待启动镜像和JAR时将配置文件动态赋值给JAR包。

对于Spring Boot项目,有两种做法可以实现该目的:

  1. --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文件。

  1. --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发现性能问题
  1. 线程组
  2. Http请求
  3. 查看结果树
  4. 聚合报告
1.3 发现容量问题
1. 在安装完jmeter之后,对项目进行性能压测,发现server端的并发线程数上不去;
image.png
2. 采用 pstree -p 进程号|wc -l 查看线程数;采用top -H查看机器性能;
[root@localhost ~]# pstree -p 127762 | wc -l
218
[root@localhost ~]# top -H

cpu使用飙升,load average > 5


image.png
  • 表象:单机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定制化内嵌tomcat配置
@Component
public class WebServerConfiguration implements WebServerFactoryCustomizer {

    @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
image.png

Mysql数据库QPS容量问题;
主键查询:千万级别数据 1-10毫秒
唯一索引查询:千万级别数据=10-100毫秒
非唯一索引查询:千万级别数据=100-1000毫秒
无索引:百万条数据=1000毫秒+

Mysql数据库TPS容量问题 ;
非插入更新删除操作:同查询
插入操作:1W~10W tps(依赖配置优化,后续讲解)

你可能感兴趣的:(电商高并发秒杀1 Tomcat调优)