Nginx简介

  Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师IgorSysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页伺服器中表现较好.目前中国大陆使用nginx网站用户有:新浪、网易、腾讯,另外知名的微网志Plurk也使用nginx

 

  nginx可以作为一个反向代理服务器,用户请求经过它(其实这里用户请求到这里已经终止),判断静态页面或动态页面后再送往后方相应的服务器(nginx要另外启用一个进程到后方服务器取内容),服务器得到请求,响应,返回给nginxnginx会重新封装首部,缓存后再返回给客户端(nginx又重新启用一个进程发送结果给客户端了)。

  所以Nginx的实际并发能力,要除以2,因为它既要处理用户的请求,又要重新构建新的请求。它在反向代理的情况下,处理能力是有限的。

  注意:这里的缓存,是把urlhash,存储为key,因为hash可以保证唯一并且长度很小。响应的内容存储为value

 

Nginx安装

  详细过程参考http://dengxi.blog.51cto.com/4804263/1710472

 

Nginx的配置文件

 

  配置文件位于 /etc/nginx/nginx.conf

 

1、配置文件的结构

    ....

    events

    {

    ....

    }

    http

    {

    ....

        server

         {

            location{}

            ....

         }

        server

         {

            location {}

            ....

         }

    }

 

2、正常运行的必备配置

 

1)、user username [groupname];

    指定运行worker进程的用户和组

    例:user nginx nginx;

 

2)、pid /path/to/pidfile_name;

    指定nginxpid文件

 

3)、worker_rlimit_nofile #;

    指定一个worker进程所能够打开的最大文件句柄数;要等于或略大于worker_connections的值,因为还要打开其他文件

    例: worker_rlimit_nofile 51200;

 

4)、worker_rlimit_sigpending #;

    设定每个用户能够发往worker进程的信号的数量;

 

5)、events {

     use epoll;

     worker_connections  51200;

     }

    使用的网络I/O模型,Linux系统推荐采用epoll模型,FreeBSD系统推荐采用kqueue模型

 

 

3、优化性能相关的配置

 

1)、worker_processes 6;此项很关键!

     worker进程的个数,通常其数值应该为CPU的物理核心数减一

 

2)、worker_cpu affinity cpumask ...; 此项很关键!

    例:

     worker_processes6;  初始产生的worker进程个数,6个进程,把6个进程分别绑定在以下任意一个内核上(例如CPU一共有8个内
                   核,
nginx的进程只运行在这6个上面)

     worker_cpu_affinity00000001 00000010 00000100 00001000 00010000 00100000

 

3)、ssl_engine device;

     ssl硬件加速器,由于https链接所消耗的资源比http大得多,可能要多消耗56倍,所以有专门处理ssl的硬件设备

 

(4)、timer_resolution t;  此项很关键!

    每次内核事件调用返回时,都会使用gettimeofday()来更新nginx缓存时钟,time_resolution用于定义每隔多久才会
     由
gettimeofday()更新一次。因为每次调用返回都更新的话太消耗资源。不过目前x86-64系统上,gettimeofday()花费时间已经很
     小,可以忽略

 

(5)、worker_priority nice;

    用于定义worker的优先级,-2019,这项对系统性能提升很大,但值不要太小了。此项很关键

 

 

4、事件相关

 

1)、accept_mutex [on|off]  默认打开

    是否打开Nginx的负载均衡锁,此锁能够让多个worker进程轮流的、序列化地与新的客户端建立连接。而通常一个worker进程的负
    载达到其上限的
7/8master就尽可能不再将请求调度至此worker


2)、lock_file /path/to/lock_file;

        

3)、accept_mutex_delay #ms; 默认500ms

     accept锁模式中,一个worker进程为取得accept锁的等待时长。如果某worker进程在某次视图取得锁时失败了,至少要等待#ms
    能再一次请求锁。详细看“
Nginxaccept_mutex配置分析”

 

4)、multi_accept on |off 默认off

    是否允许一次性响应多个用户请求。当一批用户请求进来时,是否让一个worker响应所有请求。允许的话效率有提高

 

5)、use [epoll|rtsig|select|poll]

     定义使用的事件模型,建议让nginx自动选择。Linux一般会选poll

 

6)、 worker_connections #;

     每个worker能够并发响应最大请求数。但要注意,系统每处理一个请求就要消耗一个套接字文件。做反向代理的时候要把
    worker_rlimit_nofile的值X2

 

 

5、用于调试的配置

 

用于调试、定位问题,只在调试nginx时使用:

1)、daemon [on|off]

     是否让nginx运行在后台:默认为on,调试时可以设置为off,使得所有信息直接输出控制台、屏幕


2)、master_process on|off

     是否以master/worker模式运行nginx,默认on;调试时可以设置off,只运行一个worker进程。


3)、error_log/path/to/error_log level; 默认error级别

     错误日志文件及级别。调试可使用debug级别.但要求编译时必须--with-debug 启用debug功能

 

 

6、虚拟主机的配置

  使用虚拟机来配置站点,每个虚拟主机使用一个server{}段,非虚拟主机的配置或公共配置,需要定义在server{}之外,http{}之内

 

1)基于IP及端口的虚拟主机

  一段server{...}就是一个虚拟主机,要基于端口,只要把端口改为相应的即可

 

    http

    {

     #第一个虚拟主机

      server

          {

           #监听的ip和端口

           listen 192.168.61.141:80;

           #主机名称

           server_name 192.168.61.141;

           #访问日志文件存放路径

           access_log logs/server1.access.log combined;

           location/

               {

                 #默认首页文件,顺序从左到右

                 index index.html index.htm;

                 #HTML网页文件的存放目录

                 root /web/server1;

                 }

         }

        

     #第二个虚拟主机

     server

         {

           #监听的ip和端口

           listen 192.168.61.141:80;

           #主机名称

           server_name 192.168.61.141;

           #访问日志文件存放路径

           access_log logs/server2.access.log combined;

           location/

                {

                  #默认首页文件,顺序从左到右

                  index index.html index.htm;

                  #HTML网页文件的存放目录

                  root /web/server2;

                 }

         }

    }

 

2)基于域名的虚拟主机

  注意写法*.a.com www.a.com之外的所有*.a.com二级域名的访问都由它来处理

    http

    {

     #第一个虚拟主机

     server

         {

           #监听的ip和端口

           listen 80;

           #主机名称

           server_name www.a.com *.a.com;

           #访问日志文件存放路径

           access_log logs/server1.access.log combined;

           location/

                 {

                   #默认首页文件,顺序从左到右

                   index index.html index.htm;

                   #HTML网页文件的存放目录

                   root /web/server1;

                 }

         }

        

         #第二个虚拟主机

         server

             {

                 #监听的ip和端口

                 listen 80;

                 #主机名称

                 server_name www.b.com *.b.com;

                 #访问日志文件存放路径

                 access_log logs/server2.access.log combined;

                 location/

                   {

                         #默认首页文件,顺序从左到右

                         index index.html index.htm;

                         #HTML网页文件的存放目录

                         root /web/server2

                   }

             }

    }

 

3)参数详细说明

 

 a)、listen

    listen地址[:端口]

     常用参数

     default_server:定义此serverhttp中默认的server.如果所有的server都没有使用listen参数,那么第一个server即为默认
            server

     rcvbuf=size:接受缓冲大小

     sndbuf=size:发送缓冲大小

     ssl:是否https 服务

 

 b)、server_name

     设定主机名,可以跟多个。名称中可以使用通配符和正则表达式。当nginx收到一个请求时,会取出其首部的server的值,跟众
    多
server_name进行比较,方式:

          (1)先做精确匹配 www.dx.com

         (2)左侧通配符匹配 *.dx.com

         (3)右侧通配符匹配 www.*

           (4)正则表达式匹配 ~^.*\.dx\.com$

 

 c)、server_name_hash_bucket_size  32|64|128

     为了实现快速主机查找,nginx使用hash表来保存主机名

 

 d)、location [=|~|~*|^~] uri { ... }

      location @name { ... }

      功能:允许根据用户请求的URI来匹配指定的各location以进行访问配置;匹配到时,将被location块中的配置所处理

           =:精确匹配

           ~:正则表达式模式匹配,匹配时区分字符大小写

           ~*:正则表达式模式匹配,匹配时忽略字符大小写

           ^~:只需要前半部分与uri匹配即可,左侧匹配,不检查正则表达式

       匹配优先级:

           字符字面量最精确匹配、正则表达式检索(由多个时,由第一个匹配到的所处理),按字符字面量

 

  e)、文件路径定义

       1root path

       设置web资源路径,用于指定请求的根文档目录,从跟开始匹配

         rootroot/URI

       2alias path

         指定路径别名,只能用于location中,从最后一个/开始匹配

         aliasalias/

       3index file....

         定义默认页面,可以跟多个值。自左向右匹配

       4error_page code ... [=[response]] uri

         当对于某个请求发回错误时,如果匹配上了error_page指令中设定的code,则从定向至新的新URI错误重定向

       5try_files path1 [path2...] uri;

         自左向右尝试读取由path所指定路径,在第一找到即停止并返回,如果所有path均不存在,则返回最后一个uri

         例:  

        location~* ^/document/(.*)${

                   root/www/htdocs

                   try_files$uri /docu/$1 /temp.html

         }

 

         http://www.wangfeng7399.com/documents/a.html

         http://www.wangfeng7399.com/docu/a.html

         http://www.wangfeng7399.com/temp.html

 

7、网络连接相关的设置

 1)、keepalive_timeouttime;

      保持连接的超时时长,默认为65s

  (2)、keepalive_requests n

      在一次长连接上允许承载的最大请求数

  3)、keepalive_disable[msie6|safari |none]

      对指定的浏览器禁止使用长连接

  4)、tcp_nodelay on|off

      keepalive连接是否使用tcp_nodelay选项

  5)、client_header_timeouttime

      读取http请求首部的超时时长

  (6)、client_body_timeouttime

      读取http请求包体的超时时间

  (7)、save_timeout time

      发送响应的超时时长

 

8、对客户端请求的限制

  (1)、limit_except method...{ ... }

      指定范围之外的其他方法的访问控制,只能用于location

  2)、client_max_body_size 20m

      客户端http请求包体的最大值,常用于限定客户端所能够请求的最大包体。根据请求首部中的Content-Length来检查,以避免无
     用的传输。

      例如:

      网站上限定了用户最大上传文件为1G,如果不设置这个参数做限制,那么当用户已经上传了1G后,网站程序才能发现不能给它上
       传了,已经浪费了前面的时间和资源了。这里可以提前从
heart头部读取到要传送的文件的大小,提前拒绝不必要的上传!

 (3)、client_max_body_buffer_size 256k

      请求包体内存缓存区大小,为什么这个值这么小呢?可以想象一下如果有10000个并发会占用多少内存?所以,如果超过这个大
     小会存在
client_body_temp_path 磁盘上

  4)、limit_rate speed

      限制客户端每秒传输的字节数,默认为0,表示没有限制

  (5)、limit_rate_after time

       nginx向客户端发送响应报文时,如果时长超过了此处指定的时长,则后续的发送过程开始限速

     例如:一个下载网站,很多用户在下载,当传送了一定时间,占用了不少带宽,为避免对其他用户的影响,开始根据limit_rate
     限速了

        

9、对客户端请求的特殊处理

  (1)、ignore_invalid_headerson|off

      是否忽略不合法的http首部,默认为onoff意味着请求首部中出现不合规的首部将拒绝响应,只能用于serverhttp

  2)、log_not_found on|off

      用户访问的文件不存在时,是否将其记录到错误日志中

  3)、resolver address

      指定nginx使用的dns服务器地址

  4)、resolve timeout

     指定DNS解析超时时长,默认为30s

  5)、server_tokens on|off

      是否在错误页面中显示nginx的版本号,为了安全,一般都要关闭

 

 

10、文件操作的优化

  1)、sendfile on|off

      是否启用sendfile功能

  2)、aio on|off

      是否启用aio功能

  3)、open_file_cache man=N[incative=time]|off

       是否打开文件缓存功能

       max:用于缓存条目的最大值,允许打开的缓存条目最大数,当满两类以后将根据LRU(最小最少连接数)算法进行置换

       inactive:某缓存条目在指定时长内没有被访问过时,将自动被删除;通常默认为60s

 

       缓存的信息包括:

         文件句柄、文件大小和上次修改时间

         已经打开的目录结构

         没有找到或没有访问权限的信息
   (4)、open_file_cache_errorson|off

        是否缓存文件找不到或没有权限访问等相关信息

   5)、open_file_cache_validtime

        多长时间检查一次缓存中的条目是否超出非活动时长,默认为60s

   6)、open_file_cache_min_use#

        inactive指定的时长内被访问超过此处指定的次数时,才不会被删除

   7)、open_log_file_cachemax=1000 inactive=20s min_uses=1 valid=1m;

        打开日志缓存,最大条目1000条,非活动时间20秒,最少使用1次,有效时间1分钟

                  

 

11http核心模块的内置变量:

  $uri:当前请求的uri,不带参数

   $request_uri:请求的uri,带完整参数

   $hosthttp请求报文中host首部;如果请求中没有host首部,则以处理此请求的主机的主机名代替

   $hostnamenginx服务运行所在主机的主机名

   $remote_addr:客户端IP

   $remote_port:客户端port

   $remote_user:使用用户认证时客户端用户输入的用户名

   $request_filename:用户请求中的URI经过本地rootalias转换后映射的本地的文件路径

   $request_method:请求方法

   $server_addr:服务器地址

   $server_name:服务器名称

   $server_port:服务器端口

   $server_protocol:服务器向客户端发送响应时的协议,如http/1.1http/1.0

   $scheme:在请求中使用的scheme 映射协议本身的协议

   $http_HEADER:匹配请求报文中指定的HEADER$http_host匹配请求报文中的host首部

   $sent_http_HEADER:匹配响应报文中指定的HERDER,例如$http_content_type匹配相应报文中的content-type首部

   $document_root:当前请求映射到的root配置

 

12URL rewrite

  nginx通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但不支持else

  该模块需要PCRE支持,应在编译 nginx 时指定PCRE源码目录

 

  a)、nginx rewrite指令执行顺序:

    1)、执行server块的rewrite指令(这里的块指的是server关键字后{}包围的区域,其它xx块类似)

    2)、执行location匹配

    3)、执行选定的location中的rewrite指令

       如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件

       如果循环超过10次,则返回500 Internal ServerError错误

 

  (b)、break指令

    语法:break;

    默认值:无

    作用域:server,location,if

     停止执行当前虚拟主机的后续rewrite指令集

    break指令实例:

     if ($slow) {

         limit_rate 10k;

         break;

     }

 

  (c)、if指令

    语法:if(condition){...}

    默认值:无

    作用域:server,location

    对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行。

    if条件(conditon)可以是如下任何内容

    一个变量名;false如果这个变量是空字符串或者以0开始的字符串;

     使用= ,!= 比较的一个变量和字符串

     是用~ ~*与正则表达式匹配的变量,如果这个正则表达式中包含};则整个表达式需要用" ' 包围

     使用-f !-f 检查一个文件是否存在

     使用-d, !-d 检查一个目录是否存在

     使用-e !-e 检查一个文件、目录、符号链接是否存在

     使用-x !-x 检查一个文件是否可执行

    if指令实例

 

     if ($http_user_agent ~ MSIE) {

         rewrite ^(.*)$ /msie/$1 break;

     }

 

     if ($http_cookie ~*"id=([^;]+)(?:;|$)") {

         set $id $1;

     }

 

     if ($request_method = POST) {

         return 405;

     }

 

     if ($slow) {

         limit_rate 10k;

     }

 

     if ($invalid_referer) {

         return 403;

     }

 

   (d)、return指令

     语法:

    return code;

    return code URL;

   return URL;

      默认值:无

      作用域:server,location,if

    l  停止处理并返回指定状态码(code)给客户端。

    l  非标准状态码444表示关闭连接且不给客户端发响应头。

    l  0.8.42版本起,return 支持响应URL重定向(对于301302303307),或者文本响应(对于其他状态码).

    l  对于文本或者URL重定向可以包含变量

 

    (e)、rewrite指令

      语法:rewrite regexreplacement [flag];

      默认值:无

      作用域:server,location,if

    l  如果一个URI匹配指定的正则表达式regexURI就按照replacement重写。

    l  rewrite按配置文件中出现的顺序执行。flags标志可以停止继续处理。

    l  如果replacement"http://""https://"开始,将不再继续处理,这个重定向将返回给客户端。

     flag可以是如下参数

        last 停止处理后续rewrite指令集,然后对当前重写的新URIrewrite指令集上重新查找。

        break 停止处理后续rewrite指令集,并不在重新查找,但是当前location内剩余非rewrite语句和location外的的
            非
rewrite语句可以执行。

        redirect 如果replacement不是以http:// https://开始,返回302临时重定向

        permant 返回301永久重定向

       最终完整的重定向URL包括请求scheme(http://,https://),请求的server_name_in_redirect port_in_redirec三部分
       ,说白了也就是http协议 域名 端口三部分组成。

 

    rewrite实例

 

     server {

         ...

         rewrite ^(/download/.*)/media/(.*)..*$$1/mp3/$2.mp3 last;

         rewrite ^(/download/.*)/audio/(.*)..*$$1/mp3/$2.ra last;

         return 403;

         ...

         }

    如果这些rewrite放到“/download/ location如下所示, 那么应使用break而不是last , 使用last将循环10次匹配,然后返回
     500错误:

 

     location /download/ {

         rewrite ^(/download/.*)/media/(.*)..*$$1/mp3/$2.mp3 break;

         rewrite ^(/download/.*)/audio/(.*)..*$$1/mp3/$2.ra break;

         return 403;

     }

 

 

    如果客户端使用IE浏览器,则重定向到/nginx-ie目录下

    if ($http_user_agent~ MSIE) {

         rewrite ^(.*)$ /nginx-ie/$1 break;

    }

 

    禁止访问多个目录:

    location ~^/(cron|templates)/ {

         deny all;

         break;

    }

 

    禁止访问以/data开头的文件:

    location ~ ^/data {

         deny all;

         break;

    }

 

    禁止访问.sh.flv.mp4为文件名后缀的URL地址:

    location ~.*\.(sh|flv|mp4)?$ {

         return 403;

    }

 

    注意:

    (1)、在写URI地址的时候,留意.是否要转义字符操作,测试过暂时不用,但老师是写的。

    (2)、如果正则表达regex式中包含“}”或“;, 那么整个表达式需要用双引号或单引号包围.

    (3)、如果被替换的URI中含有参数(即类似/app/test.php?id=5之类的URI),默认情况下参数id=5会自动附加到替换串上,如
        果不想自动附带后面的参数,可以在
replacement后加一个问号。如下,我们加了一个自定义的参数user=$1,然后在结尾
        处放了一个问号
?,把原请的参数去掉。

    例:

    rewrite ^/users/(.*)$/show?user=$1? last;

    rewrite ^/test(.*)$http://www.test.com/home? permanent; 结果是http://www.test.com/home

 

   (f)、rewrite_log指令

     语法:rewrite_log on|off;

     默认值:rewrite_log off;

     作用域:http,server,location,if

     开启或关闭以notice级别打印rewrite处理日志到error log文件。

    例:

    rewrite_log on;

    error_loglogs/xxx.error.log notice;

n  打开rewrite on

n  error log的级别调整到 notice