主进程和工作进程(Master and Worker Processes)
NGINX 有一个主进程和一个或多个工作进程。如果启用缓存,缓存加载器和缓存管理器进程也会在启动时运行。
主进程的主要目的是读取和评估配置文件,以及维护工作进程。
工作进程执行请求的实际处理。NGINX 依赖于操作系统相关的机制来有效地在工作进程之间分配请求。工作进程的数量由nginx.conf配置文件中的worker_processes指令定义,可以设置为固定数量,也可以配置为根据可用 CPU 内核的数量自动调整。
控制命令
要重新加载您的配置,您可以停止或重新启动 NGINX,或向主进程发送信号。可以通过运行nginx
带有-s
参数的命令(调用 NGINX 可执行文件)来发送信号。
nginx -s <SIGNAL>
这里的<SIGNAL>
可以是以下之一:
quit
– 优雅地关闭reload
– 重新加载配置文件reopen
– 重新打开日志文件stop
– 立即关机(快速关机)
该kill
实用程序还可用于直接向主进程发送信号。默认情况下,主进程的进程 ID 会写入nginx.pid文件,该文件位于**/usr/local/nginx/logs或/var/run**目录中。
配置文件
指令(Directives)
配置文件由指令及其参数组成。简单(单行)指令都以分号结尾。其他指令充当“容器”,将相关指令组合在一起,将它们括在花括号 ( {}
) 中;这些通常被称为块。以下是一些简单指令的示例。
user nobody;
error_log logs/error.log notice;
worker_processes 1;
特定于功能的配置文件(Feature-Specific Configuration Files)
为了使配置更易于维护,我们建议您将其拆分为一组存储在**/etc/nginx/conf.d目录中的特定于功能的文件,并在主nginx.conf**文件中使用include指令来引用内容特定于功能的文件。
include conf.d/http;
include conf.d/stream;
include conf.d/exchange-enhanced;
上下文(Contexts)
一些顶级指令,称为contexts,将适用于不同流量类型的指令组合在一起:
虚拟服务器(Virtual Servers)
在每个流量处理上下文中,您都包含一个或多个server
块来定义控制请求处理的虚拟服务器。您可以在server
上下文中包含的指令因流量类型而异。
对于 HTTP 流量(http
上下文),每个服务器指令控制对特定域或 IP 地址资源请求的处理。上下文中的一个或多个位置server
上下文定义了如何处理特定的 URI 集。
对于邮件和 TCP/UDP 流量(邮件和流上下文),server
每个指令控制到达特定 TCP 端口或 UNIX 套接字的流量的处理。
具有多个上下文的示例配置文件(Sample Configuration File with Multiple Contexts)
user nobody; # a directive in the 'main' context 主上下文中的指令
events {
# configuration of connection processing 连接处理配置
}
http {
# Configuration specific to HTTP and affecting all virtual servers
# 特定于HTTP并影响所有虚拟服务器的配置
server {
# configuration of HTTP virtual server 1
# HTTP虚拟服务器1的配置
location /one {
# configuration for processing URIs starting with '/one'
# 处理以“/one”开头的URI的配置
}
location /two {
# configuration for processing URIs starting with '/two'
# 处理以“/two”开头的URI的配置
}
}
server {
# configuration of HTTP virtual server 2
# HTTP虚拟服务器2的配置
}
}
stream {
# Configuration specific to TCP/UDP and affecting all virtual servers
# 特定于TCP/UDP并影响所有虚拟服务器的配置
server {
# configuration of TCP virtual server 1
# TCP虚拟服务器1的配置
}
}
继承(Inheritance)
通常,子上下文是包含在另一个上下文(其父)中的一个,它会继承父级包含的指令的设置。某些指令可以出现在多个上下文中,在这种情况下,您可以通过在子上下文中包含指令来覆盖从父级继承的设置。有关示例,请参阅proxy_set_header指令。
负载均衡(Load Balancer)
HTTP 负载均衡
在 http context 中使用 upstream 指令定义服务器组,upstream 中使用 server 指令进行配置(不要与server
定义在 NGINX 上运行的虚拟服务器的块混淆),下面的示例结合了上面的两个片段,并展示了如何将 HTTP 请求代理到后端服务器组。该组由三台服务器组成,其中两台运行相同应用程序的实例,而第三台是备份服务器。因为块中没有指定负载均衡算法upstream
,NGINX 使用默认算法,Round Robin:
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
}
server {
location / {
proxy_pass http://backend;
}
}
}
选择负载均衡算法
NGINX 开源支持四种负载均衡方法,NGINX Plus 增加了两种方法:
-
循环 - 请求在服务器之间均匀分布,并考虑服务器权重。默认情况下使用此方法(没有启用它的指令):
upstream backend { # no load balancing method is specified for Round Robin server backend1.example.com; server backend2.example.com; }
-
最少连接——请求被发送到活动连接数最少的服务器,再次考虑服务器权重:
upstream backend { least_conn; server backend1.example.com; server backend2.example.com; }
-
IP Hash – 请求发送到的服务器由客户端 IP 地址确定。在这种情况下,要么使用 IPv4 地址的前三个八位字节,要么使用整个 IPv6 地址来计算哈希值。该方法保证来自同一地址的请求到达同一服务器,除非它不可用。
upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; }
如果其中一台服务器需要暂时从负载平衡轮换中移除,则可以使用down参数对其进行标记,以保留客户端 IP 地址的当前散列。由该服务器处理的请求会自动发送到组中的下一个服务器:
upstream backend { server backend1.example.com; server backend2.example.com; server backend3.example.com down; }
-
通用哈希- 请求发送到的服务器由用户定义的键确定,该键可以是文本字符串、变量或组合。例如,密钥可以是成对的源 IP 地址和端口,或 URI,如本例所示:
upstream backend { hash $request_uri consistent; server backend1.example.com; server backend2.example.com; }
该指令的可选参数一致
hash
启用ketama一致性哈希负载平衡。请求根据用户定义的散列键值均匀分布在所有上游服务器上。如果将上游服务器添加到上游组或从上游组中删除,则在负载平衡缓存服务器或其他累积状态的应用程序的情况下,只会重新映射少数键,从而最大限度地减少缓存未命中。 -
最短时间(仅限 NGINX Plus)——对于每个请求,NGINX Plus 选择平均延迟最低和活动连接数最少的服务器,其中最低平均延迟是根据指令包含的以下参数中的哪一个来计算的
least_time
:header
– 从服务器接收第一个字节的时间last_byte
– 从服务器接收完整响应的时间last_byte inflight
– 从服务器接收完整响应的时间,考虑到不完整的请求
upstream backend { least_time header; server backend1.example.com; server backend2.example.com; }
-
随机- 每个请求都将传递到随机选择的服务器。如果
two
指定了该参数,首先NGINX会考虑服务器权重随机选择两台服务器,然后使用指定的方法选择其中一台服务器:least_conn
– 最少的活动连接数least_time=header
(NGINX Plus) – 从服务器接收响应头的最少平均时间 ($upstream_header_time
)least_time=last_byte
(NGINX Plus) – 从服务器收到完整响应的最少平均时间 ($upstream_response_time
)
upstream backend { random two least_time=last_byte; server backend1.example.com; server backend2.example.com; server backend3.example.com; server backend4.example.com; }
的随机负载平衡方法应被用于在多个负载平衡器传递请求到相同组的后端分布式环境。对于负载均衡器可以查看所有请求的环境,请使用其他负载均衡方法,例如循环、最少连接和最少时间。
**注意:**当配置除 Round Robin 之外的任何方法时,将相应的指令(
hash
、ip_hash
、least_conn
、least_time
、 或random
)放在块中server
指令列表的上方upstream {}
。
服务器权重
默认情况下,NGINX 使用 Round Robin 方法根据权重在组中的服务器之间分配请求。该指令的weight
参数server
设置服务器的权重;默认是1
:
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com;
server 192.0.0.1 backup;
}
在这个例子中,backend1.example.com有 weight 5
;其他两台服务器有默认权重(1
),但有 IP 地址的那台192.0.0.1
被标记为backup
服务器,除非其他两台服务器都不可用,否则不会接收请求。随着权重的这种配置,每的6
请求,5
发送到backend1.example.com和1
对backend2.example.com。
服务器慢启动
服务器慢启动功能可防止最近恢复的服务器被连接淹没,这可能会超时并导致服务器再次被标记为失败。
在 NGINX Plus 中,慢启动允许上游服务器0
在恢复或可用后逐渐恢复其权重到其标称值。这可以通过指令的slow_start
参数来完成server
:
upstream backend {
server backend1.example.com slow_start=30s;
server backend2.example.com;
server 192.0.0.1 backup;
}
时间值(此处为30
秒)设置 NGINX Plus 将与服务器的连接数增加到完整值的时间。
请注意,如果只有一个单一的服务器组,中max_fails
,fail_timeout
和slow_start
参数的server
指令被忽略,服务器永远不会认为不可用。
启用会话持久性
会话持久性意味着 NGINX Plus 识别用户会话并将给定会话中的所有请求路由到同一个上游服务器。
NGINX Plus 支持三种会话持久化方法。方法是用sticky
指令设置的。(对于具有NGINX开源会话持久性,使用hash
或ip_hash
如所描述的指令以上。)
-
粘性 cookie ——NGINX Plus 将会话cookie添加到来自上游组的第一个响应,并标识发送响应的服务器。客户端的下一个请求包含 cookie 值,NGINX Plus 将请求路由到响应第一个请求的上游服务器:
upstream backend { server backend1.example.com; server backend2.example.com; sticky cookie srv_id expires=1h domain=.example.com path=/; }
在示例中,该
srv_id
参数设置 cookie 的名称。可选expires
参数设置浏览器保留 cookie 的时间(此处为1
小时)。可选domain
参数定义设置cookie的域,可选path
参数定义设置cookie的路径。这是最简单的会话持久化方法。 -
粘性路由——NGINX Plus 在收到第一个请求时为客户端分配一个“路由”。所有后续请求都与指令的
route
参数进行比较,server
以识别请求代理的服务器。路由信息取自 cookie 或请求 URI。upstream backend { server backend1.example.com route=a; server backend2.example.com route=b; sticky route $route_cookie $route_uri; }
-
粘性学习方法——NGINX Plus 首先通过检查请求和响应来查找会话标识符。然后NGINX Plus“学习”哪个上游服务器对应哪个会话标识符。通常,这些标识符在 HTTP cookie 中传递。如果请求包含已经“学习”的会话标识符,NGINX Plus 会将请求转发到相应的服务器:
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; }
在示例中,其中一台上游服务器通过
EXAMPLECOOKIE
在响应中设置 cookie来创建会话。强制
create
参数指定一个变量,指示如何创建新会话。在示例中,新会话是从EXAMPLECOOKIE
上游服务器发送的 cookie 创建的。强制
lookup
参数指定如何搜索现有会话。在我们的示例中,EXAMPLECOOKIE
在客户端发送的 cookie 中搜索现有会话。强制
zone
参数指定一个共享内存区域,其中保存有关粘性会话的所有信息。在我们的示例中,区域名为client_sessions1
,大小为MB。这是一种比前两种更复杂的会话持久性方法,因为它不需要在客户端保留任何 cookie:所有信息都保存在服务器端的共享内存区域中。
如果集群中有多个 NGINX 实例使用“粘性学习”方法,则可以在以下条件下同步其共享内存区域的内容:
- 这些区域具有相同的名称
- 该
zone_sync
功能在每个实例上配置 - 在
sync
被指定的参数
sticky learn create=$upstream_cookie_examplecookie lookup=$cookie_examplecookie zone=client_sessions:1m timeout=1h sync; }
有关详细信息,请参阅集群中的运行时状态共享。
限制连接数
使用 NGINX Plus,可以通过使用max_conns
参数指定最大数量来限制与上游服务器的活动连接数量。
如果max_conns
已达到限制,则请求将被放入队列以供进一步处理,前提queue
是还包含该指令以设置可以同时在队列中的最大请求数:
upstream backend {
server backend1.example.com max_conns=3;
server backend2.example.com;
queue 100 timeout=70;
}
如果队列被请求填满或在可选timeout
参数指定的超时时间内无法选择上游服务器,则客户端会收到错误。
请注意,max_conns
如果keepalive
在 other 中打开了空闲连接,则会忽略该限制worker processes
。因此,与服务器的连接总数可能会超过max_conns
内存与多个工作进程共享的配置中的值。
与多个工作进程共享数据
如果upstream
块不包含该zone
指令,则每个工作进程都会保留自己的服务器组配置副本并维护自己的一组相关计数器。计数器包括与组中每个服务器的当前连接数以及将请求传递给服务器的失败尝试次数。因此,无法动态修改服务器组配置。
当zone
指令包含在一个upstream
块中时,上游组的配置保存在所有工作进程共享的内存区域中。这个场景是动态配置的,因为工作进程访问组配置的相同副本并使用相同的相关计数器。
该zone
指令对于上游组的主动健康检查和动态重新配置是强制性的。但是,上游组的其他功能也可以从使用该指令中受益。
例如,如果组的配置未共享,则每个工作进程都会维护自己的计数器,用于将请求传递给服务器的失败尝试(由max_fails参数设置)。在这种情况下,每个请求只能到达一个工作进程。当被选择来处理请求的工作进程未能将请求传输到服务器时,其他工作进程对此一无所知。虽然某些工作进程可能认为服务器不可用,但其他工作进程可能仍会向该服务器发送请求。对于要明确认为不可用的服务器,fail_timeout
参数设置的时间范围内的失败尝试次数必须等于max_fails
工作进程数的乘积。另一方面,该zone
指令保证了预期的行为。
同样,如果没有该指令,最少连接负载平衡方法可能无法按预期工作zone
,至少在低负载下是这样。此方法将请求传递给活动连接数最少的服务器。如果组的配置未共享,则每个工作进程使用自己的连接数计数器,并可能将请求发送到另一个工作进程刚刚发送请求的同一服务器。但是,您可以增加请求数以减少这种影响。在高负载下,请求在工作进程之间均匀分布,并且该Least Connections
方法按预期工作。
设置区域大小
不可能推荐理想的内存区域大小,因为使用模式差异很大。所需的内存量取决于启用了哪些功能(例如会话持久性、健康检查或DNS 重新解析)以及如何识别上游服务器。
例如,在sticky_route
启用会话持久性方法和单个运行状况检查的情况下,256 KB 区域可以容纳有关指定数量的上游服务器的信息:
- 128 个服务器(每个定义为一个 IP 地址:端口对)
- 88 个服务器(每个定义为主机名:端口对,其中主机名解析为单个 IP 地址)
- 12 个服务器(每个定义为主机名:端口对,其中主机名解析为多个 IP 地址)
使用 DNS 配置 HTTP 负载平衡
可以在运行时使用 DNS 修改服务器组的配置。
对于在server
指令中使用域名标识的上游组中的服务器,NGINX Plus 可以监控相应 DNS 记录中 IP 地址列表的更改,并自动将更改应用于上游组的负载均衡,而无需重新开始。这可以通过resolver
在http
块中包含指令以及指令的resolve
参数来完成server
:
http {
resolver 10.0.0.1 valid=300s ipv6=off;
resolver_timeout 10s;
server {
location / {
proxy_pass http://backend;
}
}
upstream backend {
zone backend 32k;
least_conn;
# ...
server backend1.example.com resolve;
server backend2.example.com resolve;
}
}
在这个例子中,resolve
参数的server
指令告诉nginx加上定期重新决心的backend1.example.com和backend2.example.com域名转换为IP地址。
该resolver
指令定义了 NGINX Plus 向其发送请求的 DNS 服务器的 IP 地址(此处为10.0.0.1
)。默认情况下,NGINX Plus 以记录中生存时间 (TTL) 指定的频率重新解析 DNS 记录,但您可以使用valid
参数覆盖 TTL 值;在示例中,它是300
秒或5
分钟。
可选ipv6=off
参数表示只使用 IPv4 地址进行负载均衡,但默认支持同时解析 IPv4 和 IPv6 地址。
如果一个域名解析为多个 IP 地址,这些地址将保存到上游配置中并进行负载均衡。在我们的示例中,服务器根据最少连接负载平衡方法进行负载平衡。如果服务器的 IP 地址列表发生了变化,NGINX Plus 会立即启动跨新地址集的负载平衡。
#!/bin/sh
echo "----------------------------------start install nginx -----------------------------"
yum install -y gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel
if [ 'grep "nginx" /etc/passwd | wc -l' ]; then
echo "adding user nginx"
groupadd nginx
useradd -s /sbin/nologin -M -g nginx nginx
else
echo "user nginx exsits"
fi
echo "-----------------------------------downloading nginx-------------------------------"
wget http://nginx.org/download/nginx-1.19.5.tar.gz
tar -xvf nginx-1.19.5.tar.gz
cd nginx-1.19.5
echo "------------------------------------configuring nginx,plz wait----------------------"
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
if [ $? -ne 0 ]; then
echo "configure failed ,please check it out!"
else
echo "make nginx, please wait for 20 minutes"
make
fi
if [ $? -ne 0 ]; then
echo "make failed ,please check it out!"
else
echo "install nginx, please wait for 20 minutes"
make install
fi
chown -R nginx.nginx /usr/local/nginx
ln -s /lib64/libpcre.so.0.0.1 /lib64/libpcre.so.1
# /usr/local/nginx/sbin/nginx
# iptables -I INPUT 3 -s 0.0.0.0/0 -p tcp --dport 80 -j ACCEPT