NGINX:漫谈优化
优化那些事儿
生产环境下网站做前期的优化肯定是比不可少的,简单来说就是用同等条件的硬件资源,处理更多的网站业务,大程度提供网站业务处理能力;前辈留下的实战经验可都是财富,好多坑只有踩过才知道痛,下面就来漫谈下优化的那些事儿
修改系统Ulimit
网站优化,首先要做的是先对系统进行优化,上线的服务器经常是用Linux系统做的;而在Linux下面部署应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题;这是因为Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,这个值也会影响服务器的最大并发数(每个连接都是打开一个文件描述符),生产服务器这个值肯定是不够的;先做个测试看看ulimit的重要性
查看ulimit值:
[root@localhost ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7671
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 7671
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
其中 "open files (-n) 1024 "是Linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的socket数量,可影响所有底层用到socket的服务,包括MySQL等)
进行ab压力测试:
[root@bogon ~]# ab -n 2000 -c 1000 http://192.168.20.219/paperindex.htm #发起1000个并发连接,共2000次请求
ab工具下载-》》windows:https://pan.baidu.com/s/1skNwUKH Linux:yum -y install httpd 默认在/usr/bin/ab下
统计日志:
[root@localhost logs]# cat host.access.log | wc -l
2001
[root@localhost logs]# awk '{print $4}' host.access.log | grep 500 | wc -l
874
[root@localhost logs]# awk '{print $4}' host.access.log | grep 200 | wc -l
1127
web端一共收到2000次请求,200状态码的正常访问1127次,其余800多次客户端访问抛出500异常,未能提供正常响应
修改ulimit:
ulimit -n 65535 暂时生效 ##也可为655360
若要令修改ulimits的数值永久生效,则必须修改配置文档,可以给ulimit修改命令放入/etc/profile里面,这个方法实在是不方便 还有一个方法是修改/etc/security/limits.conf
[root@localhost ~]# vim /etc/security/limits.conf
文件里面有很详细的注释,比如
* soft nofile 65535 * hard nofile 65535
星号代表全局, soft为软件,hard为硬件,nofile为这里指可打开文件数。
把以上两行内容加到 limits.conf文件中即可 另外,要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中。查看 /etc/pam.d/login 文件中有:
[root@localhost ~]# vim /etc/pam.d/login
session required /lib/security/pam_limits.so 修改完重新登录就可以见到效果,可以通过 ulimit -n 查看 重启nginx服务
[root@localhost ~]# ulimit -n
65535
重新做压力测试:
[root@bogon ~]# ab -n 100000 -c 10000 http://192.168.20.219/paperindex.htm Benchmarking 192.168.20.219 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
直接发送100000次请求,10000并发
统计日志:
[root@localhost logs]# cat host.access.log |wc -l
101337
[root@localhost logs]# awk '{print $4}' host.access.log |grep 200 |wc -l
101337
web端一共收到101337次请求,所有请求状态200正常
限制访问连接
生产环境下很多情况是不对访问做限制,但也有特殊状况,比如部署个网络投票评选平台,会有恶意刷票的情况出现,刷票会占用大量系统资源,影响其他正常的访问,这时就需要对访问的IP进行并发数或者访问频率进行限制
nginx有两个模块可以控制访问
- limit_conn_zone 限制同时并发访问的数量
- limit_req_zone 限制访问数据,每秒内最多几个请求
但具体有什么不同呢?下面是 nginx 官网上抛出的解释
limit_conn_zone
Limit simultaneous connections from a client.
This module makes it possible to limit the number of simultaneous connections for the assigned session or as a special case, from one address. limit_req_zone
Limit frequency of connections from a client.
This module allows you to limit the number of requests for a given session, or as a special case, with one address.
Restriction done using leaky bucket.
按照字面的理解
- limit_conn_zone 功能是限制一个客户端的并发连接数(这个模块可以限制单个地址 的指定会话 或者特殊情况的并发连接数)
- lit_req_zone的功能是通过漏桶原理来限制用户的连接频率(这个模块允许你去限制单个地址 指定会话或特殊需要 的请求数 )
一个是限制并发连接一个是限制连接频率,表面上似乎看不出来有什么区别,那就直接看效果如何
测试limit_conn_zone修改配置文件:
http {
include mime.types;
default_type application/octet-stream; limit_conn_zone $remote_addr zone=James_conn:10m ; limit_conn James_conn 1; ..............
}
limit_zone James_conn $binary_remote_addr 10m;这里的James_conn是声明一个 limit_zone 的名字,$remote_addr是客户端的IP,10m是会话状态储存的空间,1M大概可以保存16000IP
limit_conn James_conn 1 ;限制客户端并发连接数量为1
并发测试:
[root@bogon ~]# ab -n 20 -c 10 http://192.168.20.219/paperindex.htm #10个并发,20个请求
log日志:
分析日志20次的请求中不只一次返回200,多测试几次依然如此,看来此模块也不一定能限制的住1秒钟1个并发连接,但还是拒绝了大多数的访问
后续:
又对服务器进行了10000并发10000次请求
[root@bogon ~]# ab -n 10000 -c 10000 http://192.168.20.219/paperindex.htm
日志结果:
短时间内大的并发量处理还是有效果的
测试limit_req_zone修改配置文件:
http {
include mime.types;
default_type application/octet-stream; limit_req_zone $remote_addr zone=req_James:10m rate=1r/s; ......................................
server {
listen 80;
server_name localhost;
limit_req zone=req_James burst=120 nodelay; ...........................
}
}
简单说明一下, rate=1r/s 的意思是每个地址每秒只能请求一次,也就是说根据漏桶原理 burst=120 一共有120块令牌,并且每秒钟只新增1块牌,120块令牌发完后就不会再响应 ,加上nodelay之后超过 burst大小的请求就会直接返回503,而不是在后台进行排队等待
连接频率测试:
[root@bogon ~]# ab -n 10000 -c 1000 http://192.168.20.219/paperindex.htm #1000并发的10000次请求
整个测试过程大概花了4秒钟,也就在一共可以正常的访问124次左右
log日志:
几乎全是503错误,再对日志进行统计
126次正常访问,9949次503错误,结果跟我们猜想的清楚差不多,说明这个模块真的还蛮好用的
番外:根据真实IP做限制
##取用户的真实IP map $http_x_forwarded_for $clientRealIp {
## 没有通过代理,直接用 remote_addr
"" $remote_addr;
## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP
## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...## 这里第一个 202.123.123.11 是用户的真实IP,后面其它都是经过的 CDN 服务器
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
## 通过 map 指令,我们为 nginx 创建了一个变量 $clientRealIp ,这个就是 原始用户的真实 IP 地址,
## 不论用户是直接访问,还是通过一串 CDN 之后的访问,我们都能取得正确的原始IP地址 ## 每秒并发连接限制
limit_conn_zone $clientRealIp zone=TotalConnLimitZone:10m ; ## 每秒请求数限制
limit_req_zone $clientRealIp zone=ConnLimitZone:10m rate=10r/s; #未经过测试 以后有时间再做
优化配置文件突破十万并发
#user nobody;
worker_processes auto; ##允许Nginx进程生成的worker process数 根据cpu内核数自动生成 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
#为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一个进程分配到多个cpu #error_log logs/error.log
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid; worker_rlimit_nofile 102400;
#这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx 进程数相除,
#但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致 events {
use epoll; ##配置事件驱动模型,使用epoll 的I/O 模型
worker_connections 102400; ##配置最大连接数,每个进程允许的最多连接数,理论上每台nginx 服务器的最大连接数
#为worker_processes*worker_connections
} http {
include mime.types; ##定义MIME-Type
default_type application/octet-stream;
log_format main '$remote_addr - [$time_local] - "$request"' ##定义日志类型,远程地址、时间、请求内容、请求状态、cookie值
' - $status' $http_cookie; types_hash_max_size 2048; ##多servername需设置
client_header_buffer_size 4k; ##客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求
#头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE 取得
open_file_cache max=102400 inactive=20s;
#这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存
open_file_cache_valid 30s;
#这个是指多长时间检查一次缓存的有效信息
server_names_hash_bucket_size 512;
sendfile on;
server_tokens off; ##关闭默认版本号
keepalive_timeout 20; ##定义链接超时时间,防止慢速dos攻击
client_header_timeout 15; ##请求头超时时间
client_body_timeout 15; ##请求体超时时间
reset_timedout_connection on; ##关闭不响应的客户端连接,释放客户端占有内存
send_timeout 10; ##客户端两次读取时间,如果这段时间里没有读取任何数据,nginx就会关闭连接 ########################内核优化#####################
net.ipv4.tcp_max_tw_buckets = 6000
#timewait 的数量,默认是180000。
net.ipv4.ip_local_port_range = 1024 65000
#允许系统打开的端口范围。
net.ipv4.tcp_tw_recycle = 1
#启用timewait 快速回收。
net.ipv4.tcp_tw_reuse = 1
#开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。
net.ipv4.tcp_syncookies = 1
#开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理。
net.core.somaxconn = 262144
#web 应用中listen 函数的backlog 默认会给我们内核参数的net.core.somaxconn 限制到128,而nginx 定义的
#NGX_LISTEN_BACKLOG 默认为511,所以有必要调整这个值。
net.core.netdev_max_backlog = 262144
#每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.ipv4.tcp_max_orphans = 262144
#系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打
#印出警告信息。这个限制仅仅是为了防止简单的DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值
#(如果增加了内存之后)。
net.ipv4.tcp_max_syn_backlog = 262144
#记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M 内存的系统而言,缺省值是1024,小内存的系统则是128。
net.ipv4.tcp_timestamps = 0
#时间戳可以避免序列号的卷绕。一个1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。
#这里需要将其关掉。
net.ipv4.tcp_synack_retries = 1
为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN 的ACK。也就是所谓三次握手中的第二次握手。
#这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。
net.ipv4.tcp_syn_retries = 1
在内核放弃建立连接之前发送SYN 包的数量。
net.ipv4.tcp_fin_timeout = 1
如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2 状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。
#缺省值是60 秒。2.2 内核的通常值是180 秒,3你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB 服务器,
#也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比FIN-WAIT-1 要小,因为它最多只能吃掉1.5K 内存,但是它们的生存期长些。
net.ipv4.tcp_keepalive_time = 30
当keepalive 起用的时候,TCP 发送keepalive 消息的频度。缺省是2 小时。 server { ##直接访问IP 反馈500错误
listen 80 default;
return 500;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
} server {
listen 80;
server_name www.test.com www.test.com.cn;
#rewrite域名跳转
if ($host != 'www.test.com' ) {
rewrite ^/(.*)$ http://www.test.com/$1 permanent; #调转
}
access_log /data/web_log/test/access.log main;
error_log /data/web_log/test/error.log debug; #设置cookie值
if ($http_cookie ~* "(.*)$"){
#if ($http_cookie ~* "JCRB_VOTE=([A-Z0-9]*)"){
set $guid $1;
} #当访问.txt结尾的文件时向/data/yanz目录里找
location ~ \.txt$ {
root /data/yanz;
} location / {
root /data/test;
index index.html index.xml;
ssi on;
ssi_silent_errors on;
ssi_types text/shtml;
} error_page 404 /404.html;
location = /404.html {
root html;
} error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
} } }
NGINX:漫谈优化的更多相关文章
- nginx + SSL优化配置
nginx + SSL优化配置: #http段添加如下配置项: http { ssl_prefer_server_ciphers on; #设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户 ...
- nginx 配置优化的几个参数
nginx 配置优化的几个参数 2011-04-22 本文地址: http://blog.phpbean.com/a.cn/7/ --水平有限欢迎指正-- -- 最近在服务器上搞了一些nginx 研究 ...
- 【实战分享】又拍云 OpenResty / Nginx 服务优化实践
2018 年 11 月 17 日,由 OpenResty 主办的 OpenResty Con 2018 在杭州举行.本次 OpenResty Con 的主题涉及 OpenResty 的新开源特性.业界 ...
- [Nginx] – 性能优化 – 配置文件优化
Nginx基本安全优化 1.调整参数隐藏Nginx版本号信息 一般来说,软件的漏洞都和版本有关,因此我们应尽量隐藏或清除Web服务队访问的用户显示各类敏感信息(例如:Web软件名称及版本号等信 ...
- Nginx配置项优化详解【转】
(1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...
- Nginx软件优化【转】
转自 Nginx软件优化 - 惨绿少年 - 博客园 Nginx软件优化 - 惨绿少年 - 博客园 https://www.cnblogs.com/clsn/p/8484559.html 1.1 Ngi ...
- Nginx软件优化
1.1 Nginx优化分类 安全优化(提升网站安全性配置) 性能优化(提升用户访问网站效率) 1.2 Nginx安全优化 1.2.1 隐藏nginx版本信息优化 官方配置参数说明:http://ngi ...
- nginx配置文件优化
nginx配置优化 #定义Nginx运行的用户和用户组user www www: #启动工作进程,通常设置成和cpu的数量相等worker_processes 8: 最多开启8个,8 ...
- Nginx配置优化参考
Nginx配置优化参考 ...
随机推荐
- c++获取cpu信息
原文地址:http://blog.csdn.net/jamesliulyc/article/details/2028958 1.什么是cpuid指令 CPUID指令是intel IA32架构下获得CP ...
- mysql 启动报错--发现系统错误2,系统找不到指定的文件。
解决方法: 控制面板--找到mysql程序--修复
- logging.xml file setfile(null,true) call failed
定义目录三个方法:一:${catalina.base}或${catalina.home}相对路径配置方法.catalina.home是你配置服务器时自动在环境变量中加的路径,默认是指向tomcat服务 ...
- [转]SQL注入漏洞及绑定变量浅谈
1.一个问题引发的思考 大家在群里讨论了一个问题,奉文帅之命写篇作文,且看: String user_web = "user_web" String sql = "upd ...
- Oracle过程及函数的参数模式详解
一.In.out.in out模式 在Oracle中过程与函数都可以有参数,参数的类型可以指定为in.out.in out三种模式. 三种参数的具体说明,如下图所示: (1)in模式 in模式是引用传 ...
- 最值得一看的几条简单的谷歌 Google 搜索技巧,瞬间提升你的网络搜索能力
可能你和我一样,几乎每天都必须与搜索引擎打交道,不过很多时候,你辛辛苦苦搜了半天也没找到合适的资料,然而“高手们”上来一眨眼功夫就能命中目标了.这并不是别人运气好,而是搜索引擎其实是有很多技巧可以帮助 ...
- mybatis由浅入深day02_6延迟加载_延迟加载总结
6 延迟加载 6.1 什么是延迟加载 需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载. resultMap可以实现高级映射 ...
- 查看系统负载:uptime
uptime命令用于查看系统负载,跟 w 命令的输出内容一致 [root@localhost ~]$ uptime :: up days, :, users, load average: 0.03, ...
- XMPP HTTP
1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上 ...
- 关于js中定时器的返回值问题
在js中,我们常常会用到定时器来处理各种各样的问题,当我们需要清除定时器的时候,我们常常会定义一个值来接受定时器的返回值,然后再把定义好的这个值写到清除定时器的括弧后面,如: var times = ...