安装

  • 分发版本安装

    1
    2
    sudo apt update
    sudo apt-get install nginx
  • docker安装

  • 编译安装

基础知识

基础命令

  • 启动Nginxnginx

  • 查看版本:nginx -v

    image-20230422160713618

  • 等所有进程停止后退出Nginxnginx -s quit

  • 暴力退出Nginxnginx -s stop

  • 重新加载配置文件(热更新):nginx -s reload

  • 测试配置文件:nginx -t

目录结构

  • Ubuntu 20.04使用apt安装nginx.1.18.0(Ubuntu)为例,不同版本可能不完全一致,但相似
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.
├── conf.d # 用户自己定义的conf配置文件
├── fastcgi.conf # fastcgi相关参数,cgi与fastcgi关系可查看参考4(What is CGI, FastCGI?)
├── fastcgi_params # fastcgi相关参数,与fastcgi.conf 区别如后所示
├── koi-utf # 编码转换映射文件, charset_map koi8-r < -- > utf-8
├── koi-win # 编码转换映射文件, charset_map koi8-r < -- > windows-1251
├── mime.types # 文件扩展名与文件类型映射表,nginx根据映射关系,设置http请求响应头的Content-Type值
├── modules-available # 可用模块配置
├── modules-enabled # 启用模块配置
│   ├── 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf
│   ├── 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf
│   ├── 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf
│   └── 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf
├── nginx.conf # 主配置文件(全局配置)
├── proxy_params # proxy相关参数
├── scgi_params # scgi相关参数
├── sites-available # 可用网站配置,系统默认设置的配置文件
│   └── default
├── sites-enabled # 启用网站配置,由sites-available中的配置文件转换生成
│   └── default -> /etc/nginx/sites-available/default
├── snippets # 重复的配置可放在这里,被其他文件引用
│   ├── fastcgi-php.conf
│   └── snakeoil.conf
├── uwsgi_params # uwsgi相关参数
└── win-utf # 编码转换映射文件, charset_map windows-1251 < -- > utf-8

内置变量

  • $args :这个变量等于请求行中的参数,同 $query_string
  • $content_length :请求头中的 Content-length 字段
  • $content_type :请求头中的 Content-Type 字段
  • $document_root :当前请求在 root 指令中指定的值
  • $host :请求行的主机名,为空则为请求头字段 Host 中的主机名,再为空则与请求匹配的 server_name
  • $http_host$host加端口
  • $http_user_agent :客户端 agent 信息
  • $http_cookie :客户端 cookie 信息
  • $limit_rate :这个变量可以限制连接速率
  • $request_method :客户端请求的动作,通常为 GET 或 POST
  • $remote_addr :客户端的 IP 地址
  • $remote_port :客户端的端口
  • $remote_user :已经经过 Auth Basic Module 验证的用户名。
  • $request_filename :当前请求的文件路径,由 root 或 alias 指令与 URI 请求生成
  • $scheme :HTTP 方法(如 http,https)
  • $server_protocol :请求使用的协议,通常是 HTTP/1.0 或 HTTP/1.1
  • $server_addr :服务器地址,在完成一次系统调用后可以确定这个值
  • $server_name :服务器名称
  • $server_port :请求到达服务器的端口号
  • $request_uri :包含请求参数的原始 URI,不包含主机名,如:”/foo/bar.php?arg=baz”
  • $uri :不带请求参数的当前 URI,$uri 不包含主机名,如”/foo/bar.html”
  • $document_uri :与 $uri 相同

配置文件介绍

概述

  • 分为四个部分

    • 全局配置:影响Nginx服务器全局 ,一般配置worker数量,错误日志等
    • events配置:负责Nginx与客户端的网络连接,如配置网络IO模型,配置单个worker支持的最大连接数等
    • http模块:主要配置部分,配置请求转发,反向代理等的地方
    • virtual hosts模块:通过虚拟主机将不同的配置进行隔离

    image-20230410220600668

配置文件详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
######## global ########
# 配置Nginx运行时的用户及用户组
# 默认为nobody nobody
user www www;

# 设置worker进程数量
# 根据CPU数量设置
# 默认数量为1,可以设置为auto来自动设置
worker_processes 2;

# 设置erro_log路径及级别,可以设置记录多个级别的信息
# 级别:debug|info|notice|warn|error|crit|alert|emerg
error_log /var/log/nginx/error.log info;
error_log /var/log/nginx/error.log debug;
error_log /var/log/nginx/error.log error;

# 进程文件地址,记录了主进程的进程ID
pid /var/run/nginx.pid;

# 设定每个worker能够打开的文件描述符最大数量
worker_rlimit_nofile 65535

######## events ########
events {
# 设置网路连接序列化,防止惊群现象发生,默认为on
# accept_mutex on;

# 设置一个进程是否同时接受多个网络连接,默认为off
# multi_accept on;

# 使用epoll作为网络通讯模型
use epoll;
# 单个worker的最大连接数
worker_connections 1024;
}

######## http ########
http {
# 文件扩展名与文件类型映射表
# include mime.types;

# 默认文件类型,默认为text/plain
# default_type application/octet-stream;

# 自定义日志格式
# combined为日志格式的默认值
# 参考10提到,需要需要开启压缩 gzip on; 否则不生成日志文件(待验证)
# log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for';
# access_log log/access.log myFormat;
# gzip on;

# 以下四个和客户端相关
# 当客户端发起请求时,Nginx默认会使用client_header_buffer_size作为缓冲区来读取HTTP请求头的信息
# 当HTTP请求头的信息大小超过1k时,使用large_client_header_buffers作为缓冲区读取
# 再次超过,则会返回400错误码
client_header_buffer_size 1k;
large_client_header_buffers 21k;
# body缓冲区大小,类似上面的头部大小设定
# 超过client_max_body_size,则会返回413错误码
client_body_buffer_size 16k;
client_max_body_size 8m;

# 这三个一般配合使用,与网络IO相关
# 涉及零拷贝,即是否有缓冲区拷贝等
sendfile on;
# 优化一次性数据发送量
tcp_nopush on;
# 关闭了网络拥塞算法
tcp_nodelay on;

# 同一个连接最大的请求数量,默认100
keepalive_requests 100000;
# 同一个连接存活的时间,单位为秒
keepalive_timeout 120;

# 错误页
# error_page 404 https://www.baidu.com;

######## virtual hosts ########
server {
# 监听端口
listen 80;
# 请求域名 多个用空格分隔
# 可以是:全名,通配符,正则表达式
server_name example.org www.example.org;

# location是对server_name更为详细的配置,紧跟通配符或正则表达式
# 匹配到不同规则,返回不同结果
# 当请求为图片时,设置了过期时间为10天
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 10d;
}

# 匹配server_name/
# 配到到即会返回/usr/share/nginx/html/index.html给客户端
location / {
root /usr/share/nginx/html;
index index.html;
}

# server_name/app
location /app/ {
proxy_pass http://127.0.0.1:88;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;
}
}
}

location

  • 优先级顺序:精确匹配,前缀匹配,正则匹配,普通字符匹配

  • 精确匹配(=):等于,严格匹配,如果找到,立即停止搜索并立即处理此请求

  • 前缀匹配(^~):如果匹配成功,则不再匹配其它 location,^表示 “非”,即不查询正则表达式

  • 正则匹配(~和~*):前者表示区分大小写,后者表示不区分大小写

  • 示例

    1
    2
    3
    4
    5
    6
    7
    location ^~ /images/ {
    proxy_pass http://localhost:8080;
    }

    location ~ \.jpg {
    proxy_pass http://localhost:8080;
    }
    • /images/1.jpg代理到 http://localhost:8080/images/1.jpg
    • /some/path/1.jpg代理到http://localhost:8080/some/path/1.jpg

Upstream

  • 负载均衡模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    http {
    # 将多个服务器放在cluster1集群中
    upstream cluster1 {
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    server {
    # 匹配到时,讲请求转发到cluster1集群中
    # 具体分配根据负载均衡策略进行分配
    location /app1/ {
    proxy_pass http:ss//cluster1/;
    }
    }
    }
  • 负载均衡策略

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    # 轮询,默认方式,按照时间顺序一个个分配
    # 如果有服务器下线,Nginx会自动提出下线服务器
    upstream cluster1 {
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    # weight
    # 权重越高,分配的请求越多
    upstream cluster1 {
    server 192.168.1.163:8080 weight = 1;
    server 192.168.1.164:8080 weight = 1;
    server 192.168.1.165:8080 weight = 10;
    }

    # ip_hash
    # 根据客户端的IP来固定选择分配的服务器
    upstream cluster1 {
    ip_hash;
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    # hash
    # 通用hash,允许用户自定义hash的key,key可以是字符串、变量或组合
    # 例如,key可以是配对的源 IP 地址和端口,也可以是 URI
    # consistent参数启用 ketama一致哈希算法
    upstream backend {
    hash $request_uri consistent;
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    # 最小连接
    # 将下一个请求分配给活动连接数最少的服务器(较为空闲的服务器)
    upstream backend {
    least_conn;
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    # 随机
    # 每个请求都将传递到随机选择的服务器
    # two是可选参数,NGINX 在考虑服务器权重的情况下随机选择两台服务器,然后使用指定的方法选择其中一台,默认为选择连接数最少(least_conn)的服务器
    upstream backend {
    random two least_conn;
    server 192.168.1.163:8080;
    server 192.168.1.164:8080;
    server 192.168.1.165:8080;
    }

    # 健康检查
    # 在反向代理中,如果后端服务器在某个周期内响应失败次数超过规定值,nginx会将此服务器标记为失败,并在之后的一个周期不再将请求发送给这台服务器
    # 通过fail_timeout来设置检查周期,默认为10秒
    # 通过max_fails来设置检查失败次数,默认为1次
    upstream backend {
    server 192.168.1.163:8080;
    server 192.168.1.164:8080; max_fails=3 fail_timeout=30s;
    }

try_files

  • try_files:可用于检查指定的文件或目录是否存在,如果不存在,则重定向到指定位置

  • 如下,如果原始URI对应的文件不存在,NGINX将内部重定向到/www/data/images/default.gif

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    server {
    root /www/data;

    location /images/ {
    # 最后一个参数也可以是状态代码(状态码之前需要加上等号)
    try_files $uri /images/default.gif;
    }

    location / {
    try_files $uri $uri/ $uri.html =404;
    }

    # 如果原始 URI 和附加尾随斜杠的 URI 都没有解析到现有文件或目录中,则请求将重定向到命名位置,该位置会将其传递到代理服务器
    location / {
    try_files $uri $uri/ @backend;
    }

    location @backend {
    proxy_pass http://backend.example.com;
    }

    }

return与rewrite

return

  • 服务端停止处理并将状态码status code返回给客户端

    • return code URL
    • return code text
    • return code
    • return URL
  • 强制所有请求使用HTTPS

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 错误写法
    server {

    listen 8003;
    server_name a.hello.com

    return 301 https://localhost:8004;
    }

    # 正确写法
    server {

    listen 8003;
    server_name a.hello.com

    return 301 https://192.168.56.105:8004;
    }

    # 原因在于return是重定向,而proxy_pass是转发,因此使用return时不能使用localhost

rewrite

  • 如果指定的正则表达式与请求 URI 匹配,则 URI 将按照字符串中的指定进行更改。指令按其在配置文件中出现的先后顺序执行

    1
    2
    3
    4
    5
    6
    7
    server {
    # ...
    rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra last;
    return 403;
    # ...
    }
    • 上面是使用该指令的示例 NGINX 重写规则。它匹配以字符串 /download 开头的 URL,然后在路径后面的某个位置包含 /media//audio/ 目录
    • 它将这些元素替换为 /mp3/,并添加相应的文件扩展名,.mp3.ra。和 变量捕获未更改的路径元素
    • 例如
      • /download/cdn-west/media/file1 变成了 /download/cdn-west/mp3/file1.mp3
      • 如果文件名上有扩展名(如 .flv),则表达式会将其剥离,并将其替换为.mp3
  • 如果字符串包含新的请求参数,则以前的请求参数将追加到这些参数之后。如果不需要这样做,则在替换字符串的末尾放置一个问号可以避免附加它们

    1
    rewrite ^/users/(.*)$ /show?user=$1? last;

last与break

  • last:如果当前规则匹配,停止处理后续rewrite规则,使用重写后的路径,重新搜索location及其块内指令
  • break:如果当前规则匹配,停止处理后续rewrite规则,执行{}块内其他指令

使用

概述及使用建议

conf.d和sites-available

  • 直接在conf.d里面配置xx.conf比在sites-available中配置,再添加超链接到sites-enabled中方便

重复的配置可继承自父级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 推荐
server {
server_name www.example.com;
root /var/www/nginx-default/;

location / {
# root继承父级配置
# [...]
}
location /foo {
# root继承父级配置
# [...]
}
location /bar {
# 覆盖
root /some/other/place;
# [...]
}
}

# 不推荐
server {
server_name www.example.com;

location / {
root /var/www/nginx-default/;
# [...]
}
location /foo {
root /var/www/nginx-default/;
# [...]
}
location /bar {
root /some/other/place;
# [...]
}
}

不要将所有请求都代理到后端服务器(动静分离)

  • 考虑到很多请求是访问静态内容(如图片,css,javascript等文件),可以使用缓存或者配置静态目录来减少发送到后端的请求数量,这样可以减小后端服务器的开销
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 推荐
server {

listen 8002;
server_name ruoyi.tomcat;
root /home/www/static;

location / {
try_files $uri $uri/ @proxy;
}

location @proxy {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://localhost:8080;
}

}

# 不推荐
location / {
proxy_pass http://localhost:8088;
}

检查文件是否存在使用try_files代替if -f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 推荐
server {
root /var/www/example.com;
location / {
try_files $uri $uri/ /index.html;
}
}

# 不推荐
server {
root /var/www/example.com;
location / {
if (!-f $request_filename) {
break;
}
}
}

在重写路径中包含http://或https://

1
2
3
4
5
# 推荐
rewrite ^ http://example.com permanent;

# 不推荐
rewrite ^ example.com permanent;

通过域名访问(反向代理)

HTTP代理

  • 直接在浏览器输入域名即可访问同一服务器部署的不同网站,不需要显示输入端口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    server {
    listen 80 default_server; # 监听端口
    root /mnt/aa; # 访问根目录
    index index.html index.htm; # 默认页,可以不设置
    server_name www.hello.com; # 根据域名跳转
    location / {
    try_files $uri $uri/ =404;
    proxy_pass http://127.0.0.1:8081; # 跳转的路径
    }
    }
    server {
    listen 80; # 监听端口
    root /mnt/bb;
    index index.html index.htm;
    server_name bs.hello.com;
    location / {
    try_files $uri $uri/ =404;
    proxy_pass http://127.0.0.1:8082; # 另一个路径
    }
    }

    # 如果proxy-pass的地址包括/或其他路径,那么/some/path将会被替换
    # 如下所示,访问 http://localhost/some/path/page.html 将被代理到 http://localhost:8080/zh-cn/page.html
    server {
    listen 80; # 监听端口
    server_name 1.hello.com;
    location /some/path/ {
    proxy_pass http://localhost:8080/zh-cn/;
    }
    }
  • 由于使用反向代理之后,后端服务无法获取用户的真实IP,所以,一般反向代理都会设置以下header信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    location /some/path/ {
    #nginx的主机地址
    proxy_set_header Host $http_host;
    #用户端真实的IP,即客户端IP
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_pass http://localhost:8088;
    }
  • 常用变量的值

    • $host:nginx主机IP,例如192.168.56.105
    • $http_host:nginx主机IP和端口,192.168.56.105:8001
    • $proxy_host:localhost:8088,proxy_pass里配置的主机名和端口
    • $remote_addr:用户的真实IP,即客户端IP。

非HTTP代理

  • fastcgi_pass:将请求转发到FastCGI服务器(多用于PHP)

  • scgi_pass:将请求转发到SCGI server服务器(多用于PHP)

  • uwsgi_pass:将请求转发到uwsgi服务器(多用于python)

  • memcached_pass:将请求转发到memcached服务器

  • TCP反向代理:与HTTP反向代理同级,需要修改nginx.conf文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # HTTP代理
    http {
    server {
    listen 8002;
    proxy_pass http://localhost:8080/;
    }
    }

    # TCP代理
    stream {
    server {
    listen 13306;
    proxy_pass localhost:3306;
    }

SSL设置(HTTPS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 443 ssl;
server_name www.hello.com;

ssl_certificate [证书公钥路径];
ssl_certificate_key [证书密钥路径];
# 如果设置了密码,需要加上
# ssl_password_file /home/ssl/cert.pass;
ssl_session_timeout 5m;
# 表示使用的加密套件的类型
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
# 表示使用的TLS协议的类型
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root /mnt/cc; #站点目录
try_files $uri $uri/ /index.html;
}
}

允许与禁止IP

1
2
3
4
5
6
7
8
allow 12.12.12.22  # 允许访问
deny 223.104.123.12; # 禁止访问

deny 123.0.0.0/8; # 封 123.0.0.1~123.255.255.254 这个段的ip
deny 123.1.0.0/16; # 封 123.1.0.1~123.1.255.254 这个段的ip
deny 123.1.1.0/24; # 封 123.1.1.1~123.1.1.254 这个段的ip

deny all; # 除allow的IP地址外,其他的IP地址都禁止访问

域名迁移,不让用户收藏的链接或者搜索引擎的链接失效

  • 将请求从 www.old-name.com old-name.com永久重定向到 www.new-name.com,包含http和https请求

    1
    2
    3
    4
    5
    6
    server {
    listen 80;
    listen 443 ssl;
    server_name www.old-name.com old-name.com;
    return 301 $scheme://www.new-name.com;
    }

答疑

fastcgi_params和fastcgi.conf的区别

  1. 两者的差异

    1
    2
    # fastcgi.conf只比fastcgi_params多了一行
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  2. 原本只有fastcgi_params文件,fastcgi.confnginx 0.8.30 才引入的,主要为是解决部分人在定义SCRIPT_FILENAME时采用硬编码的方式,如fastcgi_param SCRIPT_FILENAME /var/www/foo$fastcgi_script_name,于是为了规范用法便引入了fastcgi.conf

  3. 为什么要引入新文件,而不是在旧的文件上改造?

    • 这是因为fastcgi_param指令是数组型
      • 和普通指令相同的是:内层替换外层;
      • 和普通指令不同的是:当在同级多次使用的时候,是新增而不是替换
    • 换句话说,如果在同级定义两次SCRIPT_FILENAME,那么它们都会被发送到后端,这可能会导致一些潜在的问题,为了避免此类情况,便引入了一个新的配置文件
  4. 推荐使用:fastcgi.conf

转发和重定向

  • 转发是服务端行为,重定向是客户端行为

  • 转发:反向代理proxy_pass属于转发,浏览器的访问栏输入的地址不会发生变化

    截屏2022-08-09 下午2.47.52.png

  • 重定向:returnrewrite属于重定向,在客户端进行。浏览器的访问栏输入的地址会发生变化

    截屏2022-08-09 上午11.09.32.png

注意事项

  1. 正确的配置未生效,请清除浏览器缓存
    • 当你确定修改的配置的正确的,但是未生效,请清除浏览器缓存或者禁用浏览器缓存
  2. HTTPS不启用 SSLv3
    • 由于 SSLv3 中存在 POODLE 漏洞,建议不要在启用了 SSL 的站点中使用 SSLv3
    • 规则:ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  3. 不要将 root 目录配置成 //root
  4. 谨慎使用chmod 777
    • 可以使用namei -om /path/to/check显示路径上的所有权限,并找到问题的根本原因

附录

默认文件

nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 768;
# multi_accept on;
}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;

# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}


#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}

default

  • sites-available/default
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;

# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;

root /var/www/html;

# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;

server_name _;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}

进程模型

image-20230410220106907

本地测试环境与backup

  • 使用podman搭建本地 Nginx 测试环境,docker同理,镜像可见docker:nginx

    • podman启动报错及解决: Podman mount host volume return ‘Error: statfs: no such file or directory’ in Mac OS

    • Nginx版本

      1
      2
      root@xxx:/# nginx -v
      nginx version: nginx/1.25.3
    • Nginx.conf

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      # 启动 并指定自定义 nginx.conf
      # :ro 表示 read only
      podman run --name nginx-test -v ./nginx.conf:/etc/nginx/nginx.conf:ro -p 7890:80 nginx

      # nginx.conf
      # 用于测试 backup 调度策略
      events {
      use epoll;
      worker_connections 1024;
      }

      http {
      upstream backend {
      server x.x.x.x:1234;

      server x.x.x.x:1235 backup;
      server x.x.x.x:1236 backup;
      server x.x.x.x:1237 backup;
      }

      server {
      location / {
      proxy_pass http://backend;
      }
      }
      }
  • 使用 Python 搭建本机简易 webserver

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import argparse
    from flask import Flask

    app = Flask(__name__)

    @app.route('/')
    def hello_world():
    return f'Hello, World! Running on port {app.config["PORT"]}'

    if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="A simple Flask application.")
    parser.add_argument('-p', '--port', type=int, help="The port number to listen on.", default=1234)
    args = parser.parse_args()

    app.config["PORT"] = args.port
    # 如果不指定 host='0.0.0.0',那么只能通过 127.0.0.1:port 才能访问
    # 使用 ifconfig 查到的 ip:port 方式无法访问
    # 报错: curl: (7) Failed to connect to ip port xxx after 7 ms: Couldn't connect to server
    app.run(host='0.0.0.0', port=args.port)
    • 关于 host 配置,flask 源码介绍如下

      :param host: the hostname to listen on. Set this to '0.0.0.0' to

      have the server available externally as well. Defaults to

      '127.0.0.1' or the host in the SERVER_NAME config variable

      if present.

  • Nginx backup,可通过curl http://localhost:7890进行测试,7890即启动容器时映射的端口,首先都会尝试访问主

    • 主可用时,不会访问 backup

    • 主不可用时,轮询访问 backup,每次一个,如果上一个 backup 不可用,才会到下一个 backup,官方介绍

      By default, requests are distributed between the servers using a weighted round-robin balancing method. In the above example, each 7 requests will be distributed as follows: 5 requests go to backend1.example.com and one request to each of the second and third servers. If an error occurs during communication with a server, the request will be passed to the next server, and so on until all of the functioning servers will be tried. If a successful response could not be obtained from any of the servers, the client will receive the result of the communication with the last server.

    • 假设一主三备

      1. 前五次访问,主可用,一直访问主
      2. 第六次访问时,主不可用,访问备 A
      3. 第七次访问时,主可用,访问备 B
      4. 第八次访问时,主可用,访问主
      5. 第九次访问时,主不可用,访问备 C,如果备 C 不可用,则会依次轮训备 A 和备 B

参考

  1. 亲自动手搭建一个Nginx反向代理服务器
  2. Nginx官网
  3. nginx一小时入门教程,视频笔记
  4. What is CGI, FastCGI?
  5. Linux下nginx.conf中 fastcgi_params和fastcgi.conf的区别
  6. nginx 配置文件的介绍
  7. Nginx安装配置和常用使用(反向代理与负载均衡)
  8. NGINX Configuration Guide
  9. How to Configure NGINX
  10. Nginx常用配置及和基本功能讲解