Nginx配置文件性能微调
全局的配置
user www-data; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 100000;
worker_process定义了nginx对外提供Web服务时的worker进程数,起始可以设置为CPU的核数,CPU核数是多少就设置为多少(设置为"auto"将自动检测)
worker_rlimit_nofile更改worker进程的最大打开文件限制,如果没设置的话,这个值为操作系统的限制.设置后你的操作系统和Nginx可以处理比"ulimit -a"更多的文件,所以把这个值设高,这样nginx就不会有"too many open files"问题了
Event模块部分
events { worker_connections 2048; multi_accept on; use epoll; }
worker_connections设置可由一个worker进程同时打开的最大连接数.如果设置了上面提到的worker_rlimit_nofile,我们可以将这个值设得很高
注意:最大客户数也由系统的可用socket连接数限制(~ 64K),所以设置不切实际的高没什么好处
multi_accept告诉nginx收到一个新连接通知后接受尽可能多的连接
use epoll使用epoll模型,效率更高
HTTP模块部分
http {
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
...
}
service_tokens隐藏Nginx版本号
sendfile可以让sendfile()发挥作用.sendfile()可以在磁盘和TCP socket之间互相拷贝数据(或任意两个文件描述符)
默认是Pre-sendfile,传送数据之前在用户空间申请数据缓冲区,之后用read()将数据从文件拷贝到这个缓冲区,write()将缓冲区数据写入网络.sendfile()是立即将数据从磁盘读到OS缓存,sendfile()要比组合read()和write()以及打开关闭丢弃缓冲更加有效
tcp_nopush告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送
tcp_nodelay告诉nginx不要缓存数据,而是一段一段的发送--当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值
keepalive_timeout 10; client_header_timeout 10; client_body_timeout 10; reset_timedout_connection on; send_timeout 10;
keepalive_timeout 给客户端分配keep-alive链接超时时间.服务器将在这个超时时间过后关闭链接.我们将它设置低些可以让ngnix持续工作的时间更长
client_header_timeout和client_body_timeout 设置请求头和请求体(各自)的超时时间,在一定时间内收不到客户端的请求头请求体就关闭连接
reset_timedout_connection 告诉nginx关闭不响应的客户端连接.这将会释放那个客户端所占有的内存空间
send_timeout指定客户端的响应超时时间.这个设置不会用于整个转发器,而是在两次客户端读取操作之间.如果在这段时间内,客户端没有读取任何数据,nginx就会关闭连接
limit_conn_zone $binary_remote_addr zone=addr:5m;
limit_conn addr 100;
limit_conn_zone设置用于保存各种key(比如当前连接数)的共享内存的参数.5m就是5兆字节,这个值应该被设置的足够大以存储(32K*5)32byte状态或者(16K*5)64byte状态
limit_conn addr为给定的key设置最大连接数.这里key是addr,我们设置的值是100,也就是说我们允许每一个IP地址最多同时打开有100个连接
include /etc/nginx/mime.types; default_type text/html; charset UTF-8;
include只是一个在当前文件中包含另一个文件内容的指令。这里我们使用它来加载稍后会用到的一系列的MIME类型
default_type设置文件使用的默认的MIME-type
charset设置我们的头文件中的默认的字符集
gzip on; gzip_min_length 1k; #最小1K的文件才启动压缩 gzip_buffers 4 32k; #压缩过程都写到buffer里面,压缩完成才发给客户端 gzip_http_version 1.1; gzip_comp_level 9; #压缩的级别 gzip_types text/css text/xml application/javascripts; #对什么样的内容压缩 gzip_vary on; #让前边的缓存服务器识别压缩后的文件
gzip是告诉nginx采用gzip压缩的形式发送数据,这将会减少我们发送的数据量
gzip_min_length设置对数据启用压缩的最少字节数.如果一个请求小于1K,我们最好不要压缩它,因为压缩这些小的数据会降低处理此请求的所有进程的速度
gzip_buffers
gzip_http_version是http协议
gzip_comp_level设置数据的压缩等级.这个等级可以是1-9之间的任意数值,9是最慢但是压缩比最大的.我们设置为4,这是一个比较折中的设置
gzip_types设置需要压缩的数据格式
gzip_vary 让前边的缓存服务器识别压缩后的文件
open_file_cache max=100000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;
open_file_cache打开缓存的同时也指定了缓存最大数目,以及缓存的时间.我们可以设置一个相对高的最大时间,这样我们可以在它们不活动超过20秒后清除掉
open_file_cache_valid在open_file_cache中指定检测正确信息的间隔时间
open_file_cache_min_uses 定义了open_file_cache中指令参数不活动时间期间里最小的文件数
open_file_cache_errors指定了当搜索一个文件时是否缓存错误信息,也包括再次给配置中添加文件.我们也包括了服务器模块,这些是在不同文件中定义的.如果你的服务器模块不在这些位置,你就得修改这一行来指定正确的位置
Nginx expires缓存
介绍
简单的说,nginx expire功能就是为用户访问的访问内容设定一个过期时间,当用户第一次访问到这些内容时,会把这些内容存储在用户浏览器本地,这样用户第二次访问该网站,浏览器会加载检查已经缓存在用户浏览器恩地的内容,就不去服务器下载了
作用
在网站开发和运营中,对于视频、图片、css、js等不长修改的元素缓存在客户浏览器本地.
图片可以缓存365天,css、js、html等代码缓存10-30天,这样用户第一次打开页面后,会按过期时间在客户浏览器缓存上述内容,下次用户在打开页面的时候重复的元素就无需加载了可放位置:
http server location,我们一般放在location段根据匹配规则设置过期时间
配置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${ expires 3650d; } location ~ .*\.(js|css)?$ { expires 30d; } location \image { expires 1d; }
Nginx日志相关优化与安全
配置日志切割
编写脚本实现nginx日志轮询 vim cut_nginx_log.sh #!/bin/bash cd /application/nginx/log /bin/mv www_access.log www_access_$(date +%F -d -1day).log /application/nginx/sbin/nginx -s reload 将脚本加入定时任务定期执行 crontab -e 00 00 * * * /bin/sb /root/cut_nginx_log.sh > /dev/null 2 >&1
不需要记录的日志
比如访问一些图片等是不需要记录日志的 location ~ .*\. (js|jpg}JPG|jpeg|css|bmp|gif|GIF|)$ { access_log off; } 说明:用location标签匹配不记录日志的元素扩展名,然后关掉日志
Nginx站点目录及文件URL访问控制
根据扩展名限制程序和文件访问
location ~ ^/images/.*\.(php|php5|.sh|.pl|.py)$ { deny all; } location ~ ^/static/.*\.(php|pph5|.sh|.pl|.py)$ { deny all; } 说明:用location标签匹配不被解析的文件,然后关掉访问权限
禁止访问指定目录下所有的文件和目录
单目录 location ~ ^/(static)/ { #写法一 deny all; } location ~ ^/static { #写法二 deny all' } 多目录 location ~ ^/(static|image) { deny all; }
禁止访问指定目录,如果访问就返回404
location /admin/ { return 404; } location /templates/ { return 403; }
限制来源IP访问
应用场景:网站后台,只允许个别IP或者网段访问 location ~ ^/oldboy/{ allow 192.168.0.20; deny all; } location ~ ^/admin/ { deny 192.168.0.1; allow 192.168.0.0/24; allow 10.1.1.0/16; deny all; #一旦deny all;下面就不能再接IP或者IP段了 }
Nginx防止恶意解析
什么是恶意解析
假如你们公司里web服务器是多台组成的一个集群,所以IP是不一样的,对方在ping你们域名的时候会出来一个IP,但是这个IP不是万网对应你们域名的IP,然后他们拿到这个IP,在万网上边把他们的域名解析到你这个IP上来,这就造成一个问题:如果他们的域名没备案的话,公安局就会一直找你们公司
解决方案
让使用IP直接访问网站的,或者访问恶意解析到你们公司IP的域名,收到501错误
配置
server { #这个虚拟主机必须放在其他虚拟主机的前边 listen 80 default_server; server_name _; return 501; } 说明:假如nginx多个虚拟主机,如果直接访问IP的话,nginx会默认访问第一个虚拟主机,所以通过IP直接访问的话就是访问第一个虚拟主机,就会报501错误,如果其他域名恶意解析到你这个IP上了也会返回501错误
Nginx配置防盗链
什么是资源盗链
假如把别人网站上的一段视频或一张图片,复制链接,然后放在自己的网站上,用户来自己网站访问这些内容的时候,承受负担和流量的是别人的服务器
常见防盗链解决方案基本原理
根据http referer实现防盗链
在HTTP协议中,有一个表头字段叫referer,使用URL格式来表示从哪里来的链接到当前网页的资源.
通过referer可以检测目标访问的来源网页,如果是资源文件,可以跟踪到显示它的网页地址,一旦检测出来不是本站,马上执行阻止或者返回指定图片、错误信息等
一句话说明:只允许指定的域名使用资源文件,如果其他域名使用则返回指定错误信息
什么是HTTP referer
HTTP referer是header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上referer,告诉我服务器我是从哪个页面链接过来的.
配置通过referer实现防盗链
编辑nginx.conf配置文件,加入第三个location字段部分,可以根据实际情况修改 vim nginx.conf server { listen 80; server_name blog.etiantian.org; root html/blog; location / { index index.php index.html index.htm; } location ~ .*\.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } location ~* \.(jpg|gif|png|swf|flv|wma|asf|mp3|mmf|zip|rar)$ { valid_referers none blocked *.etiantian.org etiantian.org #允许使用资源文件的域名 if ($invalid_referer){ #如果不是上边允许的域名使用资源文件的时候,就返回另一张图片,或者返回403也可以 rewrite ^/http://blog.etiantian.org/img/nolink.jps } #通过location匹配需要防盗的资源文件 } access_log logs/access_blog.log main; }
Nginx错误页面优雅显示
参数:error_page
可放位置:http,server
原理:如果发现404错误等,也可以是其他错误代码,自动跳转到某个页面(页面自定义)
配置404优雅显示
编辑nginx.conf配置文件,放在server下面就是针对某个虚拟主机的404做优雅显示,放在http就是对所有虚拟主机的404做优雅显示 vim nginx.conf server { listen 80; server_name blog.etiantian.org; root html/blog; location / { index index.php index.html index.htm; } location ~ .*\.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } #方法一 error_page 404 /error/404.html #如果发现404错误就跳转到html/blog/error/404.html页面 #方法二 error_page 404 www.baidu.com #如果发现404错误就跳转到www.baidu.com 方法三 error_page 404 403 /error/404.html #如果发现404、403错误就跳转指定页面 access_log logs/access_blog.log main; }
Nginx站点目录文件及目录权限优化
单机LNMP环境,站点目录和文件属性设置如下
所有目录权限755 所有文件权限644 所有目录和文件属主属组都是root 用户上传资源的目录权限755,属主属组都是nginx服务用户
集群参考
Nginx限制HTTP请求
我们可以通过nginx限制http请求的方法来达到提升服务器安全的目的,例如:让http只能使用GET、HEAD、POST放的配置如下
if (request_method !~ ^T|HEAD|POST)$) { return 501; }
还可以通过限制上传服务器的Web服务(可以具体到文件)使用GET方法,来达到防止用户通过上传服务器访问存储内容,让访问存储渠道只能从静态或图片服务器入口进入,例如在上传上限制HTTP的GET方法
if ($request_method ~* ^(GET)$) { return 501; } #请参考专业的nginx架构逻辑图
基于nginx Web服务linux系统内核参数优化
http://oldboy.blog.51cto.com/2561410/1336488
http://yangrong.blog.51cto.com/6945369/1321594
Nginx程序架构优化
为网站程序解耦
简单的说就是把一堆程序代码按照业务员用途分开,然后提供方服务,例如:注册登录、上传、下载、浏览列表、商品内容页面、订单支付等都应该是独立的程序服务,只不过在客户端看来是一个整体
中小公司必须做到以下几个程序模块独立
- 网页页面服务
- 图片附件及下载服务
- 上传图片服务
使用普通用户启动Nginx
为什么让Nginx服务使用普通用户
默认情况下,Nignx的master进程使用的是root用户,worker进程使用的是nginx指定的普通用户,使用root用户跑nginx进程有两个最大的问题
- 管理权限必须是root,
- 使用root跑nginx服务,一旦网站出现漏洞,用户就可以很容易的获得服务器的root权限
给nginx服务降权解决方案
- 给nginx服务降权,用inca用户跑nginx服务,给开发及运维设置普通账号,只要和inca同组即可管理nginx,该方案解决了nginx管理问题,防止root分配权限过大
- 开发人员使用普通账号即可管理nginx服务及其站点下的程序,看日志
给nginx服务降权实战
安装nginx使用root用户装到/application/nginx下
创建用来跑nginx的普通用户
[root@lnmp02 ~]# useradd inca
配置inca用户的nginx
[root@lnmp02 ~]# su - inca [inca@lnmp02 ~]$ mkdir conf www logs [inca@lnmp02 ~]$ touch conf/nginx.conf [inca@lnmp02 ~]$ vim nginx.conf worker_processes 1; error_log /home/inca/logs/error.log; user inca inca; pid /home/inca/logs/nginx.pid; events { worker_connections 1024; use epoll; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server { listen 8080; server_name www.etiantian.org; root /home/inca/www; location / { index index.html index.htm; } access_log /home/inca/logs/www_access.log main; } } [inca@lnmp02 ~]$ cp /application/nginx/conf/mime.types /home/inca/conf/.
启动Nginx
[inca@lnmp02 ~]$ /application/nginx/sbin/nginx -c /home/inca/conf/nginx.conf
测试Nginx进程是否是inca用户
[inca@lnmp02 ~]$ ps -ef |grep nginx inca 28697 1 0 02:50 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx -c /home/inca/conf/nginx.conf #可以看到nginx进程已经是inca账户了 inca 28698 28697 0 02:50 ? 00:00:00 nginx: worker process
Nginx页面缓存
模块:proxy_cache
缓存静态的文件,例如:CSS、JS、图片等
无缓存时用户访问流程
有缓存时用户访问流程
应用场景:Nginx作为反向代理的时候做Web页面缓存
作用
Web缓存位于Web服务器和客户端之间,当用户访问一个URL时,Web缓存服务器会去后端服务器取回要输出的内容,当下一个请求到来时,如果访问的是相同的URL,Web缓存服务器直接输出内容给客户端,就不再次向后端服务器发出请求了,从而降低了Web服务器、数据库的负载,减少了网络延迟,提高了用户访问速度
proxy_cache相关指令集
proxy_cache_path
可放位置:http段
语法:proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size[inactive=time] [max_size=size];
实例:proxy_cache_path /tmp/ngx_cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=5g;
path:存放目录
levels:指定该缓存空间有两层目录hash目录,第一层目录为一个字母,第二层目录为两个字母,例如:/tmp/ngx_cache/c/29/xxxxxxxxxxxx
keys_zone:指定该缓存区的名字
500m:指内存缓存空间大小为500m
inactive:指定过期时间,如果缓存数据在1天内没有被访问就删除
max_size:的5g是指硬盘缓存空间为30G
作用:用于设置缓存文件的存放路径
proxy_cache_methods
可放位置:
语法:proxy_cache_methods[GET HEAD POST];
实例:proxy_cache_methods[GET HEAD];
作用:用于设置缓存哪些HTTP方法,默认缓存HTTP的GET/HEAD方法,不缓存POST方法
proxy_cache_min_uses
可放位置
语法:proxy_cache_min_uses the_number
实例:语法:proxy_cache_min_uses 1
作用:用于设置缓存最小使用次数,默认值为1
proxy_cache_valid
可放位置:location
语法:proxy_cache_valid reply_code [reply_code...] time ;
实例:proxy_cache_valid 200 304 12h;
实例:proxy_cache_valid 301 302 1m;
实例:proxy_cache_valid any 1m;
作用:设置200、304状态的URL缓存12h,301、302状态的URL缓存1m,其他的都缓存1m
proxy_cache_key
可放位置:location
语法:proxy_cache_key line ;
实例:proxy_cache_key $host$uri$is_args$args;
作用:用来设置Web缓存的key值,Nginx根据Key值md5哈希存储缓存,一般根据$host(域名),$request_uri(请求的路径)等变量组合成proxy_cache_key
proxy_cache
可放位置:location
语法:proxy_cache [name]
实例:proxy_cache cache_one
作用:调用http段定义的proxy_cache_path
proxy_set_header
可放位置:location
实例:roxy_set_header HOST $host;
实例:proxy_set_header X-Forwarded-For $remote_addr;
作用:记录host主机名和客户端IP地址
配置Nginx Web缓存
环境说明
nginx-proxy 192.168.0.93 nginx
realserver 192.168.0.94 nginx
配置realserver
安装Nginx省略 配置nginx虚拟主机 [root@realserver ~]# vim /application/nginx/conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 8080; location / { root html/test; index index.html index.htm; } } } 配置网站程序 [root@realserver ~]# vim /application/nginx/html/test/index.html <img src="/root/test.jpg" /> 启动nginx [root@realserver ~]# /application/nginx/sbin/nginx 测试此虚拟主机 [root@realserver ~]# curl 192.168.0.94:8080/index.html #出来一张图片则为成功
配置Nginx Web缓存
安装Nginx省略 配置Nginx Web缓存 [root@nginx-proxy ~]# vim /application/nginx/conf/nginx.conf worker_processes 1; events { worker_connections 1024; } 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"'; '"addr:$upstream_addr-status:$upstream_status- cachestatus:$upstream_cache_status"' ; sendfile on; keepalive_timeout 65; proxy_cache_path /tmp/ngx_cache levels=1:2 keys_zone=cache:500m inactive=1d max_size=5g; upstream server_pool{ server 192.168.0.194:8080; } server { listen 80; server_name www.etiantian.org; location / { proxy_pass http://server_pool; proxy_cache cache; proxy_cache_valid 200 304 12h; proxy_cache_valid 301 302 1m; proxy_cache_valid any 1m; proxy_cache_key $host$uri$is_args$args; proxy_set_header HOST $host; proxy_set_header X-Forwarded-For $remote_addr; expires 1d; add_header Nginx-Cache "$upstream_cache_status"; #curl -I的时候可以查看是否命中 } access_log logs/www_access.log main; } } 测试Nginx Web缓存 [root@nginx-proxy ~]# curl -I 192.168.0.93 HTTP/1.1 200 OK Server: nginx/1.6.3 Date: Sun, 06 Nov 2016 00:25:20 GMT Content-Type: text/html Content-Length: 29 Connection: keep-alive Last-Modified: Sat, 05 Nov 2016 23:37:38 GMT ETag: "581e6d42-1d" Expires: Mon, 07 Nov 2016 00:25:20 GMT Cache-Control: max-age=86400 Nginx-Cache: MISS #可以看到第一次是MISS的,因为第一次请求Nginx还没缓存 Accept-Ranges: bytes [root@nginx-proxy ~]# curl -I 192.168.0.93 HTTP/1.1 200 OK Server: nginx/1.6.3 Date: Sun, 06 Nov 2016 00:25:23 GMT Content-Type: text/html Content-Length: 29 Connection: keep-alive Last-Modified: Sat, 05 Nov 2016 23:37:38 GMT ETag: "581e6d42-1d" Expires: Mon, 07 Nov 2016 00:25:23 GMT Cache-Control: max-age=86400 Nginx-Cache: HIT #可以看到第二次就命中了 Accept-Ranges: bytes