• Linux学习系列之Nginx调优实战


    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服务降权解决方案 

    1. 给nginx服务降权,用inca用户跑nginx服务,给开发及运维设置普通账号,只要和inca同组即可管理nginx,该方案解决了nginx管理问题,防止root分配权限过大
    2. 开发人员使用普通账号即可管理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 
    复制代码
  • 相关阅读:
    Linux各个目录的作用及内容
    发现未授权登录用户怎么办
    开启GodMode
    通过域名方式决定使用哪个数据库的方式分享
    openerp-server.conf 中配置 dbfilter 参数无效的解决办法
    OpenERP7.0 忘记admin管理员密码解决办法
    DEB方式在UBUNTU安装ODOO 8.0
    解决apt-get的E: Could not get lock /var/lib/dpkg/lock方法
    Ubuntu 11.04 (Natty) 已经停止支持 但可以使用old-releases源了
    How to get the url of a page in OpenERP?
  • 原文地址:https://www.cnblogs.com/djwhome/p/9582745.html
Copyright © 2020-2023  润新知