本文总结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;
}
}
|