Java web应用性能分析服务端慢之Nginx慢

news2025/3/9 23:10:18

        一般Nginx作为整个应用的入口,即做静态服务器,也做负载均衡、反向代理;同时也因为位置靠前,还可以通过Nginx对于访问的IP、并发数进行相应的限制。在Java web应用性能分析中,Nginx是重要环节,Nginx的性能也影响整个应用。

Nginx原理

        下面我们看一下Nginx的整体架构

        Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处理网络请求与响应。

        master进程主要用来管理worker进程,具体包括如下4个主要功能:

  1. 接收来自外界的信号。
  2. 向各worker进程发送信号。
  3. 监控woker进程的运行状态。
  4. 当woker进程退出后(异常情况下),会自动重新启动新的woker进程。

woker进程主要用来处理基本的网络事件:

  1. 多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
  2. 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
  3. worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。同时,nginx为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。

Ngnix 是如何实现高性能的?

1.事件驱动模型

        基于异步及非阻塞的事件驱动模型,可以说是 Nginx 得以获得高并发、高性能的关键因素。这一点上和 Netty 类似,底层都是使用的 BSD kqueue、Linux epoll 及 Solaris event ports。

2.多进程机制

        使用多进程的好处有两点:

  1. 进程之间不共享资源,不需要加锁,减少了使用锁对性能造成的影响,同时降低编程的复杂度,降低开发成本。
  2. 采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master 进程则很快启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。
3.内存池

        为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。

4.模块化设计

        高度模块化的设计是 Nginx 的架构基础。Openresty 就是在 Nginx 上引入了 lua 等第三方模块,使得扩展更加方便了。

Nginx调优

        在这里我们Nginx调优主要包括:性能调优、安全调优、以及资源管理。

        请求响应模型过程中的TCP网络消耗

1.worker工作进程调整:绑定CPU

        查看CPU核心数

user  nginx nginx;                 # 启动Nginx⼯作进程的⽤⼾和组
worker_processes  [number | auto]; # 启动Nginx⼯作进程的数量
worker_cpu_affinity 00000001 00000010 00000100 00001000;
# 将Nginx⼯作进程绑定到指定的CPU核⼼,默认Nginx是不进⾏进程绑定的,
# 绑定并不是意味着当前nginx进程独 占以⼀核⼼CPU,但是可以保证此进程不会运⾏在其他核⼼上,
# 这就极⼤减少了nginx的⼯作进程在不同的cpu核 ⼼上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,
#因此可以有效的提升nginx服务器的性 能。 此处CPU有四颗核心。也可写成:
#worker_cpu_affinity 0001 0010 0100 1000;

#cpu的亲和能偶使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不#断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。
#每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相#等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗
  1. 一个master Process管理多个worker process,也就是说Nginx采用的是多进程结构,而不是多线程结构
  2. 当client发出请求(任务)时,master Process会通知管理的worker process
  3. worker process开始争抢任务,争抢到的worker process会开启连接,完成任务
  4. 每个worker都是一个独立的进程,每个进程里只有一个主线程
  5. Nginx采用了IO多路复用机制(需要在Linux环境),使用IO多路复用机制,是Nginx在使用为数不多的worker process就可以实现高并发的关键

2.事件处理模型和worker工作进程数

work_connections表示每个worker(子进程)可以创建多少个连接,
默认:work_connections:1024
最大:work_connections:65535
同时要根据系统的最大打开文件数来调整

系统的最大打开文件数>= worker_connections*worker_process
根据系统的最大打开文件数来调整,worker_connections 进程连接数量要小于等于系统的最大打开文件数
worker_connections 进程连接数量真实数量= worker_connections * worker_process

查看系统的最大打开文件数:

ulimit -a | grep "open files"

其他系统内核调整

# 配置文件/etc/sysctl.conf
sysctl -w net.ipv4.tcp_syncookies=1 # 防止一个套接字在有过多试图连接到时引起过载
sysctl -w net.core.somaxconn=1024 # 默认128,连接队列
sysctl -w net.ipv4.tcp_fin_timeout=10 # timewait 的超时时间
sysctl -w net.ipv4.tcp_tw_reuse=1 # os 直接使用 timewait的连接
sysctl -w net.ipv4.tcp_tw_recycle=0 # 回收禁用

# /etc/security/limits.conf
*               hard    nofile            204800
*               soft    nofile             204800
*               soft    core             unlimited
*               soft    stack             204800
events {
    worker_connections  1024; # 每个工作进程的最大连接数,默认值512
    multi_accept on;  # 尽可能多地接受新的连接
    use epoll;        # 选择合适的事件模型,例如epoll或kqueue
}


Nginx 事件模型对比
Nginx 的事件模型主要有两种:select、poll、epoll、kqueue、devpoll、eventport。

select:select 模型是最早期的,它在大多数操作系统上都有相同的表现。它的主要缺点是,每次调用 select 时,都需要传递所有的文件描述符集合,这使得 select 的系统调用在大量并发连接的情况下效率非常低。

poll:poll 模型在实现上是比 select 更先进的模型,它没有文件描述符的数量限制。但是,它的性能仍然不如 epoll。

epoll:epoll 是 Linux 下的一个高效的事件通知模型,它只有在有事件通知时才会唤醒进程,而且它是边缘触发,而 select 和 poll 是水平触发。

kqueue:kqueue 是 BSD 系统(包括 macOS)下的一个高效事件通知模型,它也是边缘触发。

devpoll:devpoll 是 Solaris 下的一个事件通知模型。

eventport:eventport 是 Solaris 和部分其他操作系统下的一个事件通知模型,它是边缘触发,而且是线程安全的。

在 Nginx 中,可以通过 --with-select_module、--without-select_module、--with-poll_module、--without-poll_module、--with-epoll_module、--with-kqueue_module、--with-devpoll_module 和 --with-eventport_module 这些编译参数来启用或禁用对应的事件模型。

例如,如果你想要在 Nginx 中使用 epoll 事件模型,你可以在编译 Nginx 时添加 --with-epoll_module 参数。

./configure --with-epoll_module
make
make install
在实际的生产环境中,通常会根据操作系统的不同选择不同的事件模型。例如,在 Linux 系统上,通常会选择 epoll,而在 Solaris 系统上,则会选择 devpoll 或 eventport。

注意:在 Nginx 中,默认情况下会自动选择最适合当前操作系统的事件模型。
3.开启gzip压缩

        启用Nginx的gzip模块可以压缩响应内容,减少网络传输数据量,提高性能。可以使用gzip on指令启用压缩功能。


gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";

释义如下:
这是用来配置 gzip 压缩的。gzip 是一种用于压缩文件的压缩程序,在 Web 开发中被广泛应用,主要用于压缩 Web 应用的静态资源以减少传输流量,提高网页的加载速度。
gzip on;:启用 gzip 压缩。
gzip_min_length 1k;:指定压缩文件的最小长度,只有文件大小超过 1KB 时才启用压缩。
gzip_comp_level 9;:指定压缩级别。级别越高,压缩效率越高,但会占用更多的 CPU 资源和时间。一般建议将级别设置为 6-9 之间。(这里根据你的服务器来定)
gzip_types:指定需要压缩的文件类型。在这里,配置文件将 text、application 和 image 类型的文件压缩。一般来说,压缩的文件类型应该是纯文本格式或可压缩的二进制文件。
gzip_vary on;:使用 Vary 头来指示代理服务器或浏览器缓存已压缩的版本。这样,更高效的压缩格式可以分别缓存,并在请求时正确地使用。
gzip_disable "MSIE [1-6].";:禁用 gzip 压缩的浏览器,例如早期版本的 Internet Explorer。这些浏览器对于压缩格式的支持很差,因此禁用压缩可以避免出现问题。(这一步避免版本低浏览器访问网页出现问题)

4.配置静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
}
5.限制连接速率
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
    ...
    location / {
        limit_req zone=mylimit;
        ...
    }
}
6.保持连接时间

keepalive_timeout 65;

        keepalive就是建立一下长连接,这个timeout就是,当浏览器建立一个连接之后,这个连接最长能存在多少事件不给他关闭,这个65也不是说建立65s连接后就直接关闭,而是一个活跃事件,就是第一次请求和下一次请求都会刷新这个65s,再65s内没有再请求数据才会真的关闭这个连接,所以这个事件也不应该太长,60左右也差不多了。
 

7.配置超时时间

client_body_timeout 12;
send_timeout 10;

- keepalived_timeout :客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接。
- tcp_nodelay:也是防止网络阻塞,不过要包涵在keepalived参数才有效。
- client_header_buffer_size 4k:客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过 1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
- open_file_cache max=102400 inactive=20s :这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
- open_file_cache_valid 30s:这个是指多长时间检查一次缓存的有效信息。
- open_file_cache_min_uses 1 :open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
- client_header_timeout :设置请求头的超时时间。我们也可以把这个设置低些,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误。
- client_body_timeout设置请求体的超时时间。我们也可以把这个设置低些,超过这个时间没有发送任何数据,和上面一样的错误提示。
- reset_timeout_connection :告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。
- send_timeout :响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接。
- server_tokens :并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。
- client_max_body_size:上传文件大小限制。

proxy_connect_timeout 90; #后端服务器连接的超时时间,发起握手等候响应超时时间
proxy_send_timeout 90;  #后端服务器数据回传时间,就是在规定时间内后端服务器必须传完所有的数据
proxy_read_timeout 90;  #连接成功后,等候后端服务器响应时间,其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间,页面等待服务器响应时间)
proxy_buffers 4 32k;  #4是数量 32k是大小 该指令设置缓存区的大小和数量,从被代理的后端服务器取得的第一部分响应内容,会放置到这里,默认情况下,一个缓存区的大小等于内存页面大小,可能是4k也可能是8k取决于平台
proxy_busy_buffers_size 64k; #nginx在收到服务器数据后,会分配一部分缓冲区来用于向客户端发送数据,这个缓存区大小由proxy_busy_buffers_size决定的。大小通常是proxy_buffers单位大小的两倍,官网默认是8k/16k。



keepalive_timeout 60;
keepalive_requests 100;
tcp_nodelay on;
client_header_buffer_size 4k;
open_file_cache max=102400 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
client_header_timeout 15;
client_body_timeout 15;
reset_timedout_connection on;
send_timeout 15;
server_tokens off;
client_max_body_size 10m;

这两个配置参数是用来设置服务器的 keepalive 功能的。
keepalive_timeout: 这个参数指定了一个已经建立的连接在没有活动(无数据传输)时保持的时间长度。对于每个连接,如果超过 keepalive_timeout 时间没有数据传输,则服务器会关闭该连接。默认值通常为 75 秒。较小的值可以确保连接及时释放,但会增加连接关闭和重新建立的频率;较大的值可以减少连接关闭和重新建立的频率,但可能会导致长时间的闲置连接占用服务器资源。
keepalive_requests: 这个参数定义了一个 keepalive 连接上最多能够处理的请求次数。当一个 keepalive 连接处理了 keepalive_requests 次请求之后,服务器会关闭该连接。默认值通常为 100。较大的值可以减少连接的关闭和重新建立,但在某些情况下可能会占用过多的服务器资源。
8.启用TCP缓冲

        通过调整tcp_nodelay和tcp_nopush指令可以启用TCP缓冲,从而提高性能。这些指令可以确保Nginx等待足够的数据量再发送给客户端,从而减少TCP连接的数量,提高传输效率。

9.配置缓存

        启用Nginx的缓存可以显著提高性能。可以使用proxy_cache_path指令在Nginx中配置缓存目录。启用缓存后,Nginx会在第一次请求时将响应存储在缓存中,以便在后续请求中快速提供响应。

        往nginx.conf 的 http内容段落中加入

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

释义如下:

/path/to/cache 是指定的缓存存储路径。

levels=1:2 指定了文件系统中缓存目录的层级结构,这里是一级目录和两级子目录。

keys_zone=my_cache:10m 定义了一个名为 my_cache 的缓存区域,大小为 10 兆字节。

max_size=10g 指定了缓存最大可使用的空间大小为 10 GB。

inactive=60m 表示缓存文件在60m时间内没有被访问时,会被视为不活动,并有可能被清理掉。

10.开启高效传输模式
http {
  include mime.types;
  default_type application/octet-stream;
  ……

  sendfile on;
  tcp_nopush on;
  ……
}
- Include mime.types :媒体类型,include 只是一个在当前文件中包含另一个文件内容的指令。
- default_type application/octet-stream :默认媒体类型足够。
- sendfile on:开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
- tcp_nopush on:必须在sendfile开启模式才有效,防止网路阻塞,积极的减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送。)

11.启用HTTPS

        启用Nginx的HTTP2模块可以提高性能,因为HTTP2使用多路复用技术,可以同时发送多个请求和响应,从而提高网络传输效率。可以使用http2 on指令启用HTTP2。

12.调整缓冲区

        可以通过调整Nginx的缓冲区大小来提高性能。可以使用client_body_buffer_size、client_header_buffer_size和large_client_header_buffers等指令调整缓冲区大小。

        总的来说,Nginx性能调优需要结合服务器的硬件配置、网络环境和预期的并发连接数等因素进行综合考虑。

13.设置完整的日志格式和路径

        在后期问题排查过程中,配置完整的日志,可以快速协助定位问题。

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';
 
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;

14.设置Nginx监控

        Nginx 提供了一个状态页面,可以用来监控 Nginx 的运行状态。为了使用这个状态页面,你需要在 Nginx 配置中启用 stub_status 模块。

        stub_status模块参数可以用来查看Nginx的一些状态信息如连接数、请求数统计等,需要安装好相应的模块stub_status才支持配置,安装时需要指定–with-http_stub_status_module,

        比如:./configure --prefix=/usr/local/nginx  --with-http_stub_status_module
 

        以下是一个配置示例,它在 server 块中添加了一个 location 用于 Nginx 状态页面:

server {
    listen 80;
    server_name localhost;
 
    location /nginx_status {
        stub_status on;          # 开启状态页面
        access_log   off;       # 不记录访问nginx状态的日志
        allow 127.0.0.1;       # 只允许本地访问
        deny all;              # 拒绝其他IP访问
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1617924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMvc(2)RequestMapping注解

RequestMapping注解 1 、RequestMapping的作用2、RequestMapping的出现位置3、类上与方法上结合使用4、RequestMapping注解的value属性4.1 value属性的使用4.2 Ant风格的value4.3 value中的占位符(重点) 5、RequestMapping注解的method属性5.2衍生Mappin…

VsCode一直连接不上 timed out

前言 前段时间用VsCode连接远程服务器,正常操作后总是连接不上,折磨了半个多小时,后面才知道原来是服务器设置的问题,故记录一下,防止后面的小伙伴也踩坑。 我使用的是阿里云服务器,如果是使用其他平台服务…

第十四章大数据和数据科学4分

14.1 引言 14.1.3 科学理念 1.数据科学 数据科学将数据挖掘、统计分析和机器学习与数据集成整合,结合数据建模能力,去构建预测模型、探索数据内容模式。 数据科学依赖于: 1)丰富的数据源。具有能够展示隐藏在组织或客户行为中不…

提升效率!微信自动统计数据报表,轻松实现!

在数字化时代,提高工作效率是每个人的追求。下面就给大家分享一个能够自动统计微信号运营数据的神器——个微管理系统,让大家无需手动整理和计算,提高工作效率! 1、好友统计报表 它分为通讯录好友统计、新增好友统计和删除好友统…

Linux进程地址空间及其页表

文章目录 一、引言二、Linux进程地址空间的概念1、进程地址空间定义2、进程地址空间的组成3、进程地址空间与物理内存的关系 三、页表与内存映射1、页表的定义及作用2、页表的缺页中断 三、进程的写时拷贝 一、引言 在Linux中,进程管理是其核心功能之一&#xff0c…

统一SQL 支持Oracle unpivot列转行

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库:Oracle 目标数据库:TDSQL-MySQL 操作目标 在Oracle中,可以使用unpivot将列转换成行,在TDSQL-MySQL中没有对应的功能,由…

LateX的基础学习

what can i say 在text.tex中写下 \documentclass{article} \begin{document]Hello \LaTeX. \end{document} 关闭记事本,cmd中dir保存,用latex text.tex来编译,可以命令行慢慢编译,这可以做成bat文件 为什么不直接开始在texst…

OSPF认证方式,ISIS简介,ISIS路由器类型

OSPF:转发,泛洪,丢弃

selenium‘拟人包装‘设置

1、设置header,proxy 1.1关于user-agent 输入about:version 找到user-agent: import requests # 引用requests库 from selenium import webdriver#载入浏览器驱动#header,proxy设置 optionswebdriver.ChromeOptions()#实例化浏览器参数设置options.add_argument…

clickhouse学习笔记04

ClickHouse高可用之ReplicatedMergeTree引擎介绍 ClickHouse高可用架构准备-环境说明和ZK搭建 RPM安装ClickHouse 上传我们的clickhouse rpm文件。 安装: 中途需要输入用户名和密码 可以不设置 直接回车。 启动: 查看状态: 查看端口是否占用…

【鸿蒙NEXT】web组件debug模式

官方文档 使用Devtools工具调试前端页面 打开web debug模式 webview.WebviewController.setWebDebuggingAccess(true)chrome 访问 chrome://inspect/#devices Discover network targets 中添加 localhost:9222 创建cat.sh com.coooliang.yourappbundname 为你应用的bundlen…

什么品牌的裤子好看又耐穿?夏季裤子品牌排行榜分享

男生应该怎么样去挑选合适自己的裤子,这应该是不少男士朋友选裤子时最大的疑问了。因为市面上有着不少质量不好,版型不适合亚洲人的裤子了,如果随意去选择就很容易踩雷,那么今天就给大家分享一下关于如何选择裤子的方法&#xff0…

JVM之本地方法栈和程序计数器和堆

本地方法栈 本地方法栈是为虚拟机执行本地方法时提供服务的 JNI:Java Native Interface,通过使用 Java 本地接口程序,可以确保代码在不同的平台上方便移植 不需要进行 GC,与虚拟机栈类似,也是线程私有的,…

牛客网刷题 | BC60 判断是不是字母

描述 KiKi想判断输入的字符是不是字母,请帮他编程实现。 输入描述: 多组输入,每一行输入一个字符。 输出描述: 针对每组输入,输出单独占一行,判断输入字符是否为字母,输出内容详见输出样例…

第二节课,后端登录代码 校验

一、注册逻辑 二、代码写的位置 I UserService.java 写业务逻辑的 2.1 代码1 2.1.1 注释生成 先按 /** 再按 回车 2.1.2 多补充一点 2.2 代码2 Implement method userRegister # 在这里实现用户注册的逻辑,例如将用户名和密码存储到数据库中 2.2.1 自动进入user…

企业上了财务系统,有必要再上费控系统吗?

相信很多财务人员甚至是老板肯定有这样的疑惑:企业已经有了财务系统,为什么还要上费控软件呢?为什么越大的企业越倾向使用专业费控平台来管理企业费用? 当我们在讨论这个问题的时候,首先要搞清楚,这里所说的…

OS国产化改造中LVM卷迁移指导

一、前言 因OS改造涉及LVM卷,且vg卷包含磁盘数量较多,lv中数据较大(100T左右),因此要在OS改造中确保LVM卷信息完整不丢失,保证其上数据安全尤为重要。本文旨在探讨lvm信息存储及迁移,以指导完成…

使用R语言生成频数分布表

概要 使用R语言生成频数分布表 在R语言中,可以使用freq()函数来生成频数分布表。首先,将需要分组的数据存储在一个向量中。然后,使用freq()函数将这个向量作为参数输入,即可生成频数分布表。以下是一个示例: 示例 …

ctfshow web入门 SQl注入 web185--web190

web185 这道题还有另外一个脚本就是用concat的拼接达到有数字的目的 concat(truetrue) 2 concat(true) 1 concat(true, true) 11 然后上脚本(Y4tacker这个师傅的) # Author:Y4tacker import requestsurl "http://341e93e1-a1e7-446a-b7fc-75beb…

123.Mit6.S081-实验1-Xv6 and Unix utilities

今天我们来进行Mit6.S081实验一的内容。 实验任务 一、启动xv6(难度:Easy) 获取实验室的xv6源代码并切换到util分支。 $ git clone git://g.csail.mit.edu/xv6-labs-2020 Cloning into xv6-labs-2020... ... $ cd xv6-labs-2020 $ git checkout util Branch util …