nginx:小知识

137 阅读5分钟

一、服务器名称

  1. server_name 匹配(性能)顺序:

    • 精确匹配;
    • 以星号开头的最长通配符名称,如:*.example.org
    • 以星号结尾的最长通配符名称,如:mail.*
    • 正则表达式(正则表达式匹配的位置会优先于普通前缀匹配的位置。 ~* .(gif|jpg|jpeg)$ 优先于 /documents/
  • 第一个匹配的正则表达式(按照配置文件中出现的顺序)。

    最好在可能的情况下使用精确名称。如果服务器最常请求的名称是 example.orgwww.example.org,则明确定义它们会更有效。

     # 建议
     server {
         listen       80;
         server_name  example.org  www.example.org  *.example.org;
         ...
     }
     ​
     # 不建议
     server {
         listen       80;
         # 特殊的通配符形式 ".example.org" 存储在通配符名称哈希表中,而不是精确名称哈希表中
         server_name  .example.org;
         ...
     }
    
  1. 名称使用通配符:

    通配符只能出现在域名的开头或结尾,并且只能出现在点的边界上。如:*.example.orgmail.*

  2. 名称使用正则表达式:

    • 必须以波浪号字符开头,同时不要忘了加 ^ $ 如:

    •  server_name  ~^www\d+.example.net$;
      
    • 包含字符“{”和“}”的正则表达式应该加引号:

    •  server_name  "~^(?<name>\w\d{1,3}+).example.net$";
      

      之后使用命名的正则表达式捕获作为变量使用:

       server {
           server_name   ~^(www.)?(?<domain>.+)$;
       ​
           location / {
               root   /sites/$domain;
           }
       }
      

二、负载均衡

  1. 支持以下三种方式:
    • round-robin(轮询):为默认配置。将请求以轮询的方式分发给应用服务器;
    • least-connected(最小连接数):下一个请求分配给当前连接数最少的服务器;
    • ip-hash(IP 哈希):使用哈希函数确定应选择哪个服务器以处理下一个请求(基于客户端的 IP 地址)。
  • round-robin 轮询
 http {
     upstream myapp1 {
         server srv1.example.com;
         server srv2.example.com;
         server srv3.example.com;
     }
 ​
     server {
         listen 80;
 ​
         location / {
             # 要为 HTTPS 而不是 HTTP 配置负载均衡,只需将协议设置为 "https"
             proxy_pass http://myapp1;
         }
     }
 }
  • 最小连接数负载均衡

使用最小连接数负载均衡时,nginx 将尽量避免向繁忙的应用服务器发送过多请求,而是将新请求分发到较不繁忙的服务器。

 upstream myapp1 {
     least_conn;
     server srv1.example.com;
     server srv2.example.com;
     server srv3.example.com;
 }
  • IP哈希

确保来自同一客户端的请求总是被定向到相同的服务器,除非此服务器不可用。

 upstream myapp1 {
     ip_hash;
     server srv1.example.com;
     server srv2.example.com;
     server srv3.example.com;
 }
  • 加权负载均衡

通过使用服务器权重,还可以进一步影响 nginx 负载均衡算法。在最新的nginx版本上,也可以对最小连接数和 ip-hash 负载均衡使用权重。

 upstream myapp1 {
     server srv1.example.com weight=3;
     server srv2.example.com;
     server srv3.example.com;
 }
  1. 健康检查

如果从特定服务器收到的响应出现错误,nginx 将将此服务器标记为失败,并将在一段时间内尽量避免选择此服务器用于后续的入站请求。

max_fails 指令,是设置一个服务器在与 nginx 通信的过程中,连续出现了指定次数的失败尝试,nginx 将把该服务器标记为失败。默认情况下,max_fails 设置为 1。当设置为 0 时,禁用对该服务器的健康检查。fail_timeout 参数定义了服务器被标记为失败的时间长短。在服务器失败后的 fail_timeout 时间间隔之后,nginx 将开始通过实时客户端请求对服务器进行平稳的探测。如果探测成功,服务器将被标记为存活。

三、配置https

配置HTTPS服务器,必须:

  • 监听套接字上启用ssl参数;
  • 指定服务器证书和私钥文件的位置。
 server {
     listen              443 ssl; #请用SSL
     server_name         www.example.com;
     ssl_certificate     www.example.com.crt;
     ssl_certificate_key www.example.com.key;
     ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
     ssl_ciphers         HIGH:!aNULL:!MD5;
     ...
 }

服务器证书是一个公共实体,会发送给连接到服务器的每个客户端。私钥是一个安全实体,应该存储在一个受限制访问的文件中,但必须能够被nginx的主进程读取。

ssl_protocols: 指定支持的SSL/TLS协议的版本。默认情况下,Nginx启用了TLSv1、TLSv1.1、TLSv1.2 和 TLSv1.3。通常不需要显式指定。

ssl_ciphers: 这个指令用于指定可用于SSL/TLS握手的密码套件。在默认情况下,Nginx使用了 HIGH:!aNULL:!MD5 这个值,表示高级加密套件,而且不允许使用匿名密钥交换和不安全的MD5算法。这也是一个比较强大和相对安全的默认设置。

  1. HTTPS服务器优化

SSL操作会消耗额外的CPU资源。在多处理器系统上,应该运行多个工作进程,数量不少于可用CPU核心数。最消耗CPU资源的操作是SSL握手。

减少每个客户端的握手操作次数:

    1. 启用keepalive连接,通过一个连接发送多个请求;
    1. 重用SSL会话参数,以避免在并行和后续连接中进行SSL握手。

    会话存储在SSL会话缓存中,该缓存在工作进程之间共享,并由ssl_session_cache指令进行配置。1兆字节的缓存大约包含4000个会话。默认缓存超时为5分钟,可以通过使用ssl_session_timeout指令进行增加。

     worker_processes auto;
     ​
     http {
         ssl_session_cache   shared:SSL:10m;
         ssl_session_timeout 10m;
     ​
         server {
             listen              443 ssl;
             server_name         www.example.com;
             keepalive_timeout   70;
     ​
             ssl_certificate     www.example.com.crt;
             ssl_certificate_key www.example.com.key;
             ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
             ssl_ciphers         HIGH:!aNULL:!MD5;
             ...
         }
     }
    
  1. 单一的服务器来处理HTTP和HTTPS请求
 server {
     listen              80;
     listen              443 ssl;
     server_name         www.example.com;
     ssl_certificate     www.example.com.crt;
     ssl_certificate_key www.example.com.key;
     ...
 }
  1. 基于名称的HTTPS服务器

如下所示:假如 www.example.comwww.example.org 都指向 120.79.250.121

在单个IP地址上配置两个或更多监听HTTPS的服务器,浏览器将接收默认服务器的证书,即www.example.com,而不考虑请求的服务器名称。这是由SSL协议行为引起的。SSL连接在浏览器发送HTTP请求之前建立,nginx不知道请求的服务器名称。

 server {
     listen          443 ssl;
     server_name     www.example.com;
     ssl_certificate www.example.com.crt;
     ...
 }
 ​
 server {
     listen          443 ssl;
     server_name     www.example.org;
     ssl_certificate www.example.org.crt;
     ...
 }

四、内置变量

http://example.com/page?param1=value1&param2=value2 为例:

  • $scheme: 获取请求的协议,对应 http
  • $host: 获取客户端请求中的主机头信息;对应 example.com
  • $uri: 获取不带参数的原始 URI;对应 /page
  • $args: 获取请求中的查询参数部分;对应 param1=value1&param2=value2
  • $request_uri: 获取客户端请求的原始URI,包括参数。对应 /page?param1=value1&param2=value2

五、重定向到主机

    1. 推荐使用 return 而非 rewrite
 server {
     listen       80;
     server_name  example.org;
     return       301 http://www.example.org$request_uri;
 }
 ​
 server {
     listen       80;
     server_name  www.example.org;
     ...
 }

如果真的想使用 rewrite,则是下面的形式:

 rewrite      ^ http://www.example.org$request_uri?;
    1. 的逻辑:
 server {
     listen       80;
     server_name  example.com www.example.com;
     ...
 }
 ​
 server {
     listen       80 default_server;
     server_name  _;
     return       301 http://example.com$request_uri;
 }

第二个 server 块定义了 listen 80 default_server;,这表示它是默认的服务器块,将匹配所有未被其他服务器块匹配的请求。server_name _; 表示对任何主机名(没有匹配的情况下),都将其重定向到 http://example.com 并保留原始请求的URI。