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

Nginx配置实战

2016-06-08 11:39 471 查看

一、虚拟主机(virtual host)

    详见官网(搜关键词location):http://nginx.org/en/docs/http/request_processing.html

   (1)假设所有server { } 均listen 端口 * : 80,在形如以下这种配置,nginx仅根据请求header中的“Host”字段来进行路由选择对应的虚拟server。如果没有匹配到任何server_name或者请求header中没有“Host”字段,则nginx匹配此端口对应的默认虚拟server。在这里就是排在第一位的虚拟server,这也是nginx标准的默认server选择方式;但也可以指定默认server,0.8.21以上版本形如listen
 80  default_server,早期版本中形如listen  80 default。

特别的,指定默认server是监听端口的属性,而不是server_name的属性。

      server {

                               listen     80;

                               server_name  example.org  www.example.org;

                               ...

          }

   (2)假设所有server{ } 均listen具体的 ip:port,在形如以下这种配置,nginx会对照server块中的listen配置,先测试请求的IP/Port,然后在匹配到的server块中再接着测试请求header中的“Host”字段,若在该server块中没有server_name匹配此“Host”,则请求会被相应的默认server所处理。由于default是listen的属性,因此不同的ip:port可以分别指定为相应的默认server。

         server {

                listen     192.168.1.1:80;

                server_name example.org www.example.org;

                ...

     }

   (3)阻止没有“host”字段的请求,server可以直接丢弃这类请求,按以下方式配置。非标准码444意为关闭连接,0.8.48以上版本中 server_name的默认设置就是"",因此这里可以省略不写"",而在早期版本中默认的server_name是主机的hostname。

      server{

                listen     80;

                server_name "";

                return     444;

     }

二、location匹配规则

    详见官网(搜关键词location):http://nginx.org/en/docs/http/request_processing.html

网上半桶水货的讹传太多,官网才是权威的来源。。。

   (1)首先搜索最长匹配的文字字符串规则(即非正则表达式规则),不管这些常规的文字字符串规则是按照什么顺序先后出现的,即这些常规文字字符串规则出现的先后顺序不影响nginx匹配文字字符串规则的结果。

   (2)其次搜索匹配的正则表达式规则,按照正则表达式规则出现的先后顺序进行匹配,一旦匹配上则停止继续搜索正则表达式规则,并执行该正则表达式所对应的location块。

   (3)最后若没有搜索到匹配的正则表达式规则,则使用在(1)中搜索到的最长匹配的文字字符串规则。

特别的:location / { }可以匹配所有的请求,因此其在最长文字字符串匹配规则中的优先级也是最低的,location规则仅匹配请求行中的URI段而不匹配请求参数。

当请求是 / 时,只会被匹配到location / {index xxx yyy},此时index指令会先后测试这些指定的index files,假设index指令形如index index.html index.php;若index.html不存在而index.php存在,则nginx会重新发起一个内部重定向,重新进行location匹配,就好像这个请求是从客户端发起的。

另外,目前location的正则匹配规则中没有取“非”语法。

三、context继承性

nginx配置文件采用树形结构组织,使用一系列的括弧({ })嵌套来定义层次结构,在nginx中这些括弧所定义的区域被称为“contex”。由于一个context可以被另一个context所包含,nginx提供了指令的继承级别:如果一个指令在多个嵌套的区域内有效,那么在更宽泛的context下所定义的指令将会被传递到child contexts并作为其默认值;child contexts也可以随意覆盖这些值。

    
main context(global context):位于任一context之外,它表述了nginx配置最宽泛的环境,定义了最基础的影响整个程序的细节,很多指令不能被低层的context继承。可定义user、worker_processes、worker_cpu_affinity、worker_rlimit_nofile、error_log、pid等普通细节。[/code]
events context:位于main context内,nginx使用event-based的连接处理模型,它设置了nginx如何处理连接。

http context:包含指令以及其它context,定义了如何处理http或https连接。

sever context:允许重复定义,每个实例定义一个特定的虚拟server用于处理客户端的请求,nginx根据listen和server_name来选择使用哪个虚拟server来响应一个请求。在这个context里可以定义指令覆盖http context中定义的很多指令。

location context:位于 sever context。

other context:比如split_clients、perl 、map、geo、types、charset_map。

upstream context:配置了"upstream" servers,定义了一个server池可供nginx发送代理请求。

if context:类似传统程序中的if声明,在if context中return和rewrite指令被认为是可靠安全的。

最后建议少用if context而是多用其它sibling context:(1)if context未经过大量测试;(2)nginx已优化用于选择server context和location context的算法。

原文详见:

https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts

    指令proxy_set_header比较特殊:nginx允许重新定义或增加传递给proxied server的header域字段,字段的值可以是文本、变量或二者的组合。当且仅当当前context level 没有设置任何proxy_set_header指令当前context
level才会从前面的context level继承proxy_set_header指令;这就意味着若当前context level存在proxy_set_header指令则上一个context level的任一proxy_set_header指令均不会被继承(即对当前context level无效)。

四、反向代理

可以增加其它header字段或cookie字段,增加cookie字段的指令类似如下:

proxy_set_header  Cookie  "$http_cookie; cookie _name_xx=value_yy";

    当nginx反向代理一个请求时会自动调整从客户端收到的header信息:

   (1)丢弃任何值为空的header字段;

   (2) 名称带有下划线的header字段被视为非法并丢弃,除非underscores_in_headerson;

   (3)”Host” 字段值会被重写为 $proxy_host(upstream ip/name和port);

   (4)”Connection”字段值被设置为”close”,即告诉upstreamserver一旦nginx响应了原始请求即关闭和upstream server的连接,upstream server不可认为此连接是长连接。 

    原文详见:

https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching

五、rewrite(break | last | return)

Syntax: rewrite 
regex
 
replacement
 
[flag];
  

Default: —

Context:
server
location
if
 

Flag: break, last, redirect, permanent

  rewrite使用PCRE正则表达式来改变请求的URI,rewrite指令的执行方式如下:

    (1) 位于server level(server context) 的rewrite指令按先后顺序执行;

    (2) 重复地:

      <1> 基于请求URI匹配location;

      <2> 在匹配的location中按先后顺序执行rewrite指令;

      <3> 如果URI被 rewritten,循环执行该过程,但最多不超过10次。

break: 终止rewrite模块当前指令集合的执行,如果break是在location中,那么该location中的其它非rewrite指令将继续执行。

last: 终止rewrite模块当前指令集合的执行,发起一个内部重定向,重新搜索进行location匹配。

redirect: 返回302临时重定向,当替换后的URI(
replacement
 )不是以“http”或“https”开头时使用。

permanent: 返回301永久重定向。

如果
replacement
 中包含新的请求参数,那么之前请求的参数将追加在新的参数后,如果不希望之前的参数被追加,那么紧接着replacement放置一个“?”即可。 形如:

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

如果rewrite正则表达式中包含 ”}” 或 “;” ,那么整个正则表达式应该被单引号或双引号所包围。$request_uri表示请求的URI。

return指令: 停止处理并返回指定的状态码,非标准状态码444关闭一个连接且不发送响应头。return语法如下,当URL作为唯一的参数且以“http”、“https”、“$scheme”开头时发送的状态码是302。

return code [text];

return code URL;

return URL;

测试break的方式如下:各testx.php 打印自身文件名。

case 1:

    if ( $request_uri = "/test.php" ){

      rewrite ^/.*  /test1.php break;

    }

    rewrite ^/.*  /test2.php break;

    location ~ ^/test  {  #此location context中无rewrite指令

       ……

       fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

       ……

}

测试表明:打印的结果“test1”,即“rewrite^/.*  /test2.php break;”不会被执行,而搜索匹配location正则仍然继续执行,也即只是servercontext的rewrite模块执行被终止了。

case2:在case1的locationcontext中增加指令:“rewrite ^/.*  /test3.phpbreak;”,

打印的结果是“test3”。

case3:在case1的基础上增加一个location,其它保持不变。

       location ~ ^/test1 {

                rewrite ^/.*  /test3.php last;

                ……

        }

打印的结果是“test3”,测试表明 “rewrite ^/.*  /test2.php break;”没有被执行。

综上可知:(1)server context中的“rewrite 
regex
 
replacement
 
break
一旦执行将会使得server context中的其它任何rewrite都不会被执行;(2)location
context
中的“rewrite 
regex
 
replacement
 
last
被执行后不会再去搜索匹配server context中的rewrite指令,而只会去搜索匹配location context。

六、其它相关

   (1)listen address[:port] [backlog=number],参数backlog 限制了用于存放处于挂起状态连接的队列最大长度, 已连接但未进行accept处理的SOCKET队列大小,即这些连接已经完全建立了,但还没有被处理,其默认值是 -1。当一个连接请求到达时,如果此时队列满了,客户端会收到连接拒绝(“Connection refused”)。

    php-fpm的backlog大小设置跟php-fpm的处理能力有关,backlog太大了,导致php-fpm处理不过来,nginx那边等待超时,断开连接,报504 gateway timeout错。同时php-fpm处理完准备write 数据给nginx时,发现TCP连接断开了,报“Broken pipe”。 php-fpm的backlog太小的话,nginx之类的client请求,根本进入不了php-fpm的accept queue,报“502 Bad Gateway”错。所以,这还得去根据php-fpm的QPS来决定backlog的大小。计算方式最好为QPS=backlog

    详见:http://nginx.org/en/docs/http/ngx_http_core_module.html

相关:http://www.cnxct.com/something-about-phpfpm-s-backlog/

http://mp.weixin.qq.com/s?__biz=MjM5NzUwNDA5MA==&mid=201005717&idx=1&sn=74036633114ee6212e57ee4576dbfcbc&3rd=MzA3MDU4NTYzMw==&scene=6#rd

   (2)以下是一个静态集群中的配置:当访问一个文件失败时可进行rewrite,这样其它location就可以可处理了,这里用到了try_files 语法。      

    


七、配置实例

以下示例中每个servercontext 可以分别存放在不同的文件中,并使用include将其包含在主配置文件的末尾即可,形如 include  vhost/v1.conf;include  vhost/v2.conf;还可以将rewirte规则用lua语法写在文件中,然后使用rewrite_by_lua_file包含相应的lua文件即可。 

 

#user nobody;

worker_processes  8;

worker_cpu_affinity 00000001 0000001000000100 00001000 00010000 00100000 01000000 10000000;

worker_rlimit_nofile 204800;

 

#error_log logs/error_log  debug;

error_log   /home/log/error_log  notice;

pid       /home /var/nginx.pid;

 

 

events {

   use epoll;

   worker_connections  204800;

}

 

 

http {

   include      mime.types;

   include      upstream.conf;

   default_type application/octet-stream;

 

   ignore_invalid_headers  off;

   server_names_hash_bucket_size 128;

   client_header_buffer_size 4k;

   large_client_header_buffers 4 32k;

   client_max_body_size 3m;

 

   client_body_buffer_size 8k;

   client_body_timeout 15;

   client_header_timeout 10;

   send_timeout 240;

 

   sendfile       on;

   tcp_nopush     on;

   tcp_nodelay    on;     

 

   fastcgi_connect_timeout 5;

   fastcgi_send_timeout 10;

   fastcgi_read_timeout 10;

   fastcgi_buffer_size 64k;

   fastcgi_buffers 4 64k;

   fastcgi_busy_buffers_size 128k;

   fastcgi_temp_file_write_size 128k;

   fastcgi_intercept_errors on;

 

    keepalive_timeout  0;

   #keepalive_timeout  65;

 

   gzip on;

   gzip_min_length 1k;

   gzip_buffers 4 16k;

   gzip_http_version 1.0;

   gzip_comp_level 2;

   gzip_types text/plain application/x-javascript text/css application/xml;

   gzip_vary on;

 

   #problem_tracing off;

   log_format  main  '$remote_addr - $remote_user [$time_local]"$request" '

           '$status $body_bytes_sent "$http_referer""$http_cookie" "$http_user_agent" '

           '$request_time $http_x_logid $http_x_routerip$server_addr $upstream_addr $host '

           '"$http_x_forwarded_for" ';

   

   server {

       listen     8080;

       server_name  xx.com yy.com;

       more_set_headers 'Server: Nginx;

       error_page 400 403 404 500 501 502 503 504 505 http://uu.com/ error.html;

 

            set_real_ip_from 192.0.0.0/8;

            real_ip_header X-Real-IP;

       access_log  /home/log/access_log  main;    

       

       location / {

           root   /home/app/site;

           rewrite  ^/aa/v1/(.*)$  /ee/index.php last;

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

           rewrite  ^/bb.icon$    /img/bb.icon break;

           rewrite  ^/.*  /default/index.php last;

       }

     

       location ~ ^/(ee|default)/index.php$ {

           root   /home/app/web;

           fastcgi_pass   unix:/home/php/var/php-cgi.sock;

           fastcgi_index  index.php;

               fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

               fastcgi_split_path_info^(.+\.php)(.*)$;

               fastcgi_param PATH_INFO$fastcgi_path_info;

           fastcgi_param LOGID $logid;

           include       fastcgi_params;

       }

    }

   

   server {

       listen    8080;

       server_name ww.com zz.com;

       more_set_headers 'Server: Nginx;

       error_page 400 403 404 500 501 502 503 504 505 http://uu.com/error.html;
 

            set_real_ip_from 192.0.0.0/8;

            real_ip_header X-Real-IP;

       access_log  /home/log/access_log  main;

 

       location ~ ^/(js |img|css)/ {

           root    /home/app/static;

           expires  30d;

       }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息