close

引用網址:http://www.jianshu.com/p/374c938a9915

这两天读了读Nginx的官方文档,记个笔记。

启动nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
./nginx
Starting, Stopping, and Reloading Configuration
nginx -s signal

stop -> fast shutdown
quit -> graceful shutdown
reload -> reloading the configuration file
reopen -> reopening the log files
Unix tools kill
  • kill -s QUIT 1628
  • 找到pid的两个方法
    • nginx.pid文件,在/usr/local/nginx/logs or /var/run
    • ps -ax |grep nginx
server context
  • context的概念,每行以分号结尾的都是一个指令,大括号套一系列的指令就是context。
  • 一个http可以包含多个server。
  • server里面listen 表明这个server的端口号。
  • root,web的根目录。
  • server_name就是host,一个server Context可以配置多个server_name
    • 如:server_name localhost localhost.org;
  • server_name可以使用通配符,可以使用正则表达式,匹配规则:
    1. Exact name
    2. Longest wildcard starting with an asterisk, such as *.example.org
    3. Longest wildcard ending with an asterisk, such as mail.*
    4. First matching regular expression (in order of appearance in the configuration file)
  • 如果host header不能够匹配任何一个server_name,可以设置default_server来处理它。
    • 如:listen 80 default_server;
location
  • location指令有两种不同的参数:

    • 前缀字符串(pathnames)

      • 那些以该前缀字符串开头的的URIs都会匹配到。
      • 如:

        location /some/path {
            ...
        }

        这个会匹配/some/path/test 但是不会匹配 /test/some/path

    • 正则表达式

      • 大小写敏感的前面加一个~

        location ~ \.html? {
            ...
        }

        这个会匹配url中包含.html或者.htm的,任何位置都可以。

      • 大小写不敏感的加~*
    • 匹配规则,正则表达式拥有的更高的优先级,除非用了^~修饰符。^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。
    • 确切的匹配的逻辑:
      1. Test the URI against all prefix strings.
      2. The = (equals sign) modifier defines an exact match of the URI and a prefix string. If the exact match is found, the search stops.
      3. If the ^~ (caret-tilde) modifier prepends the longest matching prefix string, the regular expressions are not checked.
      4. Store the longest matching prefix string.
      5. Test the URI against regular expressions.
      6. Break on the first matching regular expression and use the corresponding location.
      7. If no regular expression matches, use the location corresponding to the stored prefix string
  • location context中的指令

    • root指令来声明访问静态文件的路径,如uri是/images/example.png,如果匹配到的location的root指令的值是/data,那么就会把/data/images/example.png作为响应。
    • proxy_pass指令,将请求打到配置的url上,被代理的server的响应到客户端。
    • 如:

      server {
          location /images/ {
              root /data;
          }
      
          location / {
              proxy_pass http://www.example.com;
          }
      }
使用变量

在配置nginx的时候可以使用变量,变量以$开头,变量在运行是得到对应的值,然后作为参数传给指令。有很有预定义的变量,如core HTTP varabiles,可以用set map和geo指令来自定义变量。大多数的变量都是在运行时得到值并且包含与特定请求相关的信息。注意是特定请求不是context。

返回特定的状态码
  • 最简单的方式是使用return指令返回特定的状态码。

    • 第一个参数是状态码,第二个参数是重定向的url或者返回体中的文字(只限于301、302、303、307)。

      location /wrong/url {
          return 404;
      }
      
      location /permanently/moved/url {
          return 301 http://www.example.com/moved/here;
      }
url重写
  • 通过rewrite指令进行url重写,在server和 location里面都可以使用rewrite指令。
  • 一共有三个参数,第一个是匹配url的正则表达式,第二个参数是重写的url,第三个参数是一个标记是可选参数。
  • uri可以多次更改,uri会依次匹配每个rewrite指令。
  • 第三个参数,last和break的区别
    • 两个值在server context中表现一致,跳过剩下的rewrite指令,进行location匹配。
    • 在location context中,last会跳出当前location寻找新的location匹配,而break不会再去匹配其他的location,在当前location请求对应的uri。
  • 小心循环重定向,尽量在server context里面进行url重写。
  • 例子:

    • 多个rewrite指令,如果都不匹配返回403

      server {
          ...
          rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
          rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
          return  403;
          ...
      }
    • 循环重定向

      location = error.html {
          rewrite /error.html /error.html last;
          fastcgi_pass 127.0.0.1:9000;
      }
    • break

      location /users/ {
          rewrite ^/users/(.*)$ /show?user=$1 break;
      }
handling errors

通过error_page指令,来处理错误。

  • 当发生404错误时候,返回一个自定义的页面

    error_page 404 /404.html;
  • 当发生404的时候,重定向到一个新的url

    location /old/path.html {
        error_page 404 =301 http:/example.com/new/path.html;
    }
  • 内部重定向

    • 配置

      server {
          ...
          location /images/ {
              # Set the root directory to search for the file
              root /data/www;
      
              # Disable logging of errors related to file existence
              open_file_cache_errors off;
      
              # Make an internal redirect if the file is not found
              error_page 404 = /fetch$uri;
          }
      
          location /fetch/ {
              proxy_pass http://backend/;
          }
      }
    • 如果/images/some/file没有找到,它就会被替换成/fetch/images/some/file,然后寻找新的location,然后再打到被代理的服务器。
    • open_file_cache_errors指令用于组织文件找不到时的报错信息,这里就不需要打开了,因为文件找不到时候已经被处理掉了。

根目录和index文件
  • 通过root指令来声明根目录的路径,root指令可以放到http, server或者location的任一层级里。子层级重新定义的root会覆盖父层级的root。
  • 例子

    server {
        root /www/data;
    
        location / {
        }
    
        location /images/ {
        }
    
        location ~ \.(mp3|mp4) {
            root /www/media;
        }
    }
  • 如果一个请求以斜杠结尾,nginx认为它想访问一个目录然后会去寻找index文件,index指令用来定义index文件的名称,默认是index.html。
  • 如果index文件不存在会报404,但是如果想列出该目录下的文件,则使用audoindex指令。
    • 如:
      location /images/ {
          autoindex on;
      }
  • 可以在index指令后面列出不止一个文件名字,中间用空格分开,nginx按顺序查找,然后返回第一个可访问的。
  • 为了返回index文件,nginx检测文件是否存在然后将文件名字连接到获取的请求的uri上进行内部重定向。
  • 例子

    • 配置:

      location / {
          root /data;
          index index.html index.php;
      }
      
      location ~ \.php {
          fastcgi_pass localhost:8000;
          ...
      }
    • 如果请求的uri是/path/并且/data/path/index.html不存在,但是/path/index.php是存在的,它匹配到了第二个location,达到被代理的服务上。
Trying Serveral Options
  • try_files 指令检测指定的文件或者目录是否存在,如果不存在进行内部跳转或者返回一个指定的状态码。

    • 如:

      server {
          root /www/data;
      
          location /images/ {
              try_files $uri /images/default.gif;
          }
      }
    • 如果uri所请求的文件不存在就会内部重定向到/www/data/images/default.gif
    • 第二个参数也可以是一个指定的状态码。
      • 如:
        location / {
            try_files $uri $uri/ $uri.html =404;
        }

 

将一个请求打到被代理的服务器
  • 在location里面使用proxy_pass指令来指定代理的地址,地址可以包含端口号。
  • 例如:

    location /some/path/ {
        proxy_pass http://www.example.com/link/;
    }
    
    location ~ \.php {
        proxy_pass http://127.0.0.1:8000;
    }
  • 注意下第一个例子,如果代理的地址包含一个uri,/link/。它将会替换请求的uri中匹配location参数的那部分
  • 如果请求是/some/path/page.html,uri则会被代理成:http://www.example.com/link/page.html
  • 如果代理的地址没有uri,那么将整个uri传递过来。
  • 将请求打到非http服务:
    • fastcgi_pass 把请求打到FastCGI服务器
    • uwsgi_pass uwsgi服务器
    • scgi_pass SCGI服务器
    • memcached_pass memcached 服务器
传递请求头
  • 默认的,nginx重新定义两个header,"Host"和"Connection",并且排除掉值为空的header。"Host"的值是$proxy_host变量的值,"Connection"设置成close。
  • 使用proxy_set_header来改变header,这个指令可以放到location或者更高的层级,它也可以在特定的server context或者http块中指定。
  • 如:

    location /some/path/ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://localhost:8000;
    }
  • 如果不想让某个header传给被代理的服务器,将其置空。

    location /some/path/ {
        proxy_set_header Accept-Encoding "";
        proxy_pass http://localhost:8000;
    }
选择出口IP
  • 代理服务器可能有多个ip地址,对于一个特定的被代理的server可以选择一个特定的ip地址。
  • 使用proxy_bind来指定ip地址。ip地址也可以使用变量,如$server_addr,指定的是接受请求的那个ip
  • 例子:

    location /app1/ {
        proxy_bind 127.0.0.1;
        proxy_pass http://example.com/app1/;
    }
    
    location /app2/ {
        proxy_bind 127.0.0.2;
        proxy_pass http://example.com/app2/;
    }
    
    location /app3/ {
        proxy_bind $server_addr;
        proxy_pass http://example.com/app3/;
    }

 

代理一组服务器
  • 使用upstream指令来定义一组服务器,指令放在http context里

    • 如:

      http {
          upstream backend {
              server backend1.example.com weight=5;
              server backend2.example.com;
              server 192.0.0.1 backup;
          }
      }
  • 使用proxy_pass指令把请求打到被代理的服务器上

    • 如:

      server {
          location / {
              proxy_pass http://backend;
          }
      }
选择一种负载均衡方法
  1. 默认的是权重轮询算法,nginx会按照各个server的权重比来分发请求。

    • 如:

      upstream backend {
         server backend1.example.com;
         server backend2.example.com;
      }
  2. 最少连接法:每次都选择连接数组少的server,如果有多个server的连接数相同,再根据这几个server的权重分发请求。

    • 例:

      upstream backend {
          least_conn;
      
          server backend1.example.com;
          server backend2.example.com;
      }
  3. ip哈希:使用IPv4的前三个八字节位或者IPv6的全部来计算哈希值,所以相同地址的请求始终会打到相同的Server上,除非这个server不可用。

    • 如果一个server需要暂时移除,使用down参数来避免请求打到这台机器上,应该哈希到这台机器上的请求会自动的发送到组里的下一台。
    • 如:

      upstream backend {
          ip_hash;
      
          server backend1.example.com;
          server backend2.example.com;
          server backend3.example.com down;
      }
  4. 哈希:使用自定义的key去进行哈希计算。

    • 通过consistent参数使用ketama一致哈希算法来减少增减服务器对客户端的影响。

      • 例:

        upstream backend {
            hash $request_uri consistent;
        
            server backend1.example.com;
            server backend2.example.com;
        }
      • 上面的就是通过uri进行哈希计算。
  5. 最小响应时间:对于每个请求,nginx选择平均等待时间最小并且连接数最少的。

    • 通过least_time的参数来确定平均等待时间的计算方式。
      • header: Time to receive the first byte from the server
      • last_byte: Time to receive the full response from the server
    • 如:

      upstream backend {
          least_time header;
      
          server backend1.example.com;
          server backend2.example.com;
      }
服务器权重
  • 默认的权重是1,通过weight参数来指定权重值。
  • 通过backup来标记备用服务器,如果其他的都宕机了,请求会打到备用的服务器是上。
  • 例:

    upstream backend {
        server backend1.example.com weight=5;
        server backend2.example.com;
        server 192.0.0.1 backup;
    }
服务器慢启动
  • 对于刚刚恢复的服务器,如果一下子被请求淹没可能会再次宕机。
  • 可以通过server指令的slow_start参数来让其权重从0缓慢的恢复到正常值。
  • 例:

    upstream backend {
        server backend1.example.com slow_start=30s;
        server backend2.example.com;
        server 192.0.0.1 backup;
    }
  • 注意如果一个组里面只有一个server,那么max_fails,fail_timeout和slow_start参数都会被忽略。并且这个服务器永远都不会被认为是不可用的。
Enabling Session Persistence
  • Session持久性是指nginx识别客户端的session然后把同一个session的请求路由到同一个server上。
  • nginx支持三种session持久的方法,通过sticky指令去设置。

    • sticky cookie方法。通过这种方法,当server第一个响应的时候,nginx添加一个cookie来标识是哪个server响应的,当它下次请求的时候,会带着cookie,nginx会把请求路由到同一台server。

      • 例:

        upstream backend {
            server backend1.example.com;
            server backend2.example.com;
        
            sticky cookie srv_id expires=1h domain=.example.com path=/;
        }
    • sticky_route方法,使用这种方法,nginx第一个收到请求的时候会给客户端下发一个路由。后续的请求都会带着路由参数,nginx再来判断请求该打到哪个server上。路由信息可以通过cookie或者uri获取到。

      • 例:

        upstream backend {
            server backend1.example.com route=a;
            server backend2.example.com route=b;
        
            sticky route $route_cookie $route_uri;
        }
    • cookie learn 方法。通过这种方法,nginx通过检测请求和响应来寻找session标记。通常,这些标记通过cookie传递。如果一个请求的包含的session标记已经learned,nginx将会把请求打到正确的server上。
    • 例:

      upstream backend {
         server backend1.example.com;
         server backend2.example.com;
      
         sticky learn 
             create=$upstream_cookie_examplecookie
             lookup=$cookie_examplecookie
             zone=client_sessions:1m
             timeout=1h;
      }
    • 在这个例子中,server通过在响应中设置一个"EXAMPLECOOKIE"来标记一个session。
    • create的参数指定一个变量来指示一个session的创建,在这个例子中,server发送"EXAMPLECOOKIE"表示新的session建立。
    • lookup的参数指定如何寻找一个已经存在的session,在这个例子中,通过查找客户端的"EXAMPLECOOKIE"来搜索现有的session。
    • zone 指定一块共享的内存来保存sticky sessions的信息。上个例子中,这块空间叫做client_sessions,大小为1M。
限制连接数量
  • 可以通过max_conns参数来限制连接数,如果达到了最大连接数,请求就可以放到通过queue指令生命的队列中来等待后续的处理 ,queue指令设置了可以放到队列中得最大的请求数、
  • 例:

    upstream backend {
        server backend1.example.com  max_conns=3;
        server backend2.example.com;
    
        queue 100 timeout=70;
    }
  • 如果队列排满或者在可选参数timeout设置的时间内无法选择上游服务器,客户端将接到一个错误。
  • 注意如果闲置的keepalive连接在另一个worker processes中打开了max_conns限制会被忽略。导致的结果是,在多个工作进程共享内存的配置中,连接的总数可能会超过max_conns的值。
被动的健康监测
  • 当nginx认为一个server不可用,它会暂时停止向这个server转发请求直至nginx再次认为它是可用的。
  • nginx通过两个参数来控制nginx的判断
    • fail_timeout,当在fail_timeout时间段内,失败次数达到一定数量则认为该server不可用。并在接下来的fail_timeout时间内不会再将请求打到这个server上。 - max_fails,这个max_fails就是上面说的失败的一定数量。
  • 默认的值是10秒和1次尝试。
  • 例:

    upstream backend {                
        server backend1.example.com;
        server backend2.example.com max_fails=3 fail_timeout=30s;
        server backend3.example.com max_fails=2;
    }
主动的心跳检测
  • 使用health_check指令来检测server是否可用,除此之外还要使用zone指令。
  • 例:

    http {
        upstream backend {
            zone backend 64k;
    
            server backend1.example.com;
            server backend2.example.com;
            server backend3.example.com;
            server backend4.example.com;
        }
    
        server {
            location / {
                proxy_pass http://backend;
                health_check;
            }
        }
    }
  • 在上个例子中,nginx每五秒请求一次backend组里的每台机器,请求地址是"/",如果失败或者超时(或者返回的状态码不是2xx或者3xx),nginx就认为这个server宕机了。nginx将停止向它转发请求,直至其再次通过心跳检测。
  • 可以通过参数控制health_check指令的行为。
  • 例:

    location / {
        proxy_pass http://backend;
        health_check interval=10 fails=3 passes=2;
    }
  • 上个例子是每十秒检测一次,如果失败了3次就认为宕机了,如果成功2次就认为通过了检测。
  • 也可以检测特定的uri
  • 例:

    location / {
        proxy_pass http://backend;
        health_check uri=/some/path;
    }
  • 通过match块自定义成功的状态。

    http {
        ...
    
        match server_ok {
            status 200-399;
            body !~ "maintenance mode";
        }
    
        server {
            ...
    
            location / {
                proxy_pass http://backend;
                health_check match=server_ok;
            }
        }
    }
  • 上个例子中要求status在200到399之间,并且body满足提供的正则表达式。
  • match块中可以包含一个status的状态,一个body的状态和多个header的状态。

    match welcome {
        status 200;
        header Content-Type = text/html;
        body ~ "Welcome to nginx!";
    }
  • 使用!

    match not_redirect {
        status ! 301-303 307;
        header ! Refresh;
    }
  • 上个例子表示status不是301、302、303或者307,并且header中不包含Refresh。

至此Nginx笔记结束,了解了这些后,对于看懂一个Nginx的配置,了解Nginx能够实现什么功能和对其进行小改应该会有一定的帮助。

 

arrow
arrow
    文章標籤
    nginx
    全站熱搜

    龍之家族 發表在 痞客邦 留言(0) 人氣()