性能优化 - Nginx & Linux

性能优化 - Nginx & Linux

来自 鑫哥 [鑫哥的技术思维]2022-05-07 09:26 发表于湖北

纲要

  • Nginx 优化后的完整配置
  • Linux 内核参数优化
  • 修改最大打开文件句柄数

Nginx 优化后的完整配置

# 核心参数(其他参数大部分情况下用不到) # user USERNAME [GROUP] # 解释:指定运行nginx的worker子进程的属主和属组,其中属组可以不指定 user nginx; # worker_processes NUMBER | auto # 解释:指定nginx启动的worker子进程数量 # 【*auto:自动设置为物理CPU核心数】 worker_processes auto; # pid DIR # 解释:指定运行nginx的master主进程的pid文件存放路径 pid /opt/nginx/logs/nginx.pid; # worker_rlimit_nofile NUMBER # 解释:指定worker子进程可以打开的最大文件句柄数 # 【系统最大打开65535,每个子进程打开数乘子进程数,实际也不会超过65535】 # 这个值需要调大,最好与 ulimit -n 的值保持一致。 worker_rlimit_nofile 65535; # worker_rlimit_core SIZE # 指定worker子进程异常终止后的core文件,用于记录分析问题 worker_rlimit_core 50M; working_directory /opt/nginx/tmp;#【必须对子进程用户赋写权限】 # 解释:将每个worker子进程与CPU物理核心绑定 # 【master负责调度,worker负责处理请求】 # 【假设CPU有4个核心,某一时刻worker1获取到了CPU1的工作调度时间片,时间片过后worker1从CPU1上面撤下来,CPU1去处理其他事件,下一时刻可能是CPU2、CPU3的时间片调度到了worker1上面,那么worker1就会在其他CPU上面工作,进程与CPU的调度切换是有损耗的,worker1如果绑定了CPU1,worker1将永远等待CPU1的调度,充分利用CPU缓存】 # 【【主要作用:将每个worker子进程与特定CPU物理核心绑定,优势在于:避免同一个worker子进程在不同的CPU核心上切换,缓存失效,降低性能;其并不能真正避免进程切换(进程切换是CPU工作特性)】】 # -- worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;# 8核心,8个worker # -- worker_cpu_affinity 01 10;# 2核心,2个worker worker_cpu_affinity 0001 0010 0100 1000;# 4核心,4个worker # 解释:指定worker子进程的nice值,以调整运行nginx的优先级,通常设定为“负值”,以优先调用nginx # 【值越小越优先;nice设定范围为-20到+19】 worker_priority -20; # 指定worker子进程优雅退出时的超时时间,不管5秒内是否处理完,都强制退出 worker_shutdown_timeout 5s; # worker子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降 # 比如某些计时的操作,worker需要去获取内核时间,频繁跟内核打交道会降低性能 timer_resolution 100ms; # daemon on | off # 设定nginx的运行方式,前台还是后台,前台用户调试,后台用于生产 daemon on; events { # Nginx使用何种事件驱动模型 # 【高并发场景下,I/O多路复用使用epoll模型,提高效率】 use epoll; # 单个worker子进程能够处理的最大并发连接数,多核情况最大其实达不到65535, worker_connections 65535; # 是否打开负载均衡互斥锁,默认off(当master接收到请求时,会给每个worker发送消息去唤醒,状态为on时,则会有一个负载均衡锁,master会轮流发给每一个) accept_mutex off; } http { include mime.types; default_type application/octet-stream; #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 logs/access.log main; # 开启高效的 零拷贝技术 进行文件传输; # 这样只需要 2 次上下文切换,和 2 次数据拷贝,在内核态即可完成,由DMA进行文件搬运,不需要CPU参与 sendfile on; # 必须在sendfile开启时才有效,防止网路阻塞,减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送) tcp_nopush on; # 客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接 keepalive_timeout 60; # 防止网络阻塞 tcp_nodelay on; # 客户端请求头部的缓冲区大小,根据系统分页大小来设置,命令 getconf PAGESIZE 取得分页大小 client_header_buffer_size 4k; # 为打开文件指定缓存,默认是没有启用的,max 指缓存数量,建议和打开文件数一致,inactive 指经过多长时间文件没被请求后删除缓存 open_file_cache max=65536 inactive=30s; # 多长时间检查一次缓存的有效信息 open_file_cache_valid 30s; # open_file_cache 指令中的 inactive 参数时间内文件的最少使用次数 # 如果超过这个数字,文件描述符一直是在缓存中打开的,如果一个文件在 inactive 时间内一次没被使用,它将被移除 open_file_cache_min_uses 1; # 设置请求头的超时时间,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误 client_header_timeout 15; # 设置请求体的超时时间,超过这个时间没有发送任何数据,和上面一样的错误提示 client_body_timeout 15; # 告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间 reset_timedout_connection on; # 应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接 send_timeout 15; # 上传文件大小限制 client_max_body_size 10m; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } location /video/ { sendfile on; # 当文件大小超过8M时,启用AIP与directio aio on; directio 8m; } # HTTPS server server { # 开启http2 # http2 在底层传输做了很大的改动和优化: # 1,每个服务器只用一个连接,节省多次建立连接的时间,在TLS上效果尤为明显 # 2,加速 TLS 交付,HTTP/2 只耗时一次 TLS 握手,通过一个连接上的多路利用实现最佳性能 # 3,更安全,通过减少 TLS 的性能损失,让更多应用使用 TLS,从而让用户信息更安全 listen 443 ssl http2; server_name localhost; ## 证书部分 #ECC证书 # 256 位 ECC Key 在安全性上等同于 3072 位 RSA Key,运算速度更快,同等安全条件下,ECC 算法所需的 Key 更短,所以 ECC 证书文件体积比 RSA 证书要小一些。 ssl_certificate ecc.crt; #ECC密钥 ssl_certificate_key ecc.key; #ECC密钥 ssl_certificate cert.pem; # RSA证书 ssl_certificate_key cert.key; # RSA密钥 # TLS 握手优化 ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; keepalive_timeout 75s; keepalive_requests 100; # 支持TLSv1.3 ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5; # 开启 1.3 o-RTT ssl_early_data on; ssl_prefer_server_ciphers on; # gzip gzip on; # 压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源 gzip_comp_level 6; # 设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0 gzip_min_length 1k; # 用来指定压缩的类型,‘text/html’类型总是会被压缩。默认值: gzip_types text/html (默认不对js/css文件进行压缩) # 缩类型,匹配MIME型进行压缩,不能用通配符 text/* text/html默认已经压缩 (无论是否指定) # 设置哪压缩种文本文件可参考 conf/mime.types gzip_types text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype; # brotli:Google 推出的无损压缩算法,有以下优势: # 1,针对常见的 Web 资源内容,Brotli 的性能要比 Gzip 好 17-25%; # 2,Brotli 压缩级别为 1 时,压缩速度是最快的,而且此时压缩率比 gzip 压缩等级为 9(最高)时还要高; brotli on; brotli_comp_level 6; brotli_min_length 1k; brotli_types text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype; location / { root html; index index.html index.htm; } } }

支持 TLS1.3 和 brotli ,都需要编译时引入相应模块

cd /opt/$nginxVersion/ ./configure \ --prefix=/usr/local/nginx \ ## 编译后安装的目录位置 --with-openssl=/opt/$OpenSSLVersion \ ## 指定单独编译入 OpenSSL 的源码位置 --with-openssl-opt=enable-tls1_3 \ ## 开启 TLS 1.3 支持 --with-http_v2_module \ ## 开启 HTTP/2 --with-http_ssl_module \ ## 开启 HTTPS 支持 --with-http_gzip_static_module \ ## 开启 GZip 压缩 --add-module=/opt/ngx_brotli ## 编译入 ngx_BroTli 扩展 make && make install ## 编译并安装

Linux 内核参数优化

  • 修改文件:/etc/sysctl.conf
  • 执行 /sbin/sysctl -p,使配置生效
# 表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直接限制最大并发连接数,需根据实际情况配置 fs.file-max = 999999 # 控制系统调试内核的功能,不同的值对应不同的功能 # 0 完全禁用 sysrq 组合键 # 1 启用 sysrq 组合键的全部功能 # 2 启用控制台日志级别控制 # 4 启用键盘控制(SAK、unraw) # 8 启用进程的调试信息输出等 # 16 启用同步命令 # 32 启用重新挂载为只读 # 64 启用进程信号(终止、杀死、溢出杀死) # 128 允许重启/关机 # 256 控制实时任务的优先级控制(nicing) kernel.sysrq = 0 # core_uses_pid 可以控制 core 文件的文件名中是否添加 pid 作为扩展名 # 设置为1,表示添加 pid 作为扩展名,生成的 core 文件格式为 core.xxx;设置为0(默认),表示生成的 core 文件统一命名为 core kernel.core_uses_pid = 1 # 规定了一个消息队列的最大值,即一个消息队列的容量,msgmnb 控制可以使用的共享内存的总页数 # Linux共享内存页大小为4KB,共享内存段的大小都是共享内存页大小的整数倍 # 一个共享内存段的最大大小是 16G,那么需要共享内存页数是16GB / 4KB = 16777216KB / 4KB = 4194304(页) kernel.msgmnb = 65536 # 进程间的消息传递是在内核的内存中进行的。msgmax 指定了消息队列中消息的最大值(65536B=64KB) kernel.msgmax = 65536 # 内核所允许的最大共享内存段的大小(bytes) kernel.shmmax = 68719476736 # 表示在任何给定时刻,系统上可以使用的共享内存的总量(bytes) kernel.shmall = 4294967296 # 表示内核套接字发送缓存区默认的大小 net.core.wmem_default = 8388608 # 表示内核套接字接受缓存区默认的大小 net.core.rmem_default = 8388608 # 表示内核套接字接受缓存区的最大大小 net.core.rmem_max = 16777216 # 表示内核套接字发送缓存区的最大大小 net.core.wmem_max = 16777216 # 接收自网卡,但未被内核协议栈处理的报文队列长度 net.core.netdev_max_backlog = 262144 # web 应用中 listen 函数的 backlog 默认会给我们内核参数的 # 对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接 # 当三次握手成功后,我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了 # 每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度与如somaxconn参数和使用该端口的程序中listen()函数有关 # somaxconn定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128 # 对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多 # 大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助 net.core.somaxconn = 40960 # 不充当路由器 net.ipv4.ip_forward = 0 # 控制系统是否开启对数据包源地址的校验 # 0 不开启源地址校验 # 1 开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包 # 2 开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包 net.ipv4.conf.default.rp_filter = 1 # 使用sysrq组合键是了解系统目前运行情况,为安全起见设为0关闭 net.ipv4.conf.default.accept_source_route = 0 # 启用有选择的应答(1表示启用) # 通过有选择地应答乱序接收到的报文来提高性能,让发送者只发送丢失的报文段,(对于广域网通信来说)这个选项应该启用,但是会增加对CPU的占用 net.ipv4.tcp_sack = 1 # tcp窗口大于64K时,必须开启此值 net.ipv4.tcp_window_scaling = 1 # TCP读缓存的最小值、默认值、最大值,单位字节 net.ipv4.tcp_rmem = 10240 87380 12582912 # TCP读缓存的最小值、默认值、最大值,单位字节 net.ipv4.tcp_wmem = 10240 87380 12582912 # TCP的内存大小,单位是页,1页等于4096字节,单位为页的数量 net.ipv4.tcp_mem = 94500000 915000000 927000000 # 系统中最多有多少个 TCP 套接字不被关联到任何一个用户文件句柄上 # 这个限制仅仅是为了防止简单的 DoS 攻击,如果增加了内存之后,更应该增加这个值 net.ipv4.tcp_max_orphans = 3276800 # SYN队列的长度,默认为1024,加大队列长度为262144,可以容纳更多等待连接的网络连接数 net.ipv4.tcp_max_syn_backlog = 262144 # 用于设置时间戳,可以避免序列号的卷绕 # 一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。设置为 0 表示将其关掉 net.ipv4.tcp_timestamps = 0 # 内核放弃连接之前发送 SYN+ACK 包的数量 # 被动建立连接时,发送SYN/ACK的重试次数 net.ipv4.tcp_synack_retries = 1 # 主动建立连接时,发送SYN的重试次数 net.ipv4.tcp_syn_retries = 1 # 开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 # 开启重用。作为客户端时,新连接可以使用仍然处于 TIME-WAIT 状态的端口,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 # TIME_WAIT 状态连接的最大数量,超出后直接关闭连接 net.ipv4.tcp_max_tw_buckets = 6000 # fin_wait1状态,发送fin报文的重试次数,0相当于8 net.ipv4.tcp_orphan_retries = 0 # fin_wait2状态,默认的 TIMEOUT 时间 net.ipv4.tcp_fin_timeout = 15 # 当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时 net.ipv4.tcp_keepalive_time = 1200 # 探测包发送间隔 net.ipv4.tcp_keepalive_intvl = 75 # 探测包重试次数 net.ipv4.tcp_keepalive_probes = 6 #开启SYN Cookies 当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 # 建立连接时的本地端口可用范围 net.ipv4.ip_local_port_range = 1024 65000

修改最大打开文件句柄数

编辑文件:/etc/security/limits.conf

* soft nofile 65535 * hard nofile 65535

__EOF__

本文作者krystal
本文链接https://www.cnblogs.com/starkzz/p/17553839.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   krysatl  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示