Nginx
Nginx
小u- 高性能的 HTTP 和反向代理服务器,同时也是电子邮件(IMAP/POP3/SMTP)代理服务器
- Nginx 分为主进程(master process)和工作进程(worker process),每个进程中只有一个线程(也可以配置线程池),通过 IO 多路复用(底层使用 epoll/kqueue 等技术)和事件循环达到高并发。主进程负责总体协调工作,比如在配置文件更新后重新应用配置、协调哪个 worker process 应该退役等等。工作进程的个数一般设置为 CPU 的个数。
Nginx 的启动和停止
- start nginx.exe:启动
- nginx [-c /etc/nginx/nginx.conf]:启动,可同时指定主配置文件
- nginx -h
- nginx -s 信号:向正在运行的 nginx 进程发送信号,信号包括:
- stop:立即关闭
- quit:正常关闭(等待工作进程处理完当前的请求才停止 nginx 进程)
- reload:重新加载配置文件
- reopen:重新打开日志文件,实现日志分隔的效果
- nginx -t:检查配置文件是否存在语法错误
- nginx -v:查看当前 nginx 的版本信息
- nginx -V:查看当前 nginx 的编译信息,如安装的模块、安装目录、各种文件的目录、编译器选项等
Nginx 的配置文件
- 默认情况下,配置文件名为 nginx.conf,并放在目录
/usr/local/nginx/conf
,/etc/nginx
或/usr/local/etc/nginx
中 - Nginx 配置生成器(opens new window)
1 | user nginx; # 指定工作进程使用的用户和组 |
默认情况下,nginx 已经自动开启了对 client 连接的 keep alive 支持(同时 client 发送的 HTTP 请求要求 keep alive)
默认 nginx 访问后端 server(nginx 称为 upstream)都是用的短连接(HTTP/1.0),一个请求来了,nginx 新开一个端口和后端建立连接,后端处理完成后主动关闭该连接
location
- location 语法:
location [ = | ~ | ~* | ^~ ] uri { ... };
或location @name { ... };
- location 的定义方式
= uri
:使 URI 和 location 匹配精确^~ uri
:由前缀字符串定义~ uri
:由正则表达式定义(匹配时区分大小写)~* uri
:由正则表达式定义(匹配时不区分大小写)@name
:定义一个命名的 location,在内部定向时使用,例如 error_page, try_files
- 如果有几个匹配上的 location 块指令,nginx 将选择具有最长前缀的 location 块
1 | location = / { |
[#](https://sdky.gitee.io/5 DevOps/04 Nginx.html#try-files)try_files
- 语法:
try_files file ... uri;
或try_files file ... =code;
- 按指定的 file 顺序查找存在的文件,并使用第一个找到的文件进行请求处理
- 查找路径是按照给定的 root(不做替换) 或 alias(会做替换) 为根路径来查找的
- 如果最后一个参数是
uri
,若给出的 file 都没有匹配到,则重新请求最后一个参数给定的 uri,就是新的 location 匹配(如果 uri 不是命名的 location,那么$args
不会自动传递,如果要保留$args
,必须明确声明参数;如果这个路径不存在,将会返回 500 错误) - 如果最后一个参数是
= 404
,若给出的 file 都没有匹配到,则最后返回 404 响应码
1 | # 比如请求 127.0.0.1/images/test.gif 会依次查找: |
1
2
3
4
5
6
7
8
try-files 如果不写上
$uri/
,当直接访问一个目录路径时,并不会去匹配目录下的索引页,即访问 127.0.0.1/images/ 不会去访问 127.0.0.1/images/index.html
常见内置预定义变量
- ngx_http_core_module
$host
:按照以下优先顺序:来自请求行的主机名,来自 Host 请求头字段的主机名,或与请求匹配的服务器名$hostname
:主机名$arg_name
:请求行中的 name 参数$args
、$query_string
:请求行中的参数$cookie_name
:名称为 name 的 cookie$http_name
:任意请求头字段,变量名称的最后一部分是将字段名称转换为小写,并用破折号替换为下划线,如$http_host
$msec
:当前时间以毫秒为单位$remote_addr
:客户端地址$remote_port
:客户端端口$remote_user
:基本身份验证提供的用户名$request
:完整的原始请求行$request_body
:请求正文$request_id
:由 16 个随机字节生成的唯一请求标识符,以十六进制表示$request_method
:请求方法$request_time
:请求处理时间以毫秒为单位$request_uri
:完整的原始请求 URI$scheme
:请求模式,http 或 https$sent_http_name
:任意响应头字段。变量名称的最后一部分是将字段名称转换为小写,并用破折号替换为下划线$status
:响应状态 - ngx_http_proxy_module
$proxy_host
:proxy_pass 指令中指定的代理服务器的名称和端口$proxy_port
:proxy_pass 指令中指定的代理服务器的端口或协议的默认端口$proxy_add_x_forwarded_for
:X-Forwarded-For 客户端请求头字段,其中附加了$remote_addr
变量,以逗号分割。如果客户端请求头中不存在 X-Forwarded-For 字段,则$proxy_add_x_forwarded_for
变量等于$remote_addr
变量
Nginx 的虚拟主机
- 虚拟主机是用来映射网站目录和网站代码文件夹的关系
- 可以通过 server 配置,每个 server 表示一个虚拟机主机
- nginx 首先根据 server 块的 listen 指令检验请求的 IP 和端口,之后根据与 IP 和端口相匹配的
server
块的server_name
项对请求的“Host” header 域进行检验 - 如果找不到服务器的名称(server_name),请求将由
default_server
处理
服务器名称
- 当通过名称搜索虚拟服务器时,如果名称与多个指定的变体匹配,例如通配符和正则表达式,则将按照优先顺序选择第一个匹配的变体:
- 精确的名称
- 以
*
开头的最长的通配符名称,例如*.example.org
- 以
*
结尾的最长的通配符名称,例如mail.*
- 第一个匹配的正则表达式(按照在配置文件中出现的顺序)
- 通配符名称:
- 通配符名称只能在名称的开头或者结尾包含一个
*
,且只能在点的边界上包含*
*
可以匹配多个名称部分,例如*.example.org
可以匹配 www.example.org、www.sub.example.org- 可以使用
.example.org
形式的特殊通配符名称来匹配确切的名称example.org
和通配符*.example.org
- 通配符名称只能在名称的开头或者结尾包含一个
- 正则表达式名称:nginx 使用的正则表达式与 Perl 编程语言(PCRE)使用的正则表达式兼容,要使用正则表达式,服务器名称必须以
~
开头
搜索通配符哈希表比搜索确切名称的哈希表要慢
由于正则表达式是按顺序验证的,因此是最慢的方法,并且是不可扩展的
由于这些原因,最好是尽可能使用确切的名称
动静分离
- 当用户请求 js、css 等静态资源时有当前 Nginx 服务器处理,请求 php 动态脚本代码时由其他的服务器处理(反向代理)
1 | # 配置 Nginx 动静分离,定义的静态页面直接从 Nginx 发布目录读取 |
Nginx 的反向代理
- 反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连的客户端,此时代理服务器对外就表现为一个服务器
- 代理服务器可以作为前端服务器处理静态资源
- proxy_pass
- 语法:
proxy_pass URL;
- 设置代理服务器的协议(http 或 https)、地址(域名或 IP,以及一个可选端口号)、应映射位置的 URI(可选)
- 语法:
- proxy_set_header
- 语法:
proxy_set_header filed value;
- 用于将字段重新定义或附加到传递给代理服务器的请求 header。该值可以包含文本、变量及其组合
- 当且仅当在当前级别上没有定义
proxy_set_header
指令时,这些指令才从上层级别继承 - 默认情况下,只重新定义了两个字段:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
- 语法:
1 | server { |
Nginx 的负载均衡
优点:分散后端服务器的压力;自动去掉不可用的后端服务器;缓存后端服务器响应内容
负载均衡的分配策略:
- 轮询(默认)
- least_conn:最少连接,下一个请求被分配给具有最少数量活动连接的服务器
- weight
- ip_hash
- fair(第三方,按后端服务器的响应时间来分配请求,响应时间短的优先分配)、url_hash(第三方)
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24http {
# 在 http 节点中定义负载均衡设备的 ip 及设备状态
upstream backend {
# ip_hash;
# least_conn; # 加权最少连接
# down 表示将当前的 server 标记为永久不可用
server 127.0.0.1:9090 down;
# weight 默认为 1,weight 越大,负载的权重就越大,被分配到的几率就越大
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060 max_fails=1 fail_timeout=10s;
# 其它所有的非 backup 机器 down 或者忙的时候,请求 backup 机器
server 127.0.0.1:7070 backup;
[ip_hash | fair | url_hash]
}
server {
listen 80;
location / {
# 在需要使用负载的 server 节点下添加
proxy_pass http://backend;
}
}
} 健康检查
- Nginx 是基于连接探测的,如果在单位周期为 fail_timeout 设置的时间内与服务器通信的失败次数达到 max_fails 次,那么就将把该服务器标记为不可用,并等待下一个周期(同样时长为 fail_timeout)再一次去请求,判断是否连接是否成功,如果探测成功,则将服务器标记为活动
- 默认情况下,
max_fails=1 fail_timeout=10s
,当 max_fails 设置为 0 时,该服务器的健康检查将被禁用(即认为该服务器是一直可用的)
Nginx 的 WebSocket 代理
- 使用 HTTP/1.1 中的协议切换机制,将客户端与服务器之间的连接从 HTTP/1.1 转换为 WebSocket
- 如果代理服务器返回一个 101 响应码(交换协议),则客户机和代理服务器之间将建立隧道,客户端通过请求中的
Upgrade
头来请求协议交换 - 默认情况下,如果代理务器在 60 秒内没有传输任何数据,连接将被关闭(这个超时可以通过 proxy_read_timeout指令来增加, 或者代理服务器可以配置为定期发送 WebSocket ping 帧以重置超时并检查连接是否仍然活跃)
1 | location /chat/ { |