高并发下Nginx性能优化 总结高并发下Nginx性能怎样优化
PurpleHin 人气:0我们终将在,没有黑暗的地方相见。 ~乔治《1984》
Nginx同Apache一样都是一种WEB服务器。基于REST架构风格,以统一资源描述符(UniformResources ldentifier)URl或者统一资源定位符(Uniform Resources Locator)URL作为沟通依据,通过HTTP协议提供各种网络服务。
Apache的发展时期很长,而且是毫无争议的世界第一大服务器。它有着很多优点:稳定、开源、跨平台等等。它出现的时间太长了,它兴起的年代,互联网产业远远比不上现在。所以它被设计为一个重量级的。它不支持高并发的服务器。在Apache上运行数以万计的并发访问,会导致服务器消耗大量内存sz操作系统对其进行进程或线程间的切换也消耗了大量的CPU资源,导致HTTP请求的平均响应速度降低。
这些都决定了Apache不可能成为高性能WEB服务器,轻量级高并发服务器Nginx就应运而生了。
特点
是一个高性能的HTTP和反向代理web服务器,轻量级提供了IMAP/POP3/SMTP服务发布于2004年10月4日(第一个公开版本0.1.0 )Nginx的1.4.0稳定版已经于2013年4月24日发布C语言编写Nginx是一个跨平台服务器Nginx有自己的函数库,并且除了zlib、PCRE和OpenSSL之外,标准模块只使用系统C库函数。
优势
占有内存少(在3W并发连接中,开启的10个nginx进程消耗内存大约150M)高并发能力强(官方测试能够支撑5W并发连接,在实际生产环境中能到2-3W并发连接数)简单(配置文件通俗易懂)价格(免费、开源)支持Rewriter重写(能够根据域名、URL的不同,将HTTP请:求分到不同的后端服务器群组)内置健康检查(如果nginx后端有几个服务宕机了,不会影响前端访问,能自动检测服务状态)节省带宽(支持GZIP压缩,可以添加浏览器本地缓存的Header头)
稳定性高,反向代理,很少宕机中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等
功能:web服务器、轻量级;负载、均衡;缓存;高并发
应用场景:代理服务器;IP负载、静态负载;动静分离;限流、健康监控
安装和命令
安装:
sudo apt-get install nginx
查看版本
nginx -v nginx version: nginx/1.18.0 (Ubuntu)
基本命令
# nginx的访问页面(welcome to nginx)具体所在位置 vi /usr/share/nginx/html/index.html # 访问IP curl 192.168.100.111 # 关闭nginx进程 nginx -s stop # 启动nginx进程 /usr/sbin/nginx # yum安装的nginx也可以使用 servic nginx start # 检查配置文件是否有误 nginx –t # 重新加载配置文件 nginx –s reload # 查看日志 tail -f filename #显示文件默认10行,刷新显示 # 例:tail -f /var/log/lvs-agent.log tail -f /etc/nginx/nginx.conf # 查看文件后几行 tail -n 行数 文件名 例: tail -n 100 /var/log/aa.log # 删除网卡ip ip addr del 192.168.11.5/32 dev lo (lo eth1 eth2) # lvs清空所有集群服务 ipvsadm –C # 获取eth0网卡上的所挂的ip值 ip a|grep eth0|grep inet|awk ‘{print $2}'|cut -d “/” -f1 # 验证该ip或者网址是否通 可用返回200 curl -I -m 10 -o /dev/null -s -w %{http_code} 10.110.26.10:8080 # 后台启动jar包 nohup java -jar /usr/sbin/项目名.jar >>/var/log/项目名.log 2>&1 & # 查看上一个命令是否执行成功 返回0执行成功 其他不成 echo $? # 查看nginx进程是否启动。此命令用在代码判断nginx进程是否启动,如果只用ps aux | grep nginx 即使没有启动也会用内容返回,影响判断 ps aux | grep nginx | greo –v grep
配置文件
nginx.conf
# nginx.conf # 全局配置区 user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; # 网络事件配置区 events { worker_connections 768; # multi_accept on; } # HTTP模块 http { ## # HTTP 全局设置 ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL 设置 ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # 日志设置 ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # 资源压缩设置 ## gzip on; # 默认开启 # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # 虚拟主机配置 ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
/etc/nginx/sites-enabled/*
server { # 虚拟主机配置 listen 80 default_server; # 监听端口 listen [::]:80 default_server; # SSL 配置 # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf; # 数据缓存位置 root /var/www/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; # 域名,可以有多个 server_name _; # 对/进行反向代理 location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. # uwsgi_pass 127.0.0.1:8000; # include /etc/nginx/uwsgi_params; try_files $uri $uri/ =404; } # pass PHP scripts to FastCGI server # #location ~ \.php$ { # include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): # fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
代理模式和配置反向代理
正向代理(forward proxy) :
是一个位于客户端(用户A)和原始服务器(origin server)(目标服务器)之间的服务器(代理服务器),为了从原始服务器取得内容,客户端向代理服务器发送一个请求并指定目标(原始服务器),然后代理服务器向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的配置才能使用正向代理。一般情况下,如果没有特别说明,代理技术默认是指正向代理技术。
相当于是一个职业中介,且客户端和实际服务器不能沟通,客户端知道他是中介
反向代理(reverse proxy)︰
和正向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。
相当于是一个买房和卖房的人,买房的时候相对于卖房的是一个买房的,卖房的时候相对于买房的是一个卖房的。
客户端不知道他是一个代理服务器,服务器也认为他只是客户端而不是代理服务器
透明代理∶
透明代理的意思是客户端根本不需要知道有代理服务器的存在,它改编你的requestfields(报文),并会传送真实IP。注意,加密的透明代理则是属于匿名代理,意思是不用设置使用代理了。透明代理实践的例子就是时下很多公司使用的行为管理软件
# 反向代理默认是关闭的 # upstream localhost是第三方模块,均衡 upstream localhost { # 实际服务器 server 192.168.136.133:8081; server 192.168.136.133:8081; server 192.168.136.133:8081; } # 负载 server { listen 80 # 代理服务器的端口 server_name localhost; location / { proxy_pass http://localhost; # 将请求发送给其中一台实际服务器 } }
负载均衡方法:
轮询法(默认)
加权轮询法(权重)
Fair
url_hash
源地址哈希法
最小连接法(least_conn)
动静分离
Nginx动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离
严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat处理动态页面
动静分离从目前实现角度来讲大致分为两种:
- 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案
- 一种是动态跟静态文件混合在一起发布,通过nginx来分开
mkdir static # 存放静态文件
server { # 虚拟主机配置 listen 80 default_server; # 监听端口 listen [::]:80 default_server; # 数据缓存位置 root /var/www/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; # 域名,可以有多个 server_name _; # 对/进行反向代理 location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. # uwsgi_pass 127.0.0.1:8000; # include /etc/nginx/uwsgi_params; try_files $uri $uri/ =404; } # 如果是这些文件后缀就去这里面找 location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css) $ { root /static; expires 30d; # 缓存有效期 } }
日志管理
日志格式
日志生成的到Nginx根目录logs/access.log文件,默认使用“main”日志格式,也可以自定义格式默认“main”日志格式
og_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; $remote_addr:客户端的ip地址(代理服务器,显示代理服务ip) $remote_user:用于记录远程客户端的用户名称(一般为“-”) $time_local:用于记录访问时间和时区 $request:用于记录请求的url以及请求方法 $status:响应状态码,例如:200成功、404页面找不到等。 $body_bytes_sent:给客户端发送的文件主体内容字节数
日志切割
nginx的日志文件没有rotate功能
编写每天生成一个日志,我们可以写一个nginx日志切割脚本来自动切割日志文件
- 第一步就是重命名日志文件 (不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,Linux是靠文件描述符而不是文件名定位文件 )
- 第二步向nginx主进程发送USR1信号
nginx主进程接到信号后会从配置文件中读取日志文件名称
重新打开日志文件 (以配置文件中的日志名称命名) ,并以工作进程的用户作为日志文件的所有者
重新打开日志文件后,nginx主进程会关闭重名的日志文件并通知
工作进程使用新打开的日志文件工作进程立刻打开新的日志文件并关闭重名名的日志文件,然后你就可以处理旧的日志文件了。[或者重启nginx服务]
nginx日志按每分钟自动切割脚本如下 :
新建shell脚本
高并发架构分析
什么是高并发?
高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS (Query Per Second),并发用户数等。
- 响应时间:系统对请求做出响应的时间
- 吞吐量:单位时间内处理的请求数量。
- QPS:每秒响应请求数
如何提升系统的并发能力?
互联网分布式架构设计,提高系统并发能力的方式,方法论上主要有两种:垂直扩展(ScaleUp)与水平扩展(Scale Out)。
垂直扩展:提升单机处理能力。垂直扩展的方式又有两种。
- 增强单机硬件性能
- 提升单机架构性能
在互联网业务发展非常迅猛的早期,如果预算不是问题,强烈建议使用“增强单机硬件性能”的方式提升系统并发能力,因为这个阶段,公司的战略往往是发展业务抢时间,而“增强单机硬件性能”往往是最快的方法。
不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。
水平扩展:只要增加服务器数量,就能线性扩充系统性能。
服务器都有极限
三种方式实现
limit_conn_zone(限制连接流)
limit_req_zone(限制请求流)
ngx_http_upstream_module(后台服务限制)
此处插上一个小工具:限制测试工具下载
yum install http-tools -y
key | 含义 |
---|---|
Document Path | 测试的页面 |
Document Length | 页面的大小 |
Concurrency Level | 并发数量、并发用户数 |
Time taken for tests | 测试耗费总时间 |
Complete requests | 请求总量、并发连接数 |
Failed requests | 请求失败的数量 |
Write errors | 错误数量 |
Requests per second | 每秒钟的请求量吞吐率 |
Time per request | 每次请求需要时间响应时间 |
限制连接流
http { # binary_remote_addr:IP # zone=one:10m;申请一块10M的空间存放连接的IP limit_conn_zone $binary_remote_addr zone=one:10m; server { # zone区域中每次放出10个连接nginx处理 limit_conn one 10; } }
限制请求流(限速)
http { # rate意思是每个连接每秒能发一个连接 limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s; server { # brust:令牌,每次新增一个,120个发完后会报错503 limit_req zone=req_one brust=120; } }
后台服务限制
该模块是提供了我们需要的后端限流功能的
该模块有一个参数: max_conns可以对服务端进行限流,可惜在商业版nginx中才能使用
在nginx1.11.5版本以后,官方已经将该参数从商业版中脱离出来了,也就是说只要我们将生产上广泛使用的nginx1.9.12版本和1.10版本升级即可使用
server { # max_conns最大接收服务数量 server 127.0.0.1:8080 max_conns=100; }
安全配置
版本安全
http { server_tokens off; }
IP安全
http { location / { allow 127.0.0.1; # 白名单 deny all; # 黑名单 } }
文件安全
http { location /logs{ autoindex on; # 展示目录 root /static; } location ^/logs~*\.(log|txt)$ { add_header Content_Type text/plain; root /static; } }
连接安全
http { # SSL settings }
Nginx优化
调整Nginx的主配置文件,增加并发量
worker_processes 2;# 调整与CPU一致 events { # 每个worker最大并发数量 worker_connection 65535; }
Nginx长连接:HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,
nginx长连接短连接,可以增强服务器的容灾能力
减少了建立和关闭连接的消耗和延迟。如果我们使用了nginx去作为反向代理或者负载均衡,从客户端过来的长连接请求就会被转换成短连接发送给服务器端,为了支持长连接,我们需要在nginx服务器上做一些配置
使用nginx时,想要做到长连接,我们必须做到以下两点:
- 从client到nginx是长连接(events)
- 从nginx到server是长连接(http)
对于客户端而言,nginx其实扮演着server的角色,反之,之于server,nginx就是一个client
events { # keepalive超时时间,默认是60s,切记这个参数也不能设置过大!否则会导致许多无效的http连接占据着nginx的连接数,终nginx崩溃! keepalive_timeout 60; } http { keepalive_timeout 60; }
Nginx压缩
gzip压缩作用:将响应报文发送至客户端之前可以启用压缩功能,这能够有效地节约带宽,并提高响应至客户端的速度,压缩会消耗nginx的cpu性能。
gzip压缩可以配置http,server和location模块下
http { #gzip模块设置 #开启压缩 gzip on; # 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。 默认值是0,不管页面多大都压缩。建议设置成大于2k的字节数,小于2k可能会越压越大。 gzip_min_length 2k; # 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 例如 4 4k 代表以4k为单 位,按照原始数据大小以4k为单位的4倍申请内存。 4 8k 代表以8k为单位,按照原始数据大小以8k 为单位的4倍申请内存。 # 如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。 gzip_buffers 4 16k; #压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间 gzip_comp_level 5; # 默认值: gzip_types text/html (默认不对js/css文件进行压缩) # 压缩类型,匹配MIME类型进行压缩 # 不能用通配符 text/* # (无论是否指定)text/html默认已经压缩 # 设置哪压缩种文本文件可参考 conf/mime.types gzip_types text/plain application/xjavascript text/css application/xml; # 值为1.0和1.1 代表是否压缩http协议1.0,选择1.0则1.0和1.1都可以压缩 gzip_http_version 1.0 # IE6及以下禁止压缩 gzip_disable "MSIE [1-6]\."; # 默认值:off # Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服 务器必须要返回包含"Via"的 header头。 # off - 关闭所有的代理结果数据的压缩 # expired - 启用压缩,如果header头中包含 "Expires" 头信息 # no-cache - 启用压缩,如果header头中包含 "Cache-Control:no-cache" 头信息 # no-store - 启用压缩,如果header头中包含 "Cache-Control:no-store" 头信息 # private - 启用压缩,如果header头中包含 "Cache-Control:private" 头信息 # no_last_modified - 启用压缩,如果header头中不包含 "Last-Modified" 头信息 # no_etag - 启用压缩 ,如果header头中不包含 "ETag" 头信息 # auth - 启用压缩 , 如果header头中包含 "Authorization" 头信息 # any - 无条件启用压缩 gzip_proxied expired no-cache no-store private auth; # 给CDN和代理服务器使用,针对相同url,可以根据头信息返回压缩和非压缩副本 gzip_vary on }
状态监控
server { location /NginxStatus { stub_status on; access_log off; } }
插件安装
./configure --prefix=... --with-http_stub_status _module
加载全部内容