Nginx之二nginx web服务配置详解

1、简要回顾

IO模型:php

    blocking、nonblocking、multiplexing、event-driven、AIOhtml

 

Nginx特性:non-blocking、event-driven、AIO前端

  因此Nginx在典型的这几项IO模型当中的所谓实现高并发服务器端编程的概念上都是支持的。node

  Nginx其此版本号为奇数的一般为开发版,为偶数的一般为稳定版,固然做为咱们来说,一般在生产环境中可以用到的应该是stable版本的。nginx

    Nginx的开发也遵循这样的一种特性,一旦它的某一个偶数版升级之后那么随之而来的比它大一个数字的奇数版将成为新的开发板,这是须要注意的一点。在1.8.0当中,他已经引进了incorporating许多新特性包括几个著名的新特性。web

 

2、Nginx1.8所引入支持的新特性(要作到了解)

  • hash load balancing method(基于hash计算的负载均衡方法)
  • backed SSL certificate verification(支持后端SSL证书校验)
  • thread pools support(支持线程池)

    之后要定义一个对应的Nginx线程,能支持多少个并发链接,能够经过线程池定义,这是一个很强大的也是很新的特性。正则表达式

  • proxy request buffering(代理请求的缓冲)

    那这样一来新特性的引入势必可以更多的更强大的对于所谓代理模式下的链接的管理功能。算法

 

2、Nginx经常使用指令介绍

一、主配置段的指令

  • 正常运行的必备配置:
  user USERNAME [GROUPNAME];

    指定运行worker进程的用户和组,组身份身份可省。它的组身份与用户身份是统一使用同一个身份来定义的,这一点有别于httpd。若是在编译时已经使用--user,--group指定了的话,那在配置文件中它颇有多是被注释掉的,由于它默认就会使用那一个对应的用户名来进行定义了。编程

    :user nginx nginx;后端

    注意:每个指令必须使用分号结尾不然视为语法错误。

 

pid /path/to/pid_file;

    指定Nginx守护进程的pid文件的位置;若是在编译时已指定在配置文件中可能被注释掉代表使用编译时指定的默认路径;

    例:pid /var/run/nginx/nginx.pid;

    大多数守护进程都会有pid文件来保存其pid信息的,包括此前学的httpd,甚至因而以fpm模式工做的php,它们都有本身的pid文件;

 

worker_rlimit_nofile number;

    指定全部worker进程(加起来)所可以打开的最大文件句柄数;说白了就是所可以打开的最大文件数量。由于worker进程都是以Nginx用户的身份运行的,因此是一共可以打开的文件的总数。

    Linux系统上包括管理员默认都受限于所可以运行的资源的数量。每一个用户默认可以打开的文件数是1024个,可是对于任何一个服务器软件来说,若是它要监听在某个套接字上提供服务的话,那么任何一个客户端链接连入以后它都须要一个套接字文件来维持这个链接。由于Linux要靠此特性来达到一切皆文件的哲学思想或者说这样一种目的。所以,站在这个角度来说,若是咱们Nginx下可以支持1万个并发链接,那么它至少须要维持1万个套接字文件,还不包括本身打开本身的配置文件。对于要想可以支持更大的并发链接数,咱们对应的每个worker进程是否是应该设置它所可以单进程打开的文件数量提高呢?由于worker进程是以Nginx用户的身份来运行的,所以咱们为了可以worker进程接受更多的并发链接,运行worker进程的用户得可以同时打开更多的文件才能够的。默认状况下的1024对于一个高并发的worker进程来说显然是过小过小了,因此必要时咱们能够经过调整此值对应于设置一个worker进程所可以打开的最大文件数。

 

worker_rlimit_core size;

    用来指明全部的worker加起来所可以使用的整体的核心文件的最大大小。指的就是这个进程所可以使用的核心数量的或者说核心文件的最大文件体积大小。此指令通常不多须要咱们手动调整。

 

  • 性能优化相关的配置:
worker_processes #;

    指定所可以打开的worker进程的个数;一般应该为物理CPU核心数-1或-2,即一般应该略少于CPU物理核心数;要留出一个核为系统本身所使用。可是如今Nginx的版本支持它的值为auto,Tengine能够设置为auto表示自动设定,自动打开几个,自动判断。

 

worker_cpu_affinity cpumask …;

    设定把worker进程绑定在哪些CPU上的。此处指明CPU用的是cpumask,cpumask为CPU掩码,CPU掩码指的是什么呢?假如主机上有四颗CPU,它可能用8位二进制来表示,那这四颗CPU怎么标识呢?在其对应上为1就表示那一颗CPU被选中了,如一号CPU为0000 000一、二号CPU为0000 00十、三号CPU为0000 0100,四号为0000 1000。因此这个worker_cpu_affinity后面所跟的若是只绑定在前三颗上面,只写前三个就可。

    例如:worker_cpu_affinity 00000001 00000010 00000100;

    但例如:0011表示第一和第二同时两颗。

    对于Nginx来说,咱们说过,它的工做特性是一个线程或者一个worker进程响应n个用户请求的。那么即使咱们启动少于CPU的物理核心数的进程,可是它依然面临一个问题,如咱们当前这个主机上所同时运行的进程数量可能会比较多,百十个进程应该是很常见的,因此即使有4个物理核心,在某一时刻,在当前CPU上所运行的也未必是Nginx的worker进程。那结果就是对于很是繁忙的worker进程来说,它有可能被频繁的调度来调度去。那颇有可能咱们启动了假设叫三个进程,这三个进程到底谁运行在哪一个CPU上是无法肯定的。咱们Linux的核心会动态的根据当前CPU的空闲数以及须要运行的进程数调度,所以多是不断的在进行变化。这样一来带给咱们的最大坏处在于因为在CPU上须要作进程切换(context switch),进程切换会消耗时间会浪费CPU,因此进程切换自己会带来额外的CPU消耗,会产生CPU的没必要要的消耗,所以为了尽量的压榨CPU,发挥CPU的最后一点一滴的性能,这就是咱们要设置进程数要少于CPU核心数的缘由。

    咱们能够这么作,明确的指明把每个进程绑定在指定CPU上,好比一号进程明确说明绑定在一号上面,它毫不在其它CPU核心上运行,二号进程绑定在二号CPU上,三号进程绑定在三号CPU上。因此这样一来,这三个进程必定不会被调度到其它核心上去了,可是其实这样是不可能避免进程间的切换的,由于咱们虽然把它绑定在这颗CPU上并不意味着这个CPU不能运行其它进程。可是至少保证了这个对于Nginx这一个进程自己不用调度到其它CPU上去了,那带来的好处是这个进程本身的缓存不会失效,说白了就是若是说这个Nginx在运行时,咱们这个Nginx进程加载了不少数据到CPU的二级缓存、一级缓存、一级指令缓存包括一级数据缓存,若是咱们不幸的把它调度到另一颗CPU上去,那在第一颗CPU的缓存的内容就会失效了,到另一颗CPU缓存还须要从新加载的,因此咱们一旦把进程绑定的话,咱们这个进程本身曾经加载到CPU上的缓存即使这个进程被调度出去,等一会它在回来运行时,那些缓存却依然有效,因此保证了缓存的有效性。可是它却没办法避免进程切换。

    优势可以提高CPU缓存的命中率;

    可是不能避免context switch,咱们真正要想极端去优化Nginx所在的服务器的话,还有一种方法;这种方法可能须要一些别的技能来支撑了。如:开机的时候设定主机上四颗CPU有三颗都不被内核使用,这叫CPU隔离,因此一开机咱们就事先说明,内核只能使用这一颗CPU。那这样子一来,内核想调度任何进程就只能在第四颗CPU上调度。那开机完成之后,咱们还要隔离中断,咱们系统可能有不少中断,中断可能由硬件产生也多是软中断,此处仅指硬件中断,硬件中断包括网卡上有报文到来或者咱们的硬盘上有IO完成等等。这些也都从CPU上隔离,因此它不处理中断,也不接受任何进程调度。当启动完之后,咱们明确说明第一个进程绑定在第一颗,第二个进程绑定在第二颗,第三个进程绑定在第三颗。那这三个进程不受内核调度,因此不再会有其它进程到这颗CPU上运行了,那这就意味着专CPU专用,第一颗CPU只为运行Nginx,Nginx不再会被切换出去了。因此这个Nginx但凡须要运行,它就本身紧紧霸占住第一颗CPU,充分发挥CPU每一时刻的运算能力来支撑Web服务的访问。

    那这样一来,三个worker线程启动起来之后,假如说每个worker线程能够支持1万个并发,那三万个就很轻松拿下了。可是这须要作两个前提,第一,咱们在启动OS时须要隔离出来这三颗CPU,第二,咱们须要把中断处理从这三颗CPU上剥离出去才能够。

 

timer_resolution interval;

  计时器解析度:下降此值,可减小gettimeofday()系统调用的次数;

    这种无谓的系统调用次数或者是咱们用不到那么高的时候,下降这个值减小这个次数会在必定意义上提高Nginx性能的或者提高咱们整个系统性能的。对于一个很是繁忙的服务器这点是不容忽略的。

    可用来减小下降worker线程中的计时器的解析度,下降解析度之后带来的结果是,说白了就是减小发起gettimeofday()这么一个系统调用,任何一个进程运行过程中,若是系统调用不少,任何一次系统调用的发生必然会产生软中断,产生软中断的直接结果就是模式转换,每一次的模式转换必然会消耗时间。由于咱们说过不少次,一个生产力很是强的进程应该把大量时间用在用户空间,那所以timer_resolution这个时间解析度为何要用到这个东西呢?

    咱们简单举个例子:好比任何一个请求到达Nginx的时候Nginx就得响应它,响应完之后就得记录日志了,可是到日志中会记录时间。那所以一旦有用户请求到达,咱们这边处理响应而要记录日志的话那么它必需要获取系统当前时间并记录在日志文件中。怎么获取系统时间呢?经过gettimeofdate来获取时间然后把这个结果再保存到日志文件中。而若是咱们的时间解析度过大的话,就可能带来的结果是他一秒钟就解析一千次,一秒钟就发起一千次系统调用,若是我把这个下降一点,好比100ms解析一次,那就意味着一秒钟只解析10次了。若是指定1s一次那就意味着1s钟只解析1次,可是咱们知道时间解析度越低它的精准度就越小,时间解析度越高精度就越高,正如咱们的显示器同样,分辨率越高,显示的就越逼真越清晰可是它所须要消耗的资源必定也是越大的。

    那所以为了提升性能,这个时间解析度应该是下降的。只要咱们对于它的时间解析度要求不是特别高的话。

 

worker_priority number;

  指明worker进程的优先级(nice值)。

    可是这个优先级是使用nice值来指明的,说白了其实这里是指明nice值

    nice值的范围是-20~19,-20对应的优先级是100,19对应的优先级是139。数字越小优先级越高。默认状况下每个进程它的nice值都是0,所以其优先级为120,数字越小优先级越高,优先级越高它越被优先调度到CPU上被运行。

    例如:worker_priority -20;指定其100的优先级。那么如此高的优先级就说明咱们的Nginx但凡是有可能,只要没有比它优先级更高的,那么他将会被排在前面优先被调度到CPU上运行。这对于一个Web服务器来说尤为是反代模式下的Web服务器或者是咱们支持更高并发的Web服务器来说这算是一个比较有效的设定。再次提醒,nice值越小,其对应的优先级越高。可是只有管理员才有权限调低nice值,好在咱们启动Nginx的时候是以root用户启动的。只不过运行worker时,它们才会由nginx普通用户来运行它,在此以前它能够彻底以root用户的身份来设定其nice值。

 

    以上是与系统优化相关的指令,这四项尤为是前两项,几乎任什么时候候咱们新配置一个Nginx都要本身手动指定,务必要理解他们指的是什么。

 

  • 事件相关的配置:

    即放在event当中的通常而言用于使用的相关配置。

accept_mutex {on|off};

  master调度用户请求至各worker进程时用的负载均衡锁;on表示能让多个worker轮流的、序列化的去响应新情求;

    mutex称为互斥锁,所谓互斥锁就是独占的,通常而言,任何一个进程持有锁之后其它进程都是被排除在外的,叫排它锁。固然这样解释其实并不精确,只是为了可以便于理解的。那么这个accept_mutex有什么用呢?

    内部调用用户请求至各worker时的负载均衡锁,这是一个。说白了,做为Nginx而言,它是由一个主控进程master生成多个worker进程响应用户请求的,问题是当一个请求到达时咱们应该使用哪个worker来响应它呢?由于worker和请求之间并非一一对应的,因此当一个新的用户请求到达时,新的用户请求主控进程必须从这多个worker进程中来响应的,挑选谁呢?而accept_mutex其实就是实现这个功能的。

    若是说咱们打开此功能,即启用了accept_mutex,表示让多个worker轮流的序列化的响应新请求。就是有先有后的、一个挨一个的来响应新的用户请求,不然的话,咱们的master有可能随机的。

 

accept_mutex_delay time;

    若是说accept_mutex启用了,若是某一个worker正在尝试接受用户请求的时候,那其它用户请求咱们要延迟多长时间等待。因此要否则怎么叫互斥锁呢?一个请求来了你们不能抢,轮到谁了就让谁来响应。可是这个worker有可能会忙不过来,那就须要指定延迟或等多长时间。这么长时间之后,则有可能会选择为下一个。这个不是特别关键;

 

lock_file file;

    accept_mutex用到的锁文件路径(互斥锁锁文件路径);

    既然咱们指明接受用户请求的互斥锁,那么这个锁的锁文件应该是谁,就是lock_file。咱们在编译时其实指明过这个锁文件了。

 

 use [epoll|rtsig(实时信号)|select|poll];

  用于指明使用的事件模型或者是复用模型机制;不建议手动指定,建议让Nginx自行选择;

    use method;注意此处的method可不是http协议的请求方法,而是指明链接处理方法,什么叫链接处理方法?对于一个并发服务器来说,有多个用户请求到达时,咱们怎么去处理用户请求呢?有多种机制,像基于事件驱动、基于复用器、基于select()来响应、基于poll()来响应、基于epoll()来响应或者叫基于event driven来响应等等。因此这里的use定义使用的事件模型的。

    Nginx会自行实现最优化选择,好比在Linux主机上能使用epoll它就不会使用select,咱们说过epoll才是真正支持事件驱动的机制,你要使用select就跟咱们的httpd prefork没什么区别了。它的并发链接数也势必会大大的下降的。因此说对于Nginx而言,虽然咱们说它是支持使用event driven机制甚至是支持AIO的,可是事实上做为用户来说,能够指明咱们到底使用哪种类型,就使用这个指令进行指定。

 

worker_connections #;

  设定单个worker进程所可以处理的最大并发链接数量;

    worker的链接数,即一个worker进程所可以接受的最大并发链接数。

    例:假设worker_connections 10240;那请问当前Nginx最多能接受的最大并发链接为多少个?不是10240,这取决于worker_proccesses有多少个,若是其定义了为3个,这里定义为10240,那就是3*10240。固然若是前面定义为8个,此处定义为10240也没用,由于不可能能达到8万多个,由于咱们的套接字有限,可是至少咱们此处的这个数字不该该成为限制。

    所以它所可以接受的最大并发链接数等于worker_connections*work_processes。可是它有可能会小于这个值,由于这个值若是设定的大于65535个的话,通常来说他就不会真正有效了。为了不单个进程自己不会由于的数量小于这个值的话,能够直接定义worker_connections为51200,不少人的配置中多是这么定义的。因此说,这个参数也是常常必需要调的参数之一。

 

  • 用于调试、定位问题:

    注意:要想可以打开调试功能,咱们在编译时必需要使用—with-debug这个选项才能够,不然调试功能是没办法启用的。

daemon {on|off};

  是否以守护进程方式运行Nginx;调试时应该设定为off;

    说白了就是若是为on就把它运行为守护进程,若是off就不运行为守护进程。不运行为守护进程就意味着它运行在前台了。运行在前台它能够把各类日志或者错误信息输出到控制台上来,咱们能够在控制台上看到。这叫作daemon模式,因此在调试时将它定义为off,其它状况下应该设定为on。

 

  master_process {on|off};

  是否以master模型来运行Nginx;调试时能够设置为off;

    正常状况下应该以这种master模型运行Nginx,调试时能够设定为off;这就表示,你若是出于调试的目的只启动一个worker进程直接接受用户请求就不会说一个主进程一个子进程,由于主进程子进程两种方式不容易调试问题所在。

 

  error_log file | stderr | syslog:server=address[,parameter=value](记录到远程服务器) | memory:size(记录到内存中,内存大小) [debug | info | notice | warn | error | crit | alert | emerg];

    简单来说,格式为:

  error_log 位置 级别;

  若要使用debug级别,须要在编译Nginx时使用了—with-debug选项;

    这是用来而配置日志功能的,全部的错误日志相关信息都会指明保存在某文件中,用于帮咱们去排错的。简单来说,它的格式其实只有三段组成,第二段主要用于指明记录到哪,第三部分主要用于指明日志级别的。默认状况下,咱们一般都记录在本机指定位置下,而级别有可能为对应的warn或者notice。

    再次说明,只有使用—with-debug打开了调试功能时,咱们也才可使用debug这个级别。不然即使指定了这个指令也无效。

 

    以上是Nginx主配置段中经常使用到的一些参数,咱们作了一些简要的说明。

 

总结:常须要进行调整的参数

    再次说明,咱们未来在配置时,最经常使用须要修改的四个参数为:worker_proccesses、worker_connections、worker_cpu_affinity以及worker_priority。都跟worker相关。

 

示例:

    若指望修改的配置生效:

 

    这样Nginx就可以读取新配置了。

 

    只要不改Nginx端口,只须要使用nginx –s reload便可生效。

 

新改动配置生效的方式:

  nginx –s reload      #这表示向nginx的主控进程传一个参数

 

  除了reload接受的其它参数还有:stop、quit、reopen

  

3、Nginx做为WEB服务器时使用的配置

  Nginx全部跟WEB相关的配置都放在http这个上下文中,因此咱们称之为http的上下文http的配置段

 

  这个配置段是由httpd的核心模块引入的,咱们前面说过,Nginx的配置文件或者咱们整个Nginx它是由多个模块组成的,这个模块其中有核心模块,像咱们刚才讲的都是由核心模块提供的。那除了Nginx本身的核心模块以外,他还有http的标准模块、有可选的http模块还有邮件相关的模块以及第三方模块。在这些众多模块当中,其中有一个叫作标准http的模块,而标准http的模块中有一项叫作http core,说白了就是为了提供http协议相关的功能而提供的一个核心模块。它用于实现控制端口、location、错误页面、别名以及其它一些最基础的相关配置,咱们称为HTTP core

 

http {}:由ngx_http_core_module模块所引入;

 

    因此咱们只要用这个模块就会用到http的相关配置的部分。它是用来作什么的?说白了,http core是用来配置一个静态的WEB服务器,它可以做为像httpd同样来工做的静态WEB服务器。咱们若是想让它工做在反向代理模式下,须要使用额外的反向代理模块来实现。

 

    这个配置段当中的配置框架配置主体部分:

 

    大致上遵循这样的格式,首先:

 

http { upstream {  #用到负载均衡或反向代理时会引入的上下文 … } server { location URL {#有点相似于DocumentRoot,可是location跟DocumentRoot还不彻底同样,由于对于咱们的VirtualHost来说DocumentRoot只能有一个,
             #可是对于一个虚拟主机server来说,location能够有多个。因此它有点相似于咱们对应与httpd中的location容器,用来定义URL和本地的对应关系的。 root “
/path/to/somedir”; … }#相似于httpd的<Location>,用于定义URL与本地文件系统的映射关系;因此咱们说在一个server中能够有n个location,
      #由于在一个server中它对应的那个站点的URL的起始事件能够多个,好比www.magedu.com下的images、bbs等等,每个路径均可以单独分别指定的把网页放在不一样位置。
      #就这一点而言,它事实上比httpd要灵活。同一个路径或同一组URL下能够映射多组不一样的路径。而在location中,它还能够对应一个URL,这个URL对应在什么地方呢?
      #那通常而言,它因为要对本地文件系统创建映射关系,因此这里边一般会有一个root用来本地文件系统路径。 location URL {
if … { … } }#同时,在location中还能够引入一个新的上下文叫if语句;若是符合某个条件,那么应该…。它还能够有条件判断的功能; } #每个server有点相似于httpd中的<VirtualHost>;因此它是用来定义虚拟主机的 server{ … } }

  注意:与http相关的配置指令必须仅可以放置于http、server、location、upstream、if上下文中。但有些指令仅应用于这5种上下文的某些中而非所有,即不一样指令它的应用位置、可以生效的位置各不相同。

 

这些配置框架中常常用到的配置指令:

  • server{}

    定义一个虚拟主机;

    演示效果:

 

    这是基于端口的虚拟主机,基于IP的只需不一样的listen IP:PORT,基于名称的时序server_name不一样。

 

  • listen

  指定监听的地址和端口;

  listen address[:port];   listen port;

  (能够只指端口不指地址表示默认监听本机上的全部地址,也能够只指地址不指端口表示默认监听在80端口)

  对于Nginx来说,其listen有三种格式:

    此前说过,Linux主机上表示套接字的地址家族有三种方式,一IPv4二IPv6三本机上通讯能够基于Unix Socket文件。因此说咱们对应的Nginx的虚拟主机也能够listen一个Unix的path路径,表示本地的一个socket类型的文件,一旦监听在socket类型的文件上,这意味着客户端只能是本机了。

    那这么复杂的指令究竟是所谓哪般呢?为什么要这么复杂呢?它所指明的这些参数应该很是容易理解,像:

    ssl:表示若是咱们要启用ssl功能,应该指定ssl;

    spdy:这是Google改进的http协议的版本,它比1.1更加优越,可是如今http2.0版本已经出现了,依然取代spdy这种格式了。如有兴趣,可自行了解。

    rcvbuf:接收的缓冲的大小;

    sndbuf:发送的缓冲大小;

    accept_filter:接收时使用的过滤器;

 

    因此咱们在一个listen指令上能够定义很是复杂的选项,固然对于此处而言咱们彻底不必搞得这么麻烦,只须要知道咱们有一个listen指令能够指定监听的地址和端口便可。

    它的更为复杂的功能其实咱们只有在特殊状况下单独设定其接受缓冲和发送缓冲大小时偶尔才会用到,因此再也不说其更为复杂的功能。

 

  • server_name NAME […];

    指定主机名,后可跟多个主机名;名称还可使用正则表达式(使用正则表达式时须要以~开头做为引导)或通配符;

    server_name只能用在server中,别的地方不能使用,因此每个指令的context表示他可用于的上下文是有要求的。

    当咱们有多个server时,当用户使用其中的某一个server时,咱们应该匹配到哪个server上?如:

server{ server_name www.test.com; } server{ server_name *.test.com }

  当用户匹配到www.test.com应该匹配到哪个上面?

  因此此处有作匹配时的匹配法则

  (1)先作精确匹配检查;

    也就是说若你访问到的主机名恰好与某一个server主机名如出一辙,并且他没有所谓的通配的概念。那么这个就彻底匹配到了,全部优先级最高的为精确匹配检查。

  (2)左侧通配符匹配检查;

    如写成*.magedu.com,当用户去访问mail.magedu.com,第一个不匹配,因而去检查第二个。而第二个这个通配符正好在左侧,而有的是这样写的:

 

server { server_name www.test.com; } server { server_name *.test.com; } server { server_name mail.*; }

 

 

  当用户访问mail.magedu.com的时候,第二个与第三个都能匹配,若是左侧通配符能匹配因而就当即生效,不然再去检查右侧通配符。

 

 

  (3)右侧通配符匹配检查,如mail.*;

 

  (4)正则表达式匹配检查,如:~^*\.magedu.com\.com$;

 

  (5)default_server;

 

 

  若默认服务器未定义,那就自上而下找第一个server来匹配。

 

 

 

    因此说,当用户请求到达时,而咱们当前主机上定义了n个虚拟主机,那咱们应该应用在哪一个虚拟主机之上,事实上是由server_name后面这么一个固定的检查法则检查完之后进行肯定的。

 

  • root path;

 

 

  设置资源路径映射的;用于指明请求的URL所对应的资源所在的文件系统上的起始路径;

  放置的容器越大,范围越大,优先级越低。

 

 

  • location

 

    两种用法:

 

  location [ = | ~ | ~* | ^~ ] uri { ... }   location @name { ... }

 

    根据请求的URI设定特定请求的配置的。

 

   功能:容许根据用户请求的URI来匹配定义的各location;匹配到时,此请求将被相应的location配置块中的配置所处理,例如作访问控制等功能;

 

例:

 

 

  当用户在浏览器中输入http://www.test.com/bbs/时,它到底应用在哪一个location上呢?第一个与第三个可以匹配到,那到底以哪一个为准呢?因此说它也有相应的优先级了,好比:

 

  =:精确匹配检查;

 

       即错一个字符都不行;

 

       所以若是访问的是http://www.test.com/,并且location = /{...},那第一个就能匹配,但若是写的是http://www.test.com/bbs/,而且location写的是=,那它就不能被第一个匹配了。由于第一个必须是根,后面不能带任何东西,这叫作精确匹配。若是不带=表示,则起始路径的均可以被匹配。

 

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

 

  ~*:正则表达式模式匹配检查,不区分字符大小写;

 

  ^~:URI的前半部分匹配,不支持正则表达式;

 

  匹配的优先级:精确匹配(=)、^~、~、~*、不带任何符号的location;

 

 

 

  验证:

 

 

 

  由于此时匹配到的第三个到/vhosts/text下去找images,而后再images下找a.txt。

 

  对于Nginx而言,location是很是关键的。

 

 

 

  • alias path;

 

  用于location配置段,实现定义路径别名;

 

  这与httpd中的alias并无两样。用来实现路径映射;

 

    注意root表示指明路径为对应的location “/” URL;也就意味着你怎么指root,它都相对于”/”这个起始路径而言的。像刚才咱们访问images下面的a.txt,这个时候images自己也是相对于这个对应的/vhosts/下面补上这个images而言,说白了你不管路径怎么映射,它是起始于/images而言的。

 

    alias表示路径映射,即location指令后定义的URL是相对于alias所指明的路径而言;

 

  如:

 

    root:

 

 

定义: location /images/ { root "/vhosts/web1"; } 例如: 访问http://www.test.com/images/a.jpg表示访问的是服务器路径:/vhosts/web1/images/a.jpg

 

    alias:

 

定义: location /images/ { alias "/www/pictures"; } 例如: 访问http://www.magedu.com/images/a.jpg表示访问的是服务器目录下的:/www/pictures/a.jpg

 

  验证:

 

 

  对于alias而言这个location URL路径右侧的根相对于这个整个alias后面的根,因此在images下的全部文件是直接在这个/vhosts/web1目录直接去找的。而root是images左侧这个根相对于/vhosts/web1而言。

 

  • index file

  这是一个新的叫作index的模块所提供的;

  默认主页面:

  index index.php index.html;

  表示有两个页面自左而右能够做为主页面,先搜索index.php找不着的话再去找index.html;

 

 

  • error_page code […] [=code] URI | @name(错误码或响应码或状态码能够有多个)

  根据http响应状态码指明特用的错误页面;

    例如:

  error_page 404 /404_customed.html

    说明:404_customed.html放在什么路径下均可以,看error_page定义在什么位置,对应的就相对于那个对应你所所在的location中的root而言的。

  [=code]:可省略,若是要定义的话,表示以指定的响应码进行响应,而不是默认的原来的响应码;(好比找不到页面可能用404响应,但我把它定义成302就能够了);默认表示以新资源(即指定的网页)的响应码为其响应码。

  例如:

 

    这是Nginx自带的404错误页面;

  自定义:

       使用-t能够测试语法错误;

    咱们还能够自行定义它的响应码,如:

 

 

  • 基于IP的访问控制机制

  两个相关指令:

    •   allow IP/Network;
    •   deny IP/Network;

    基于IP的访问能够用在http、server、location中,看你的访问控制有多大的范围。

  举例:拒绝192.168.241.1访问演示:

   只容许192.168.241.0网段访问:

 

  • 基于用户的访问控制

  支持两种认证方式:basic、digest

  要想作基于用户的访问控制,只须要在须要作访问控制的配置段中使用以下指令:

 auth_basic “”; #至关于httpd的AuthName; auth_basic_user_file “PATH/TO/PASSWORD_FILE”;   #跟用户相关的帐号密码文件的位置;这个文件尽量隐藏起来,由于不是全部用户都会使用ls –a 来查看这个文件的,
                                #因此隐藏一下总然是由好处的。

  帐号密码文件建议使用htpasswd建立;htpasswd这个命令是由httpd提供的,所以须要安装httpd。

  • https服务:

  生成私钥,生成证书签署请求,并得到证书;

  演示示例:

    显示不可靠,由于浏览器没有导入CA的证书,因此它没办法验证是否可靠。

 

  • stub_status {on|off};

  状态页的启用或关闭;

  此指令仅能用于location上下文中;

  在此结果示例中:

  Active connections:活动链接数;指的是当前全部处于打开状态的链接数。若是向客户端代理的话也包括代理的。

  server accepts handled requests    #表示接收下来并已经处理的请求;

  70 70 47  #第一个数字表示已经接受过的链接数,第二个为已经处理过的链接数,第三个为已经处理过的请求数。因为咱们可能已经启用了链接处理功能,
         #因此请求数可能会大于链接数。在“保持链接”模式下,请求数量可能会多于链接数量。

    Reading:正处于接收请求状态的链接数;

    Writing:请求已经接收完成,正处于处理请求或发送响应的过程当中的链接数;

    Waiting:保持链接模式,且处于活动状态的链接数;(要么处于正在接收请求要么正在发送请求的状态中的链接数)

 

  • rewrite regex replacement flag;

    指的是URL rewrite,说白了是实现URL重写的。你原本请求的是某一个特定URL,服务器处理以后将URL悄悄的换成别的URL。

    例如:

rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;

       它所带来的效果是,好比说用户若是请求的是http://www.magedu.com/images/a/b/c/1.jpg,那它会把这个路径自动换成http://www.magedu.com/imgs/a/b/c/1.jpg

 

  URL重写在何时用到呢?好比,咱们网站从a域名改到b域名了,可是两个域名都是咱们的,咱们指望用户之后访问时看到的都是b域名,因此全部对于a域名的访问都改为b域名下的相关地址也是能够的。再否则,咱们原本的网站某个页面路径在某个URL下如今换成新的URL像咱们这里的images换成imgs也能够基于URL重写实现。

    固然在完成某些SEO时也有用,好比说咱们把这个动态的路径改为静态的方式,那么这会使得咱们缓存服务器能缓存下来并且SEO时还能提升咱们的权重。

  不过此处的flag倒是大有讲究的;

  flag:标识位

    •  last:一旦被此rewrite规则重写完成后,就再也不被后面的其它rewrite规则进行处理;而是由User Agent从新对重写后的URL再次发起请求并从头开始执行相似的过程。

    如:匹配规则有n条,用户请求来以后,检查第一条不匹配、第二条不匹配、…、第四条匹配了,后面的就不检查了。此时由于一重写已经成为了一个新的URL,这个新的URL会再次被从新发给Nginx服务器,Nginx 服务器同样会从第一条检查、第二条、…,若是检查第三条又被重写了,所以又一次改为新的URL再次发起请求从头至尾来检查。

    完成当前这个重写规则之后,重启处理机制。

    例如:咱们访问http://www.magedu.com/images/a/b/c/1.jpg经过URL重写会转换成http://www.magedu.com/imgs/a/b/c/1.jpg,对于这个新的请求来说,浏览器会从新用新的URL对Web服务器发起新的请求,Web服务器即Nginx收到这个新情求后同样会像此前处理任何一个请求同样处理这个请求,即此时还会再次检查这个规则,若是这个规则又能彻底匹配到它的话,还会再次重写,因此这叫重启。因此第一个请求咱们经过规则检查匹配到了,因此改为新的URL了,因此浏览器此时会从新对这个连接发新情求,这个新请求会通过规则的再次检查,若是检查之后没有被匹配,所以就不会被重写,因而请求就日后继续处理了。

    •  break一旦此rewrite规则重写完成以后,由User Agent对新的URL从新发起请求,且再也不会被当前location内的任何rewrite规则所检查;新请求的URL就不会再被任何重写规则所检查,直接进行后续处理。

    何时用到break呢?就是在很不幸的状况下,两条规则可能形成循环。例如:

... rewrite ^/images/(.*\.jpg)$ /imgs/$1 last; rewrite ^/images/(.*\jpg)$ /images/$1 last; ... 如:访问http://www.test.com/images/a/b/c/1.jpg <--> http://www.test.com/imgs/a/b/c/1.jpg
    •  redirect以302响应码(临时重定向)返回新的URL;

    何时才会用302响应呢?若是说咱们替换成一个目标位置是以http协议开头时是一个新的绝对路径时,能够以redirect实现。

    •  permanent以301响应码(永久重定向)返回新的URL;

 

  举例:

 

 

 

 

  • if

  语法:

  if (condition){…}

  应用环境:server、location;

  condition:

  (1) 变量名;

       变量值为空串,或者以“0”开始,则为false;其它的均为true;

       若是变量为空串,即变量没有值的话表示为假不然为真。所以任何空串或者任何为0的值甚至于任何以0起始的字符串其都为假不然则为真。

  (2) 以变量为操做数构成的比较表达式

       可以使用=、!=相似的比较操做符进行测试。

       好比,看看某个变量的值是不是咱们所请求的某个值。

  (3) 可实现正则表达式的模式匹配

       ~:区分大小写的模式匹配检查;

       ~*:不区分大小写的模式匹配检查;

       !~和!~*:对上述两种测试取反;

       须要注意的是,并非在配置文件中用到模式正则表达式越高级越好,不用正则表达式是最好的,由于正则表达式引擎在匹配时必然会消耗更多的CPU使用周期,会下降性能的。

  (4) 测试路径为文件的可能性

       -f:表示是否存在;

       !-f:表示是否不存在;

  (5) 测试指定路径为目录的可能性

       -d

       !-d

  (6) 测试文件的存在性(无论是目录仍是文件)

       -e

       !-e

  (7) 检查文件是否有执行权限

       -x

       !-x

  例如:

if($http_user_agent ~* MSIE){   #若浏览器类型为MSIE,即为微软浏览器

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

    }

       #http_user_agent为内建变量,表示客户端浏览器的类型;

    有些时候的URL重写是必须的,像根据客户端浏览器的不一样返回不一样的站点,定向至不一样的位置上去。这样可让用户有更好的用户体验。能够想象用户使用手机打开电脑版的页面的话那该是多么痛苦。

 

  • 防盗链

    假如站点的图片只容许站内连接或者不是咱们所容许的域名一般都不容许连接。

  locating ~* \.(jpg|gif|jpeg|png)$ { valid_referer none blocked www.test.com; #validreferer是Nginx自带的一个内置的指令,它用于定义哪一种引用是合法的。valid表示合法的、容许的,referer表示引用者,所以valid_referer表示合法的引用者是谁。none blocked表示不作阻止的。  if($invalid_referer){ #$invalid_referer是咱们的refereer模块所引入的一个变量,它表示但凡不可以被上面定义为合法引用的,通通都会归到不合法引用上面,因此若是说这个变量的值不为空,就说明这一次引用多是不合法的。由于为空就由于上面的已经被匹配了。 rewrite ^/ http://www.test.com/403.html;
 } }

 

  • 定制访问日志格式

    使用log_format指令进行定义,相似于在httpd中使用的log_format指令;

    若是想定义成兼容给咱们对应的日志格式如出一辙的话,此处要使用log_format,并查找服务器端所提供的或者服务器上模块所提供的内置的变量来相似使用兼容格式,叫combined来进行定义。log_format后接的为格式名。一旦咱们要想本身定义访问日志的话,千万要记得要使用access_log,如:

5、网络链接相关的配置

  咱们未来把Nginx做为一个反代服务器时有可能会用到。

    例:前端使用Nginx做为反代服务器,后端使用Tomcat做为Web服务器,经过Nginx访问Tomcat时老是会出现503超时,而直接访问Tomcat时是正常的,可是经过前端Nginx访问偶尔老是会出现超时,代理服务器上去取后端内容超时。出现这种状况推测颇有多是Nginx反代时它会本身构建一个请求报文到后端Tomcat,可是构建这个请求等待Tomcat响应的时间默认设置的太短,而Tomcat本身的处理多是须要必定的时长的。一旦这个时间太短的话,对方还没响应过来就超时了,事实上响应是正常的。

    这一些都跟网络链接相关,因此这个时候咱们就不得不调节这些跟网络链接相关的超时时长。

 

  • keepalive_timeout #;

  保持链接或长链接的超时时长,默认为75s;(对于负载均衡器来说,75有点大)

 

  • keepalive_requests #;

    在一次长链接上所可以容许请求的最大资源数;

 

  • keepalive_disable [msie6|safari|none];

    为指定类型的User Agent禁用长链接;

    禁用长链接,可是这种禁用并非禁用整个长链接的功能,而是只为特定类型的浏览器禁用长链接,由于有些浏览器在长链接的支持上是功能有限的。

 

  • tcp_nodelay on|off;

    是否对长链接使用TCP_NODELAY选项;

    通常来说,若是想提升用户体验的话,让用户一请求当即就能获得响应,咱们仍是应该启用tcp_nodelay,不让它延迟,每一个包都单独发送,不管它有多小。

    tcp是一种开销比较大的链接类型,由于任何一次数据发送以前都要先三次握手然后要四次断开。若是很不幸的是,某一个链接刚好它所发送的数据量很是小,访问这个页面下一共也只有几个字节或者十几个字节而已,若是咱们请求网站上的资源不少都是这很小的资源的话,会发现每个包单独封装并且没有使用长链接结果是大量的资源开销被浪费掉了,那为了不这么一种浪费,TCP在它的拥塞避免算法中有一种解决方案是它把屡次请求的小资源合并成一次大的响应过去,好比请求了不少东西每个都很小,把多个小的请求合并成一个响应报文响应过去了。这样子能够节约带宽能够节约请求次数。可是这样一来会有问题,想象一下对于Web站点来说,用户请求一个资源半天还没响应,为何呢?他等待跟其余包合并呢?这是没法接受的,因此在有些原本就具备的确拥有不少小资源的Web站点上,咱们不该该启用tcp_delay的功能,因此咱们把tcp延迟功能关闭,tcp_nodelay就表示tcp是否是不延迟,on就能够。

 

  • client_header_timeout #;

    读取http报文请求首部的超时时长;

    若是我么本身的服务器很繁忙本身带宽不够用,读别人读不到,由于别人挤不进来,那这个时候应该把此时长调长一些以便能读进来别人的请求,不过即使时间延长用户体验也是不好了。

    一个客户端发请求过来了,全部的数据流依然都是要编码成数据流式报文进行请求的。那咱们读了第一个首部、读第二个首部、…可是客户端的带宽过小了,半天读不到一个,那到底应该等多长时间呢?

 

  • client_body_timeout #;

    读取http请求报文的body部分的超时时长。

 

  • send_timeout #;

    发送响应报文的超时时长;

 

6、fastcgi的相关配置

    Nginx与php结合时他不能像httpd与php结合同样把php直接作成Nginx的模块,这是不支持的,因此若是你想构建LNMP,方法只能有一个,php要启用为fpm模型。

    在Nginx上要想配置用户请求php页面时可以发给fpm的php来提供服务的话,方法很是简单,配置文件中有示例:

 

    fastcgi_params文件中定义了如何把用户请求时的变量值映射提供给后端的fastcgi服务器的。

相关文章
相关标签/搜索