tomcat和nginx性能分析和调优(二)

231 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情

不同IO模型下的性能比较

设置BIO模式

image.png 设置NIO模式

image.png 设置AIO模式

image.png

如何加大tomcat可以使用的内存

linux下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下设置:

JAVA_OPTS='-Xms[初始化内存大小] -Xmx[可以使用的最大内存]需要把这个两个参数值调大。

例如:

JAVA_OPTS='-Xms256m -Xmx512m'

window下 在系统环境下添加如上的参数也可以提高Tomcat的内存。

JAVA_OPTS -Xms256m -Xmx512m

SpringBoot项目中tomcat是内嵌的是共享内存的

Nginx

Nginx调优篇将在此篇Nginx反向代理性能调优的基础上做一个补充

Nginx架构说明

image.png

  1. nginx启动时,会先不处理网络请求,主要负责调度工作进程,也就是图示的三项:加载配置、启动工作进程及非停升级。所以,nginx启动以后,查看操作系统的进程列表,我们就能看到至少有两个nginx进程。
  2. 服务器实际处理网络请求及响应的是工作进程(worker),在类unix系统上,nginx可以配置多个worker,而每个worker进程都可以同时处理数以千计的网络请求。
  1. 模块化设计。nginx的worker,包括核心和功能性模块,核心模块负责维持一个运行循环(run-loop),执行网络请求处理的不同阶段的模块功能,如网络读写、存储读写、内容传输、外出过滤,以及将请求发往上游服务器等。而其代码的模块化设计,也使得我们可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。
  2. 事件驱动、异步及非阻塞,可以说是nginx得以获得高并发、高性能的关键因素,同时也得益于对Linux、Solaris及类BSD等操作系统内核中事件通知及I/O性能增强功能的采用,如kqueue、epoll及event ports。

什么是反向代理其与正向代理有什么区别?

正向代理的概念: 正向代理是指客户端与目标服务器之间增加一个代理服务器,客户端直接访问代理服务器,在由代理服务器访问目标服务器并返回客户端并返回 。这个过程当中客户端需要知道代理服务器地址,并配置连接。

image.png 反向代理的概念: 反向代理是指 客户端访问目标服务器,在目标服务内部有一个统一接入网关将请求转发至后端真正处理的服务器并返回结果。这个过程当中客户端不需要知道代理服务器地址,代理对客户端而言是透明的。

image.png 反向代理与正向代理的区别

正向代理反向代理
代理服务器位置客户端与服务都能连接的位置目标服务器内部
主要作用屏蔽客户端IP、集中式缓存、解决客户端不能直连服务端的问题。屏蔽服务端内部实现、负载均衡、缓存。
应用场景爬虫、翻墙、maven 的nexus 服务Nginx 、Apache负载均衡应用

配置与使用

防盗链

# 加入至指定location 即可实现
valid_referers none blocked *.zwjk.com;
 if ($invalid_referer) {
       return 403;
}

下载限速

location /download {
    limit_rate 1m; //限制每S下载速度
    limit_rate_after 30m; // 超过30 之 后在下载
}

黑名单

#封禁指定IP
deny 192.168.xx.xx;
allow 192.168.xx.xx;
#开放指定IP 段
allow 192.168.xx.xx/24;
#封禁所有
deny    all;
#开放所有
allow    all;
# 创建黑名单文件
echo 'deny 192.168.xxx.xxx;' >> balck.ip
#http 配置块中引入 黑名单文件
include       black.ip;

Nginx高速缓存

某电商平台商品详情页需要实现 700+ QPS,如何着手去做?

解决方案:

  1. 采用Ajax 动态加载 价格、广告、库存等服务
  2. 采用key value 缓存详情页主体html。

image.png 问题: 当达到500QPS 的时候很难继续压测上去。

分析原因:一个详情页html 主体达平均150 kb 那么在500QPS 已接近千M局域网宽带极限。必须减少内网通信。

基于Nginx 静态缓存的解决方案

image.png

Nginx静态缓存基本配置

一、在http元素下添加缓存区声明。

#proxy_cache_path 缓存路径
#levels 缓存层级及目录位数
#keys_zone 缓存区内存大小
#inactive 有效期
#max_size 硬盘大小
proxy_cache_path /data/nginx/cache_test levels=1:2 keys_zone=cache_test:500m inactive=20d max_size=1g;

二、为指定location 设定缓存策略。

# 指定缓存区
proxy_cache cache_luban;
#以全路径md5值做做为Key 
proxy_cache_key $host$uri$is_args$args;
#对不同的HTTP状态码设置不同的缓存时间
proxy_cache_valid 200 304 12h;

全局配置

默认配置下,什么都不修改

并发300压测5分钟查看结果

image.png 接下来做配置上的调整如下

//这次参数中的意思已经在上面的文章中提及就不做解释了,本篇文章主要是对上面文章的补充
worker_processes  auto;
worker_cpu_affinity auto;#在windows中不生效
worker_rlimit_nofile 204800;
events {
    worker_connections  102400;
}

调优后,以上配置的调优主要是针对多核cpu会有性能上的提升。

image.png

限制连接

为了方便测试查看数据,我们设置并发数为5设置限制请求数2查看结果

image.png image.png

查看nginx的日志可以发现发起了5次请求,三次直接返回了503,再看抓包工具对服务端抓包可以发现只有两次请求到达后端。

长连接配置

TCP,三次握手建立连接,四次挥手释放连接,示意图如下

image.png 通过抓包工具分析是否为长连接

image.png 通过上图可以看出,三次握手建立连接,四次挥手释放连接,nginx到服务端并不是长连接的。接下来配置长连接参数,如何配置在上文中已经有说明。

image.png

在上图中可以看出两次请求都有重新三次握手建立连接,但是没有看到四次挥手释放连接,这是因为客户端配置了长连接,服务端没有配置长连接导致的。

接下来对服务端配置长连接,tomcat中war包部署的话是默认开启的。

SpringBoot项目中默认不支持长连接需要手动配置,在上面配置tomcat的代码中修改如下代码

//同上,就添加了三句长连接的配置
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
    ((TomcatServletWebServerFactory) factory).setProtocol("org.apache.coyote.http11.Http11Nio2Protocol");
    ((TomcatServletWebServerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
            ProtocolHandler protocol = connector.getProtocolHandler();
            //开启长连接
            ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxKeepAliveRequests(-1);
            ((AbstractHttp11Protocol) connector.getProtocolHandler()).setKeepAliveTimeout(-1);
            ((AbstractHttp11Protocol) connector.getProtocolHandler()).setConnectionTimeout(20000);
            log.info("Tomcat({})  -- MaxConnection:{};MaxThreads:{};MinSpareThreads:{}", //
                     protocol.getClass().getName(), //
                     ((AbstractHttp11Protocol<?>) protocol).getMaxConnections(), //
                     ((AbstractHttp11Protocol<?>) protocol).getMaxThreads(), //
                     ((AbstractHttp11Protocol<?>) protocol).getMinSpareThreads());

        }
    });
}

配置完毕在对请求进行抓包查看

图1

image.png

图2 image.png

通过上图可以看出,第一次请求会三次握手建立连接,然后保持长连接后面的请求都没有在进行三次握手建立连接,使用同一个连接。图2中可以看到在过一段时间tcp连接断开了,长连接可以通过参数配置修改连接时间或在多少次请求后断开。

image.png 上图中配置设置允许的最大保持连接请求数为2可以看到在两个请求后断开了连接。

为什么使用长连接技术?

  • 对响应时间要求较高;
  • 服务走的是公网,客户端与服务端的TCP建立的三次握手和断开的四次挥手都需要40ms左右(真实数据包计算出来的),共需要80ms左右;
  • 每个接入方使用的IP就若干个,需要建立的请求连接有限。
  • 使用长连接技术,可以大幅减少TCP频繁握手的次数,极大提高响应时间;同时,即使使用长连接技术,也不需要消耗很多的系统资源用来缓存sockets会话信息。

总结

性能调优远不止那么简单,需要根据具体情况具体分析,排查调用链中是在那一环节出的问题,找到具体问题具体分析。