一、服务器名称
-
server_name
匹配(性能)顺序:- 精确匹配;
- 以星号开头的最长通配符名称,如:
*.example.org
; - 以星号结尾的最长通配符名称,如:
mail.*
; - 正则表达式(正则表达式匹配的位置会优先于普通前缀匹配的位置。
~* \.(gif|jpg|jpeg)$
优先于/documents/
)
- 第一个匹配的正则表达式(按照配置文件中出现的顺序)。
最好在可能的情况下使用精确名称。如果服务器最常请求的名称是 example.org
和 www.example.org
,则明确定义它们会更有效。
# 建议
server {
listen 80;
server_name example.org www.example.org *.example.org;
...
}
# 不建议
server {
listen 80;
# 特殊的通配符形式 ".example.org" 存储在通配符名称哈希表中,而不是精确名称哈希表中
server_name .example.org;
...
}
-
名称使用通配符:
通配符只能出现在域名的开头或结尾,并且只能出现在点的边界上。如:
*.example.org
和mail.*
。 -
名称使用正则表达式:
必须以波浪号字符开头,同时不要忘了加
^
$
如:server_name ~^www\d+\.example\.net$;
包含字符“{”和“}”的正则表达式应该加引号:
-
server_name "~^(?<name>\w\d{1,3}+)\.example\.net$";
之后使用命名的正则表达式捕获作为变量使用:
server { server_name ~^(www\.)?(?<domain>.+)$; location / { root /sites/$domain; } }
二、负载均衡
-
支持以下三种方式:
- 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;
}
-
健康检查
如果从特定服务器收到的响应出现错误,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算法。这也是一个比较强大和相对安全的默认设置。
-
HTTPS服务器优化
SSL操作会消耗额外的CPU资源。在多处理器系统上,应该运行多个工作进程,数量不少于可用CPU核心数。最消耗CPU资源的操作是SSL握手。
减少每个客户端的握手操作次数:
- 启用keepalive连接,通过一个连接发送多个请求;
-
- 重用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; ... } }
-
单一的服务器来处理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;
...
}
-
基于名称的HTTPS服务器
如下所示:假如 www.example.com
和 www.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¶m2=value2
为例:
-
$scheme: 获取请求的协议,对应
http
。 -
$host: 获取客户端请求中的主机头信息;对应
example.com
。 -
$uri: 获取不带参数的原始 URI;对应
/page
。 -
$args: 获取请求中的查询参数部分;对应
param1=value1¶m2=value2
。 -
$request_uri:获取客户端请求的原始URI,包括参数。对应
/page?param1=value1¶m2=value2
。
五、重定向到主机
- 推荐使用
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?;
-
非
的逻辑:
-
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。