1.Nginx正向代理和反向代理
有很多同学都分不清正向代理和反向代理,下面我尽量用通俗易懂的文字指出二者的区别。首先需要明白代理的意思,代理是指受委托代表当事人从事某种活动。正向代理就是平时说的代理(比如Shadowsocks就是正向代理),是指Nginx代理服务器受客户端委托代理客户端,转发请求,并将从服务端获得的响应返回给客户端;反向代理是指Nginx代理服务器受服务端的委托代理服务端,作为集群的web节点,反向代理一般和负载均衡配合使用。一言以蔽之:正向代理,代理端代理的是客户端;反向代理,代理端代理的是服务端。见下图:
nginx做反向代理时根据不同的配置策略,可以进行不同的转发,比如图片结尾的走文件服务器,动态页面走web服务器,而且可以判断被分发的服务器的状态,如果存在异常将转发给其它服务器。
2.负载均衡
负载均衡的实现必须依赖于反向代理,Nginx的负载均衡策略有两种:内置策略和扩展策略。
内置策略:
- 轮询:将请求依次轮询发给每个服务器。
- 最少连接:将请求发送给持有最少活动链接的服务器。
- IP哈希:通过哈希函数决定请求发送给哪个服务器。
- 权重:服务器的权重越高,处理请求的概率越大。
3.Nginx的配置文件
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... #全局块
events { #events块
...
}
http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN]
{
...
}
}
server
{
...
}
... #http全局块
}
- 全局块:一般配置影响nginx全局的指令。一般配置用户组,日志存放路径,pid存放路径和worker_connections;
- events块:配置nginx服务器与用户的网络连接。
- http块:可以嵌套多个server块,配置代理服务器,日志
- server块:可以嵌套多个location块,配置代理服务器的相关参数。
- location块:配置请求路由和处理请求的页面或服务器。
3.1 配置正向代理
现在前后端分离已经越来越流行,那么前端开发时可以在本地配置一个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########### 每个指令必须以分号结束。#################
#user nobody; #配置用户或者组,默认为nobody nobody。
#worker_processes 1; #允许生成的进程数,默认为1,设置的话一般设置成跟cpu数量相等
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别依次为:debug|info|notice|warn|error|crit|alert|emerg
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,仅用于linux2.6以上内核,可以大大提高nginx的性能
worker_connections 1024; #最大连接数
# 并发总数=worker_processes*worker_connections;
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
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; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
keepalive_timeout 65; #连接超时时间
tcp_nodelay on;
#开启gzip压缩
gzip on;
gzip_disable "MSIE [1-6].";
#设定请求缓冲
client_header_buffer_size 128k;
large_client_header_buffers 4 128k;
#设定虚拟主机配置
server {
#侦听1000端口(可以随意设定成你想要的未占用的端口)
listen 1000;
#定义使用 localhost访问(设定成你本地的IP地址或localhost)
server_name localhost;
#定义服务器的默认网站根目录位置
root html;
#设定本虚拟主机的访问日志
access_log logs/nginx.access.log main;
#默认请求
location / {
index index.html index.htm; #定义首页索引文件的名称
}
# 定义错误提示页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
#静态文件,nginx自己处理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。
expires 30d;
}
location ~* \.(html|js|css|png|jpg|jpeg|gif|ttf)$ {
proxy_pass http://127.0.0.1:63342; #访问http://localhost:1000/项目名/以html,js,css等结尾的文件请求均会被转发至http://127.0.0.1:63342;服务器中
}
location ~* \.*$ {
proxy_pass http://192.168.27.100:8180; #访问http://localhost:1000/项目名/任意路径的请求均会被转发至http://192.168.27.100:8180服务器中
}
#禁止访问 .ht结尾的文件
location ~ /.ht {
deny all;
}
}
}
我们最常配置的地方是location里面的代理服务器地址,这里要注意的是,1要把拦截小范围请求的放在前面,把拦截大范围请求的配置放在后面,因为像这里:location ~ .$ 拦截以结尾的请求(即所有请求),如果它放在前面了,那么请求再也走不到location ~ .(html|js|css|png|jpg|jpeg|gif|ttf)$这个配置里面了(在前面已经被拦截到了)。2.还是要注意检查结尾,我之前踩过一个坑,nginx配置文件是直接拷过来的,当时配置的location ~* .do$,此意为拦截以.do结尾的请求(java中可以配置),但我真正的请求是以.action结尾的,所以不会被拦截到,亦即不会被转发至后台服务器中,导致每次请求均是404。
3.2 配置负载均衡
配置负载均衡时Nginx充当的是反向代理服务器,当请求进来时,根据相应的负载策略,将请求分发至不同的处理器进行处理,配置步骤如下:
3.2.1 添加节点
在http块下,添加upstream节点。1
2
3
4upstream mytest {
server 192.168.1.1:8081;
server 192.168.1.2:8082;
}
mytest可以改成任何你喜欢的变量,
3.2.2 配置路径
将server块下的location节点中的proxy_pass配置为:http:// + upstream名称,即“
http://mytest”。1
2
3
4
5location / {
root html;
index index.html index.htm;
proxy_pass http://mytest;
}
现在负载均衡初步完成了。upstream按照轮询(默认)方式进行负载,每个请求按时间顺序逐一分配到不同的后端服务器(比如第一个请求进来就交给第一个服务器处理,第二个请求进来就交给第二个服务器处理),如果后端服务器down掉,能自动剔除。虽然这种方式简便、成本低廉。但缺点是:可靠性低和负载分配不均衡(比如明明一台服务器性能很强他处理的请求跟低配的服务器一样,那肯定是资源的浪费,要让”年轻力壮”的比”老弱病残”的处理更多的请求)。适用于图片服务器集群和纯静态页面服务器集群。所以除此之外,upstream还有其它的负载策略,分别如下:
3.2.3 weight(权重)
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。如下所示,192.168.1.2:8082的访问比率要比192.168.1.1:8081的访问比率高一倍。1
2
3
4upstream mytest{
server 192.168.1.1:8081 weight=5;
server 192.168.1.2:8082 weight=10;
}
3.2.4 ip_hash(按访问IP进行哈希计算)
每个请求按访问IP的hash结果分配,这样每个访客固定访问一个后端服务器,同时也解决了session的问题。1
2
3
4
5upstream mytest{
ip_hash;
server 192.168.1.1:8081;
server 192.168.1.2:8082;
}
3.2.5 fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。与weight分配策略类似。1
2
3
4
5upstream mytest{
server 192.168.1.1:8081;
server 192.168.1.2:8082;
fair;
}
3.2.6 url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。注意:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法。1
2
3
4
5
6upstream mytest{
server 192.168.1.1:8081;
server 192.168.1.2:8082;
hash $request_uri;
hash_method crc32;
}
上面是常用的几种负载均衡策略及配置,其实upstream还可以为每个服务器设置状态值,这些状态值的含义分别如下:
- down :落下(宕机),表示当前的server暂时不参与负载。
- weight :权重,默认为1。weight越大,负载的权重就越大。
- max_fails :最大失败次数,允许请求失败的次数默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误.
- fail_timeout :失败超时时间,max_fails次失败后,暂停的时间。
- backup:备份,其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
1
2
3
4
5
6
7upstream mytest{ #定义负载均衡设备的Ip及设备状态
ip_hash;
server 192.168.1.1:9090 down;
server 192.168.1.1:8080 weight=2;
server 192.168.1.1:6060;
server 192.168.1.1:7070 backup;
}
以上简单介绍了nginx的应用,基本可以满足平时的开发需要,以后如果有哪些补充再进行追加。