Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器,而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数,最重要的是, Nginx 是免费的并可以商业化,配置使用也比较简单。
高并发、高性能;
模块化架构使得它的扩展性非常好;
异步非阻塞的事件驱动模型这点和 Node.js 相似;
相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性;
热部署、平滑升级;
完全开源,生态繁荣;
Nginx 作用
静态资源服务,通过本地文件系统提供服务;
反向代理服务,延伸出包括缓存、负载均衡等;
API 服务, OpenResty ;
/etc/nginx/nginx.conf # nginx 主配置文件
/etc/nginx/nginx.conf.default# 可执行程序文件
/usr/bin/nginx-upgrade
/usr/sbin/nginx# nginx 库文件
/usr/lib/systemd/system/nginx.service # 用于配置系统守护进程
/usr/lib64/nginx/modules # Nginx 模块目录# 帮助文档
/usr/share/doc/nginx-1.16.1
/usr/share/doc/nginx-1.16.1/CHANGES
/usr/share/doc/nginx-1.16.1/README
/usr/share/doc/nginx-1.16.1/README.dynamic
/usr/share/doc/nginx-1.16.1/UPGRADE-NOTES-1.6-to-1.10
# 静态资源目录
/usr/share/nginx/html/404.html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
# 存放 Nginx 日志文件
/var/log/nginx
systemctl enable nginx # 开机自动启动
systemctl disable nginx # 关闭开机自动启动
# 启动 Nginx
systemctl start nginx # 启动 Nginx 成功后,可以直接访问主机 IP,此时会展示 Nginx 默认页面
# 停止 Nginx
systemctl stop nginx
# 重启 Nginx
systemctl restart nginx
# 重新加载 Nginx
systemctl reload nginx
# 查看 Nginx 运行状态
systemctl status nginx
# 查看 Nginx 进程
ps -ef | grep nginx
# 杀死 Nginx 进程
kill -9 pid # 根据上面查看到的 Nginx 进程号,杀死 Nginx 进程,-9 表示强制结束进程
nginx -s reopen # 重启 Nginx
nginx -s stop # 快速关闭
nginx -s quit # 等待工作进程处理完成后关闭
nginx -T # 查看当前 Nginx 最终的配置
nginx -t # 检查配置是否有问题
Nginx 核心配置
配置文件结构
# 运行用户,默认即是 nginx,可以不进行设置
# Nginx 进程数,一般设置为和 CPU 核数一样
warn; # Nginx 的错误日志存放目录
# Nginx 服务启动时的 pid 存放位置# events 段配置信息
events {
epoll; # 使用 epoll 的 I/O 模型(如果你不知道 Nginx 该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
1024; # 每个进程允许最大并发数
}# http 段配置信息
# 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
http {
# 设置日志模式
‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for“‘;# Nginx 访问日志存放位置
on; # 开启高效传输模式
on; # 减少网络报文段的数量
on;
65; # 保持连接的时间,也叫超时时间,单位秒
2048;
# 文件扩展名与类型映射表
# 默认文件类型
*.conf; # 加载子配置项
# server 段配置信息
server {
80; # 配置监听的端口
# 配置的域名
# location 段配置信息
root /usr/share/nginx/html; # 网站根目录
# 默认首页文件
172.168.22.11; # 禁止访问的 ip 地址,可以为 all
172.168.33.44;# 允许访问的 ip 地址,可以为 all
}
error_page 500 502 503 504 /50x.html; # 默认 50x 对应的访问页面
400 404 error.html; # 同上
}
}
全局配置,对全局生效;
events 配置影响 Nginx 服务器与用户的网络连接;
http 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置;
server 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块;
location 用于配置匹配的 uri ;
upstream 配置后端服务器具体地址,负载均衡配置不可或缺的部分;
配置文件 main 段核心参数
user
worker_rlimit_nofile_number
# 存放目录
worker_processes_number
# 与当前 cpu 物理核心数一致
worker_cpu_affinity

worker_shutdown_timeout
timer_resolution
配置文件 events 段核心参数
use
worker_connections
# 示例:
server_name www.nginx.com;
精确匹配:server_name www.nginx.com ;
左侧通配:server_name *.nginx.com ;
右侧统配:server_name www.nginx.* ;
正则匹配:server_name ~^www.nginx.*$ ;
121.42.11.34 www.nginx-test.com
121.42.11.34 mail.nginx-test.com
121.42.11.34 www.nginx-test.org
121.42.11.34 doc.nginx-test.com
121.42.11.34 www.nginx-test.cn
121.42.11.34 fe.nginx-test.club
server {
80;
*.nginx-test.com;
location / {
# 正则匹配
server {
80;
root /usr/share/nginx/html/nginx-test/reg-match/;
index index.html;
}
}# 右匹配
server {
80;
www.nginx-test.*;
location / {
# 完全匹配
server {
80;
root /usr/share/nginx/html/nginx-test/all-match/;
index index.html;
}
}
当访问 www.nginx-test.com 时,都可以被匹配上,因此选择优先级最高的“完全匹配”;
当访问 mail.nginx-test.com 时,会进行“左匹配”;
当访问 www.nginx-test.org 时,会进行“右匹配”;
当访问 doc.nginx-test.com 时,会进行“左匹配”;
当访问 www.nginx-test.cn 时,会进行“右匹配”;
当访问 fe.nginx-test.club 时,会进行“正则匹配”;
root
location /image {
root /opt/nginx/static;
}当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
alias
alias /opt/nginx/static/image/;
}当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
…
}
= 精确匹配;
~ 正则匹配,区分大小写;
~* 正则匹配,不区分大小写;
^~ 匹配到即停止搜索;
80;
# 只有当访问 www.nginx-test.com/match_all/ 时才会匹配到/usr/share/nginx/html/match_all/index.html
root /usr/share/nginx/html
index index.html
}# 当访问 www.nginx-test.com/1.jpg 等路径时会去 /usr/share/nginx/images/1.jpg 找对应的资源
location ~ .(jpeg|jpg|png|svg)$ {
# 当访问 www.nginx-test.com/bbs/ 时会匹配上 /usr/share/nginx/html/bbs/index.html
^~ /bbs/ {
index index.html index.htm;
}
}
…
}location /test/ {
…
}
不带 / 当访问 www.nginx-test.com/test 时, Nginx 先找是否有 test 目录,如果有则找test 目录下的 index.html ;如果没有 test 目录, nginx 则会找是否有 test 文件。
带 / 当访问 www.nginx-test.com/test 时, Nginx 先找是否有 test 目录,如果有则找test 目录下的 index.html ,如果没有它也不会去找是否存在 test 文件。
return
return code URL;
return URL;例如:
location / {
return 404; # 直接返回状态码
}location / {
return 404 “pages not found”; # 返回状态码 + 一段文本
}location / {
return 302 /bbs ; # 返回状态码 + 重定向地址
}
location / {
return https://www.baidu.com ; # 返回重定向地址
}
rewrite
last 重写后的 URL 发起新请求,再次进入 server 段,重试 location 的中的匹配;
break 直接使用重写后的 URL ,不再匹配其它 location 中语句;
redirect 返回 302 临时重定向;
permanent 返回 301 永久重定向;
listen 80;
server_name fe.lion.club; # 要在本地 hosts 文件进行配置
root html;
location /search {
rewrite ^/(.*) https://www.baidu.com redirect;
}location /images {
rewrite /images/(.*) /pics/$1;
}location /pics {
rewrite /pics/(.*) /photos/$1;
}location /photos {
}
}
当访问 fe.lion.club/search 时,会自动帮我们重定向到 https://www.baidu.com。
当访问 fe.lion.club/images/1.jpg 时,第一步重写 URL 为 fe.lion.club/pics/1.jpg ,找到 pics 的 location ,继续重写 URL 为 fe.lion.club/photos/1.jpg ,找到 /photos 的location 后,去 html/photos 目录下寻找 1.jpg 静态资源。
if 指令
if($http_user_agent ~ Chrome){
rewrite /(.*)/browser/$1 break;
}
$variable 仅为变量时,值为空或以 0 开头字符串都会被当做 false 处理;
= 或 != 相等或不等;
~ 正则匹配;
! ~ 非正则匹配;
~* 正则匹配,不区分大小写;
-f 或 ! -f 检测文件存在或不存在;
-d 或 ! -d 检测目录存在或不存在;
-e 或 ! -e 检测文件、目录、符号链接等存在或不存在;
-x 或 ! -x 检测文件可以执行或不可执行;
8080;
root html;if ( $uri = “/images/” ){
break;
}
}
}
80;
location /download/ {
autoindex on; # 打开 autoindex,,可选参数有 on | off
on; # 修改为 off,以 KB、MB、GB 显示文件大小,默认为 on,以 bytes 显示出⽂件的确切⼤⼩
# 以 html 的方式进行格式化,可选参数有 html | json | xml
off; # 显示的⽂件时间为⽂件的服务器时间。默认为 off,显示的⽂件时间为 GMT 时间
}
}


listen 8081;
server_name var.lion-test.club;
root /usr/share/nginx/html;
location / {
return 200 ”
remote_addr: $remote_addr
remote_port: $remote_port
server_addr: $server_addr
server_port: $server_port
server_protocol: $server_protocol
binary_remote_addr: $binary_remote_addr
connection: $connection
uri: $uri
request_uri: $request_uri
scheme: $scheme
request_method: $request_method
request_length: $request_length
args: $args
arg_pid: $arg_pid
is_args: $is_args
query_string: $query_string
host: $host
http_user_agent: $http_user_agent
http_referer: $http_referer
http_via: $http_via
request_time: $request_time
https: $https
request_filename: $request_filename
document_root: $document_root
“;
}
}
server_port: 8081
binary_remote_addr: 茉
uri: /test/
scheme: http
request_length: 518
arg_pid: 121414
query_string: pid=121414&cid=sadasd
http_user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
http_referer:
http_via:
request_time: 0.000
https:
request_filename: /usr/share/nginx/html/test/
document_root: /usr/share/nginx/html

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
反向代理*(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
隐藏真实服务器;
负载均衡便于横向扩充后端动态服务;
动静分离,提升系统健壮性;

轮询策略:默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
最小连接数策略:将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
最快响应时间策略:优先分配给响应时间最短的服务器。
客户端 ip 绑定策略:来自同一个 ip 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。

…
}上下文:http示例:
upstream back_end_server{
server 192.168.100.33:8081
}
server 定义上游服务器地址;
zone 定义共享内存,用于跨 worker 子进程;
keepalive 对上游服务启用长连接;
keepalive_requests 一个长连接最多请求 HTTP 的个数;
keepalive_timeout 空闲情形下,一个长连接的超时时长;
hash 哈希负载均衡算法;
ip_hash 依据 IP 进行哈希计算的负载均衡算法;
least_conn 最少连接数负载均衡算法;
least_time 最短响应时间负载均衡算法;
random 随机负载均衡算法;
server
weight=number 权重值,默认为 1;
max_conns=number 上游服务器的最大并发连接数;
fail_timeout=time 服务器不可用的判定时间;
max_fails=numer 服务器不可用的检查次数;
backup 备份服务器,仅当其他服务器都不可用时才会启用;
down 标记服务器长期不可用,离线维护;
keepalive
keepalive_requests
配置实例
32;
50;
30s;
}
proxy_pass
proxy_pass http://127.0.0.1:8081
proxy_pass http://127.0.0.1:8081/proxy
proxy_pass http://192.168.100.33:8081
proxy_pass http://192.168.100.33:8081/
不带 / 意味着 Nginx 不会修改用户 URL ,而是直接透传给上游的应用服务器;
带 / 意味着 Nginx 会修改用户 URL ,修改方法是将 location 后的 URL 从用户 URL 中删除;
}
}
server{
listen 8080;
server_name localhost;location /proxy/ {
root /usr/share/nginx/html/proxy;
index index.html;
}
}
# /usr/share/nginx/html/proxy/index.html
<h1> 121.42.11.34 proxy html </h1>
server 121.42.11.34:8080 weight=2 max_conns=1000 fail_timeout=10s max_fails=3;
32;
80;
20s;
}server {
80;
location /proxy {
本地机器要访问 proxy.lion.club 域名,因此需要配置本地 hosts ,通过命令:vim /etc/hosts进入配置文件,添加如下内容:

配置负载均衡
listen 8020;
location / {
return 200 ‘return 8020 n’;
}
}server{
listen 8030;
location / {
return 200 ‘return 8030 n’;
}
}server{
listen 8040;
location / {
return 200 ‘return 8040 n’;
}
}
121.42.11.34:8030;
121.42.11.34:8040;
}server {
80;
location /balance/ {
配置完成后重启 Nginx 服务器。并且在需要访问的客户端配置好 ip 和域名的映射关系。

不难看出,负载均衡的配置已经生效了,每次给我们分发的上游服务器都不一样。就是通过简单的轮询策略进行上游服务器分发。
121.42.11.34:8020;
121.42.11.34:8030;
121.42.11.34:8040;
}server {
80;
location /balance/ {
hash $request_uri 表示使用 request_uri 变量作为 hash 的 key 值,只要访问的 URI 保持不变,就会一直分发给同一台服务器。
ip_hash;
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}server {
listen 80;
server_name balance.lion.club;location /balance/ {
proxy_pass http://demo_server;
}
}
最少连接数算法
zone test 10M; # zone可以设置共享内存空间的名字和大小
least_conn;
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}server {
listen 80;
server_name balance.lion.club;location /balance/ {
proxy_pass http://demo_server;
}
}
proxy_cache_path
path 缓存文件的存放路径;
level path 的目录层级;
keys_zone 设置共享内存;
inactive 在指定时间内没有被访问,缓存会被清理,默认 10 分钟;
proxy_cache_key
proxy_no_cache
proxy_cache_bypass
upstream_cache_status 变量
REVALIDDATED: Nginx 验证陈旧缓存依然有效
BYPASS: X 响应从原始服务器获取
配置实例
1010;
1010;
index index.html;
}
}server {
1020;
1020;
index index.html;
}
}
121.42.11.34:1020;
}server {
80;
location / {
# 设置缓存内存,上面配置中已经定义好的
200 5m; # 缓存状态为 200 的请求,缓存时长为 5 分钟
$request_uri; # 缓存文件的 key 为请求的 URI
$upstream_cache_status # 把缓存状态设置为头部信息,响应给客户端
proxy_pass http://cache_server; # 代理转发
}
}
listen 80;
server_name cache.lion.club;
# URI 中后缀为 .txt 或 .text 的设置变量值为 “no cache”
if ($request_uri ~ .(txt|text)$) {
set $cache_name “no cache”
}location / {
proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,如果没有值则进行缓存
proxy_cache cache_zone; # 设置缓存内存
proxy_cache_valid 200 5m; # 缓存状态为 200 的请求,缓存时长为 5 分钟
proxy_cache_key $request_uri; # 缓存文件的 key 为请求的 URI
add_header Nginx-Cache-Status $upstream_cache_status # 把缓存状态设置为头部信息,响应给客户端
proxy_pass http://cache_server; # 代理转发
}
}
配置证书
443 ssl http2 default_server; # SSL 访问端口号为 443
# 填写绑定证书的域名(我这里是随便写的)
# 证书地址
# 私钥地址
10m;
1 TLSv1.2; # 支持 ssl 协议版本,默认为后三个,主流版本是[TLSv1.2]root /usr/share/nginx/html;
如此配置后就能正常访问 HTTPS 版的网站了。
//store.company.com/secure.html 不同源,协议不同
//store.company.com:81/dir/etc.html 不同源,端口不同
//news.company.com/dir/other.html 不同源,主机不同
Web 数据层面,同源策略限制了不同源的站点读取当前站点的 Cookie 、 IndexDB 、LocalStorage 等数据。
DOM 层面,同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
网络层面,同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
Nginx 解决跨域的原理
前端 server 的域名为:fe.server.com
后端服务的域名为:dev.server.com
80;
location / {
这样可以完美绕过浏览器的同源策略:fe.server.com 访问 Nginx 的 fe.server.com 属于同源访问,而 Nginx 对服务端转发的请求不会触发浏览器的同源策略。
gzip on;
# 要采用 gzip 压缩的 MIME 文件类型,其中 text/html 被系统强制启用;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# —- 以上两个参数开启就可以支持 Gzip 压缩了 —- #
# 默认 off,该模块启用后,Nginx 首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容;
gzip_static on;
# 默认 off,nginx 做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩;
gzip_proxied any;
# 用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩;
gzip_vary on;
# gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6;
gzip_comp_level 6;
# 获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得;
gzip_buffers 16 8k;
# 允许压缩的页面最小字节数,页面字节数从 header 头中的 Content-Length 中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大;
# gzip_min_length 1k;
# 默认 1.1,启用 gzip 所需的 HTTP 最低版本;
gzip_http_version 1.1;

Master Process 用来管理子进程的,其本身并不真正处理用户请求。
某个子进程 down 掉的话,它会向 Master 进程发送一条消息,表明自己不可用了,此时 Master 进程会去新起一个子进程。
某个配置文件被修改了 Master 进程会去通知 work 进程获取新的配置信息,这也就是我们所说的热部署。
子进程间是通过共享内存的方式进行通信的。
配置文件重载原理
Nginx 模块化管理机制