实施部署 Nginx在项目上的应用与常见问题(四)

字数: 2394

本文总结Nginx在项目上的实际应用,本文包含了Nginx的常用配置与在项目中遇到的问题。信创版本的负载均衡中间件其实也是类似于Nginx,以宝兰德负载均衡中间件BWS为例。

Nginx 负载均衡,在生产环境上常常会用到。简单通俗的架构如下:

在生产环境,通常具有多台应用服务器(一般为集群),通过 Nginx 服务器配置的地址去访问同一个应用,通过 Ng 实现应用的高并发、高可用。

Nginx基础

Nginx 的配置文件,是 Nginx_home/conf/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
# 全局块
# user user_name;                   # 运行 nginx 进程的用户名
...

# 事件块
events {
  ...
}

# http 块
http {
  # http 全局块
  ...
  # server 块
  server {
    # server 全局块
    ...
    # upstream 块
    upstream name {
      ...
    }
    # location 块
    location [PATTERN] {
      ...
    }
  }
}

全局块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 全局块通常是配置用户、日志、进程、pid 等
# 注意,全局块中涉及的路径,需 nginx 有权限读写。

# 运行 nginx 进程的用户名,指 Linux 用户
user user_name;
# 设置 nginx 的进程数,默认为 1,一般进程数=CPU 核数即可。双核配 2,4 核配 4.
worker_processes 1;
# nginx 的工作目录,不配置,默认在 logs 下
working_directory nginx_path/logs;
# 设置日志级别:debug\info\notice\warn\error\crit(高到低)
error_log nginx_path/logs/error.log info;
# 也可以使用默认,记录 error
error_log nginx_path/logs/error.log
# pid,设置 nginx 进程的 pid 文件路径和名称
pid nginx_path/logs/nginx.pid;

全局块,通常配置 user worker_processes error_log pid 即可。

解释一下 pid,这个东西就是 nginx 运行时的进程 id(Linux 每个进程都有一个进程 id,即 pid),配置 pid,就是为了将 nginx 的进程 id 写到这个文件中(例如上方的 nginx.pid 文件),可以用来判断 nginx 是否运行,防止启动多个 nginx 进程的。

网上的说法是这样的:nginx 启动时,会去找这个设置的 pid 文件,一是看这个文件是否存在,二是看 pid 文件中记录的 pid 进程是否存在,如果 pid 文件存在并且 pid 进程也存在,则说明 nginx 已经启动了,那么启动就会报错,防止启动多个 nginx 进程。

事件块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# events 块,是 nginx 处理连接的配置块
events {
  # 配置每个工作进程的最大连接数,默认 1024
  worker_connection 1024;
  # 鼓励接收,这个可不配
  multi_accept on;
  # 处理连接的事件模型,默认 epoll,可不配
  use epoll;
  # 其他可百度
}

其实只需要配置一个 worker_connection 即可

http 块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
http {
  # http 全局块常用配置
  include mime.types;    # 文件扩展名与文件类型映射表
  default_type application/octet-stream;  # 默认文件类型
  access_log logs/access.log main;    # 日志路径、格式
  access_log on;                      # 开启日志,记录客户端请求信息
  sendfile on;           # 开启文件传输功能
  keepalive_timeout 65s;    # 保持连接超时时长,超过这个时间,连接关闭
  client_max_body_size 10m;    # 允许文件传输的最大值,根据实际情况设置
  client_header_buffer_size 4k;  # 客户端请求头缓冲区大小,k(千字节)
  client_body_buffer_size 8m;  # 客户端请求体缓存区大小,m(MB)
}

client_max_body_size 参数,对传输的文件大小做限制 client_header_buffer_size client_body_buffer_size 参数,为了确保请求头(体)数据不会因为缓冲区太小而被截断

server 块

server 块里包含了 upstream 块、location 块

 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
# 该块在 http 块下
# 通过配置的服务名和监听端口去访问时,根据不同的权重随机跳转到应用服务端
# 这里的链路大概如下:

# 访问 ng 地址:http://hello:80/app  >>>  跳转 http://fzjh/app
# >>> 根据 upstream 块获取 fzjh 配置的 server   
# >>> 根据权重访问 http://192.168.1.1:8080/app http://192.168.1.2:8080/app

http {
  # http 全局块
  ...
  # server 块
  server {
    listen 80;        # 监听端口,默认 80,需要根据实际情况更改
    server_name hello;    # 用来做跳转应用的服务名
    # upstream 块  负载均衡关键块
    upstream fzjh {
      server 192.168.1.1:8080 weight=1;  # 服务器 1,权重 1
      server 192.168.1.2:8080 weight=2;  # 服务器 2,权重 2
    }
    
    # location 块  反向代理关键块
    location /app {        # 指定访问的后缀
      proxy_pass http://fzjh/app;   # proxy_pass 反向代理关键字 
    }
  }
}

说明:通常只是做反向代理的话,是不需要配置 upstream 块的,只需要配置 location 块。

负载均衡策略

负载均衡策略的问题,其实就是在 upstream 块里边去配置。比如步骤【4)server 块】中的 upstream 块用法就是一个加权轮询策略,weight=1 =2 就是服务器的权重,通过给服务器分配权重,权重大的服务器将接收更多的请求。(数值越大,权重越高

 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
# 轮询
upstream fzjh {
  server 192.168.1.1:8080;
  server 192.168.1.2:8080;
  server 192.168.1.3:8080;
}

# 加权轮询
upstream fzjh {
  server 192.168.1.1:8080 weight=1;
  server 192.168.1.2:8080 weight=3;
  server 192.168.1.3:8080 weight=5;  # 权重越大,接收请求越多
}

# ip hash
upstream fzjh {
  ip_hash;            # 没错,就是加上这个参数即可
  server 192.168.1.1:8080;
  server 192.168.1.2:8080;
  server 192.168.1.3:8080;
}

# 最少连接
upstream fzjh {
  least_conn;        # 没错,也是加个参数即可
  server 192.168.1.1:8080;
  server 192.168.1.2:8080;
  server 192.168.1.3:8080;  
}

Nginx启停

1
2
3
4
5
6
# 启动
cd nginx_home/sbin && ./nginx
# 停止  pid 文件的路径为全局块中设置
kill -QUIT `cat nginx_home/logs/nginx.pid`
# 重启
cd nginx_home/sbin && ./nginx -s reload

Nginx遇到的问题

文件上传超限

通常在使用 ng 访问应用时,在应用上传附件时,会遇到如下报错:

1
request entity too large nginx 解决方案

此错误是由于上传文件的大小超过 nginx 配置的文件传输最大值导致。通过更改 client_max_body_size 的大小即可(没有则在 HTTP块 新增即可)。更改完需要重启 nginx 服务。

无法显示验证码

应用的登录页面需要输入验证码,当通过Ng跳转到应用时,不显示验证码。在upstream 里把负载均衡策略改为 IP HASH

配置案例

反向代理

该配置为审计项目开发环境、测试环境的实际配置。当然,信创版本,使用的是 宝兰德 BWS 中间件(国产版的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
user  bes;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/bws.pid;
events {
  worker_connections 1024;
}

http {
  include 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 logs/access.log main;
  access_log on;
  sendfile on;
  keepalive_timeout 65s;
  server {
    #bws_http_server_name:server-tPegV0o6
    #bws_http_server_type:reverseProxy
    listen 8070;
    server_name 192.168.XXX.56;
    location / {
      #type:static
      #bws_http_server_location_name:location-OsbKN52L
      index index.html index.htm;
     
    }
    location /app {
       proxy_pass http://192.168.XXX.59:18080/app;
         # 此处判断,允许跨源请求、http 方法、带 cookie 信息,通用配置 -- 开始
        if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin '*';
                add_header Access-Control-Allow-Headers '*';
                add_header Access-Control-Allow-Methods '*';
                add_header Access-Control-Allow-Credentials 'true';
                return 204;
            }
           
            proxy_http_version 1.1;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
                    proxy_set_header Origin "";
					proxy_set_header Cookie $http_cookie;
         # 通用配置  -- 结束           
    }
    location = /50x.html {
      #type:static
      #bws_http_server_location_name:location-8t7KLrfH
      root html;
    }
    location = /bws_status {
      #bws_http_server_location_name:monitor
      stub_status on;
    }
    error_page 500 502 503 504 /50x.html;
  }
  gzip off;
  gzip_comp_level 1;
  gzip_min_length 1k;
  client_max_body_size 1024m;
  client_header_buffer_size 4k;
  client_body_buffer_size 8m;
}

worker_processes 1;
error_log logs/error.log info;

负载均衡

审计项目生产环境的配置(已脱敏)

 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
#user  nobody;
worker_processes auto;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/bws.pid;
events {
  worker_connections 512;
  use epoll;
}
 
http {
  include 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  logs/access.log  main;
  access_log off;
  sendfile on;
  #tcp_nopush     on;
  #keepalive_timeout  0;
  keepalive_timeout 75;
  #gzip  on;
  server {
    listen 8080;
    server_name SJGL-JR2-JQ;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    location /app {
      index index.html index.htm;
      proxy_cache off;
      concat off;
      sysguard off;
      proxy_pass http://app-8080/app;
    }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
      root html;
      proxy_cache off;
      concat off;
      sysguard off;
    }
  }
  upstream app-8080 {
    server SJGL-YY1-JQ:8080;
    server SJGL-YY2-JQ:8080;
    server SJGL-YY3-JQ:8080;
    server SJGL-YY4-JQ:8080;
    ip_hash;
    check interval=30000 fall=3 rise=2 default_down=false timeout=1000 type=tcp port=8080;
  }
}
Licensed under CC BY-NC-SA 4.0
最后更新于 2024年10月14号 22:35