Contents

Nginx

参考资料

快速入门

Nginx (engine x) 是一款轻量级的 Web 服务器、反向代理服务器、电子邮件(IMAP/POP3)代理服务器

反向代理 Reverse Proxy,指以代理服务器来 接受客户端请求
然后将请求 转发给内部网络 上的服务器,并将从服务器上得到的结果返回给请求连接的客户端
此时代理服务器对外就表现为一个反向代理服务器,对客户端隐藏了真实服务器

常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 显示版本信息
nginx -v

# 测试配置文件语法正确性
nginx -t -c conf/nginx.conf

# 指定配置文件启动 nginx
nginx -c conf/nginx.conf

# 快速停止
nginx -s stop
  • 配置文件结构

    • events:连接处理模型(如 worker_connections
    • http:定义 MIME 类型、日志格式、上游服务器(upstream)等
    • server:虚拟主机配置,包含监听端口、域名、路由规则(location)

建议

  • 路径分隔符兼容性

    Windows 路径(如 D:\...)在 Nginx 中需改为正斜杠 / 或双反斜杠 \\
    推荐 root D:/workspace/webapp;

  • 静态资源优化,开启 gzip 压缩减少传输体积

    1
    2
    
    gzip on;
    gzip_types text/css application/javascript image/svg+xml;
    
  • 隐藏 Nginx 版本信息

    1
    
    server_tokens off;
    
  • 限制敏感文件访问(如 .git、备份文件)

    1
    
    location ~ /\.(git|bak|env) { deny all; }
    

实战

Http 反向代理

conf/nginx.conf 是 nginx 的默认配置文件
也可以自定义

  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
# 运行用户
# user somebody;

# 启动进程,通常设置成和 cpu 的数量相等
worker_processes  1;

# 全局错误日志
error_log  D:/Tools/nginx-1.10.1/logs/error.log;
error_log  D:/Tools/nginx-1.10.1/logs/notice.log  notice;
error_log  D:/Tools/nginx-1.10.1/logs/info.log  info;

# PID 文件,记录当前启动的 nginx 的进程 ID
pid        D:/Tools/nginx-1.10.1/logs/nginx.pid;

# 工作模式及连接数上限
events {
    worker_connections 1024;    # 单个后台 worker process 进程的最大并发连接数
}

# 设定 http 服务器,利用它的反向代理功能提供负载均衡支持
http {
    # 设定 mime 类型(邮件支持类型),类型由 mime.types 文件定义
    include       D:/Tools/nginx-1.10.1/conf/mime.types;
    default_type  application/octet-stream;

    # 设定日志
    log_format  main  '[$remote_addr] - [$remote_user] [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log    D:/Tools/nginx-1.10.1/logs/access.log main;
    rewrite_log     on;

    # sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件
    # 对于普通应用,必须设为 on
    # 如果用来进行下载等磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的 uptime
    sendfile        on;
    # tcp_nopush     on;

    # 连接超时时间
    keepalive_timeout  120;
    tcp_nodelay        on;

    # gzip 压缩开关
    # gzip  on;

    # 设定实际的服务器列表
    upstream zp_server1 {
        server 127.0.0.1:8089;
    }

    # HTTP 服务器
    server {
        # 监听 80 端口,用于 HTTP 协议
        listen       80;

        # 定义使用 www.xx.com 访问
        server_name  www.helloworld.com;

        # 首页
        index index.html

        # 指向 web 应用的目录
        root D:\01_Workspace\Project\github\zp\SpringNotes\spring-security\spring-shiro\src\main\webapp;

        # 编码格式
        charset utf-8;

        # 代理配置参数
        proxy_connect_timeout 180;
        proxy_send_timeout 180;
        proxy_read_timeout 180;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarder-For $remote_addr;

        # 反向代理的路径(和 upstream 绑定),location 后面设置映射的路径
        location / {
            proxy_pass http://zp_server1;
        }

        # 静态文件,nginx 自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            root D:\01_Workspace\Project\github\zp\SpringNotes\spring-security\spring-shiro\src\main\webapp\views;
            # 过期 30 天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点
            expires 30d;
        }

        # 设定查看 Nginx 状态的地址
        location /NginxStatus {
            stub_status           on;
            access_log            on;
            auth_basic            "NginxStatus";
            auth_basic_user_file  conf/htpasswd;
        }

        # 禁止访问 .htxxx 文件
        location ~ /\.ht {
            deny all;
        }

        # 错误处理页面(可选择性配置)
        # error_page   404              /404.html;
        # error_page   500 502 503 504  /50x.html;
        # location = /50x.html {
        #    root   html;
        #}
    }
}

启动 web 应用,注意启动绑定的端口要和 upstream 设置的端口 server 127.0.0.1:8089; 保持一致
更改 host:在 C:\Windows\System32\drivers\etc 目录下的 host 文件中添加一条 DNS 记录
127.0.0.1 www.helloworld.com
启动 Nginx 在浏览器中访问 www.helloworld.com 即展示出 web 应用的服务

Https 反向代理

与上述 HTTP 的类似,只需要修改 server 内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
    # 监听 443 端口,主要用于 HTTPS 协议
    listen       443 ssl;

    server_name  www.helloworld.com;

    # ssl 证书文件位置(常见证书文件格式为:crt/pem)
    ssl_certificate      cert.pem;
    # ssl 证书 key 位置
    ssl_certificate_key  cert.key;

    # ssl 配置参数(选择性配置)
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    # 数字签名,此处使用 MD5
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        root   /root;
        index  index.html index.htm;
    }
}

负载均衡

假设这样一个应用场景:
将应用部署在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三台 linux 环境的服务器上
网站域名叫 www.helloworld.com
公网 IP 为 192.168.1.11
在公网 IP 所在的服务器上部署 nginx,对所有请求做负载均衡处理

 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
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

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

    # 设定负载均衡的服务器列表
    upstream load_balance_server {
        # weigth 参数表示权值,权值越高被分配到的几率越大
        server 192.168.1.11:80   weight=5;
        server 192.168.1.12:80   weight=1;
        server 192.168.1.13:80   weight=6;
    }

   # HTTP 服务器
   server {
        listen       80;

        server_name  www.helloworld.com;

        # 对所有请求进行负载均衡请求
        location / {
            root        /root;
            index       index.html index.htm;
            proxy_pass  http://load_balance_server ;    # 请求转向 load_balance_server 定义的服务器列表

            # 可选的反向代理的配置
            # proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            # 后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_connect_timeout 90;          # nginx 跟后端服务器连接超时时间(代理连接超时)
            proxy_send_timeout 90;             # 后端服务器数据回传时间(代理发送超时)
            proxy_read_timeout 90;             # 连接成功后,后端服务器响应时间(代理接收超时)
            proxy_buffer_size 4k;              # 设置代理服务器(nginx)保存用户头信息的缓冲区大小
            proxy_buffers 4 32k;               # proxy_buffers 缓冲区,网页平均在 32k 以下的话,这样设置
            proxy_busy_buffers_size 64k;       # 高负荷下缓冲大小(proxy_buffers*2)
            proxy_temp_file_write_size 64k;    # 设定缓存文件夹大小,大于这个值,将从 upstream 服务器传

            client_max_body_size 10m;          # 允许客户端请求的最大单文件字节数
            client_body_buffer_size 128k;      # 缓冲区代理缓冲用户端请求的最大字节数
        }
    }
}

负载均衡策略

  • 加权轮询 weight=1

  • 最少连接 least_conn;

  • 加权最少连接 least_conn;

  • IP Hash ip_hash;

  • 普通 Hash hash $request_uri;

多个模块的配置

假如 www.helloworld.com 站点有好几个模块
finance(金融)、product(产品)、admin(用户中心)

www.helloworld.com/finance/
www.helloworld.com/product/
www.helloworld.com/admin/

这三个应用需要分别绑定不同的端口号
但是一般用户访问这些站点的时候不会带着端口号去访问
可以使用反向代理处理

 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
http {
    # 此处省略一些基本配置

    upstream product_server {
        server www.helloworld.com:8081;
    }

    upstream admin_server {
        server www.helloworld.com:8082;
    }

    upstream finance_server {
        server www.helloworld.com:8083;
    }

    server {
        # 此处省略一些基本配置

        # 默认指向 product 的 server
        location / {
            proxy_pass http://product_server;
        }

        location /product/{
            proxy_pass http://product_server;
        }

        location /admin/ {
            proxy_pass http://admin_server;
        }

        location /finance/ {
            proxy_pass http://finance_server;
        }
    }
}

处理跨域问题

我有一台服务器上面部署了帆软报表系统 172.123.123.10:80
然后本地运行了 vue localhost:3366 和 python 后端 localhost:5000
请问该如何配置使得前端访问帆软报表系统的时候可以解决跨域问题?

使用 Nginx 作为反向代理服务器,将前端的请求转发到帆软报表系统和本地后端

 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
# 定义一个 upstream 组,用于负载均衡或简单的反向代理
upstream backend {
    server 172.123.123.10:80; # 帆软报表系统服务器
    server 127.0.0.1:5000;     # 本地Python后端服务器
}

# 定义一个 server 块,用于监听80端口的HTTP请求
server {
    listen 80;
    server_name your_domain.com; # 替换为你的域名

    # 静态资源和API请求的location配置
    # 代理所有请求到本地Vue前端
    location / {
        proxy_pass http://127.0.0.1:3366;
        # 设置HTTP请求头
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-NginX-Proxy true;
    }

    # 帆软报表系统的location配置
    # 处理所有以/report/开头的请求,将它们代理到帆软报表系统
    location /report/ {
        proxy_pass http://backend; # 使用upstream组
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-NginX-Proxy true;
    }
}

将这个配置保存为 nginx.conf 或其他随意的文件名,并放置在 Nginx 的配置目录下
然后,需要重新加载 Nginx 配置以使更改生效:
sudo nginx -s reload
sudo systemctl reload nginx

其中 proxy_pass指令用于指定反向代理的目标地址
proxy_set_header指令用于传递客户端请求的原始 IP 和 Host 信息到后端服务器,这对于后端服务来说是必要的,尤其是在处理跨域请求时

如何将两个网站配置到同一域名下?

可以使用 server block 来实现,每个服务器块可以监听相同的域名,但是通过不同的路径或者通过设置不同的反向代理来区分流量

 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
# 监听80端口,处理HTTP请求
server {
    listen 80;
    server_name yourdomain.com;  # 你的域名

    # 网站1的配置
    location /site1/ {
        # 假设网站1运行在本地的8081端口
        proxy_pass http://localhost:8081/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 网站2的配置
    location /site2/ {
        # 假设网站2运行在本地的8082端口
        proxy_pass http://localhost:8082/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

# 如果需要处理HTTPS请求,可以添加一个监听443端口的服务器块
server {
    listen 443 ssl;
    server_name yourdomain.com;  # 你的域名

    # SSL证书配置
    ssl_certificate /path/to/your/certificate.pem;
    ssl_certificate_key /path/to/your/private.key;

    # 网站1的HTTPS配置
    location /site1/ {
        proxy_pass http://localhost:8081/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 网站2的HTTPS配置
    location /site2/ {
        proxy_pass http://localhost:8082/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server_name yourdomain.com; 指定了 Nginx 监听的域名
两个location块分别处理不同的路径。/site1/路径的请求被代理到本地的 8081 端口,而/site2/路径的请求被代理到本地的 8082 端口