您的位置:首页 > 运维架构 > Nginx

Linux学习系列之Nginx调优实战

2016-11-06 02:04 309 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: