正反向代理、负载均衡、Nginx配置实现

一、正反向代理

1、前提

  我们曾经使用FQ软件,访问google;使用了代理软件时,需要在浏览器选项中配置代理的地址,我们仅仅有代理这个概念,并不清楚代理还有正向和反向之分。

2、正向代理(代替客户端访问服务器)

  正向代理:是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。

  正反向代理、负载均衡、Nginx配置实现

  正向代理中,proxy和client同属于一个LAN,对server透明;

正反向代理、负载均衡、Nginx配置实现

3、反向代理

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

正反向代理、负载均衡、Nginx配置实现

  反向代理中,proxy和server同属于一个LAN,对client透明;

正反向代理、负载均衡、Nginx配置实现

4、区别理解

  正向代理的内部是客户端,代替客户端访问服务器;反向代理的内部是服务器,客户端通过反向代理访问内部服务器;

  正向代理代理的对象是客户端,反向代理代理的对象是服务端;

  正向代理是代理(v)客户端,为客户端收发请求,使真实客户端对服务器不可见;反向代理是代理(v)服务器,为服务器收发请求,使真实服务器对客户端不可见;

  正向代理隐藏真实客户端,反向代理隐藏真实服务端;

5、代理作用

  访问 原本无法访问的服务; FQ访问Google,正向代理服务器

  提高访问速度;目标服务器返回数据会缓存带代理服务器上,下次访问同一站点会优先使用缓存数据;代理服务器途径路由速度快;

  访问授权管理;正向代理服务器根据ip限制客户端访问;

6、Nginx实现

 下文中IP对应的机器名:

   IP 机器名 角色名

  10.0.0.139 [elk] client

  10.0.0.136 [lvs-master] nginx server

  10.0.0.137 [kvm] web server 1

  10.0.0.111 [lvs-backup] web server 2

  https://blog.csdn.net/hiyun9/article/details/51602428

  6.1 正向代理

  Nginx server:(内网地址:10.0.0.136,外网地址:172.16.27.64)

  使用VirtualBox Manager虚拟出双网卡。

 1 [root@lvs-master conf.d]# ifconfig
 2 eth0      Link encap:Ethernet  HWaddr 08:00:27:30:56:99
 3           inet addr:10.0.0.136  Bcast:10.255.255.255  Mask:255.0.0.0
 4           inet6 addr: fe80::a00:27ff:fe30:5699/64 Scope:Link
 5           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 6           RX packets:891978 errors:0 dropped:0 overruns:0 frame:0
 7           TX packets:9509 errors:0 dropped:0 overruns:0 carrier:0
 8           collisions:0 txqueuelen:1000
 9           RX bytes:81841095 (78.0 MiB)  TX bytes:13339058 (12.7 MiB)
10 
11 eth1      Link encap:Ethernet  HWaddr 08:00:27:55:4C:72
12           inet addr:172.16.27.64  Bcast:172.16.27.255  Mask:255.255.255.0
13           inet6 addr: fe80::a00:27ff:fe55:4c72/64 Scope:Link
14           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
15           RX packets:913671 errors:0 dropped:0 overruns:0 frame:0
16           TX packets:22712 errors:0 dropped:0 overruns:0 carrier:0
17           collisions:0 txqueuelen:1000
18           RX bytes:109369858 (104.3 MiB)  TX bytes:1903855 (1.8 MiB)
19 
20 lo        Link encap:Local Loopback
21           inet addr:127.0.0.1  Mask:255.0.0.0
22           inet6 addr: ::1/128 Scope:Host
23           UP LOOPBACK RUNNING  MTU:16436  Metric:1
24           RX packets:36222 errors:0 dropped:0 overruns:0 frame:0
25           TX packets:36222 errors:0 dropped:0 overruns:0 carrier:0
26           collisions:0 txqueuelen:0
27           RX bytes:3899937 (3.7 MiB)  TX bytes:3899937 (3.7 MiB)
 1 [root@lvs-master conf.d]# cat zxproxy.conf
 2 server {
 3     listen       80;   #监听的端口
 4     server_name  10.0.0.136;  #server的内容地址,与client需要网络互通
 5 
 6 
 7     resolver 172.16.5.1;   #DNS,这个是DNS,访问外网
 8     location / {
 9            proxy_pass http://$http_host$request_uri;   #$http_host和$request_uri是nginx系统变量,不需要替换,保持原样
10                 }

  Nginx client:只有一个内网网卡,通过访问Nginx server去访问internet,其实FQ、肉鸡、之类的俗称就是这个原理。

 1 [root@kvm ~]# ifconfig
 2 eth0      Link encap:Ethernet  HWaddr 08:00:27:72:8C:3B
 3           inet addr:10.0.0.137  Bcast:10.255.255.255  Mask:255.0.0.0
 4           inet6 addr: fe80::a00:27ff:fe72:8c3b/64 Scope:Link
 5           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 6           RX packets:1462448 errors:0 dropped:0 overruns:0 frame:0
 7           TX packets:21130 errors:0 dropped:0 overruns:0 carrier:0
 8           collisions:0 txqueuelen:1000
 9           RX bytes:145119904 (138.3 MiB)  TX bytes:2814635 (2.6 MiB)
10 
11 lo        Link encap:Local Loopback
12           inet addr:127.0.0.1  Mask:255.0.0.0
13           inet6 addr: ::1/128 Scope:Host
14           UP LOOPBACK RUNNING  MTU:16436  Metric:1
15           RX packets:60800 errors:0 dropped:0 overruns:0 frame:0
16           TX packets:60800 errors:0 dropped:0 overruns:0 carrier:0
17           collisions:0 txqueuelen:0
18           RX bytes:4831102 (4.6 MiB)  TX bytes:4831102 (4.6 MiB)
19 
20 [root@kvm ~]# wget www.baidu.com
21 --2016-06-08 13:02:08--  http://www.baidu.com/
22 正在解析主机 www.baidu.com... 失败:域名解析暂时失败。     #无法访问百度
23 wget: 无法解析主机地址 “www.baidu.com”
24 
25 [root@kvm ~]# export http_proxy=http://10.0.0.136:80 #设定环境变量,指定代理服务器的ip及端口
26 
27 [root@kvm ~]# wget www.baidu.com      #可以成功访问百度了
28 --2016-06-08 13:08:15--  http://www.baidu.com/
29 正在连接 10.0.0.136:80... 已连接。
30 已发出 Proxy 请求,正在等待回应... 200 OK
31 长度:未指定 [text/html]
32 正在保存至: “index.html.1”
33 
34     [ <=>                                                  ] 99,762      --.-K/s   in 0.07s
35 
36 2016-06-08 13:08:16 (1.36 MB/s) - “index.html.1” 已保存 [99762]

  6.2 反向代理

1 [root@lvs-master conf.d]# ls         #nginx目录下的配置文件
2 zxproxy.conf
3 [root@lvs-master conf.d]# cp zxproxy.conf fxproxy.conf  #复制一份,之前是正向代理,现在是反向代理
4 [root@lvs-master conf.d]# mv zxproxy.conf zxproxy.conf.bak
 1 [root@lvs-master conf.d]# cat fxproxy.conf 
 2 server {
 3     listen       80;
 4     server_name  10.0.0.136; #根据环境介绍,nginx server ip
 5 
 6     location / {
 7            proxy_pass http://10.0.0.137; #被代理的服务器ip
 8                 }
 9 
10 #proxy_pass: proxy_pass URL
11 #默认值:NO
12 #使用字段:location,location中的if字段
13 #这个参数设置被代理服务器的地址和被映射的URL,地址可以使主机名、域名、IP加端口的模式,如:
14 #proxy_pass    http://192.168.1.6:8099/linuxtone/;
15 
16 [root@lvs-master conf.d]# service nginx restart #重启加载配置
 1 #先登录到实验环境中的clinet机上,ip如下:
 2 [root@elk ~]# ifconfig                         
 3 eth0      Link encap:Ethernet  HWaddr 08:00:27:3D:40:40
 4           inet addr:10.0.0.139  Bcast:10.255.255.255  Mask:255.0.0.0
 5           inet6 addr: fe80::a00:27ff:fe3d:4040/64 Scope:Link
 6           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 7           RX packets:2618345 errors:0 dropped:0 overruns:0 frame:0
 8           TX packets:247926 errors:0 dropped:0 overruns:0 carrier:0
 9           collisions:0 txqueuelen:1000
10           RX bytes:336182790 (320.6 MiB)  TX bytes:35145157 (33.5 MiB)
11 
12 lo        Link encap:Local Loopback
13           inet addr:127.0.0.1  Mask:255.0.0.0
14           inet6 addr: ::1/128 Scope:Host
15           UP LOOPBACK RUNNING  MTU:16436  Metric:1
16           RX packets:177352 errors:0 dropped:0 overruns:0 frame:0
17           TX packets:177352 errors:0 dropped:0 overruns:0 carrier:0
18           collisions:0 txqueuelen:0
19           RX bytes:26547640 (25.3 MiB)  TX bytes:26547640 (25.3 MiB)
20 
21 [root@elk ~]# curl 10.0.0.136    #访问反向代理服务器
22 <html>
23 10.0.0.137                 
24 </html>
25 #我们看到访问代理服务器,结果被转发到了web server1上。
26 
27 #接下来我们分别看下nginx-server和web-server1的日志:
28 nginx-server:
29 [root@lvs-master ~]# tail /var/log/nginx/access.log
30 10.0.0.139- - [08/Jun/2016:15:35:43 +0800] "GET / HTTP/1.1" 200 26 "-" "curl/7.19.7 
31 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-"
32 
33 web-server:
34 [root@kvm httpd]# tail /var/log/httpd/access_log
35 10.0.0.136 - - [08/Jun/2016:15:21:12 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7 
36 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
37 
38 ##我们看到nginx-server上的nginx的日志,显示访问的用户是10.0.0.139也就是我们环境的clinet,
39 #而web-server上显示的ip是10.0.0.136,也就是nginx-server。
40 #说白了反向代理,对客户来说nginx-server就是真正的服务器,实际上,当用户访问nginx-server的时候,会将请求转发到
41 #web-server1上,然后web-server1将请求的结果发给nginx-server,然后由ngin小-server将请求的结果转交给用户。
42 
43 #在web-server上看到的都是代理的ip,能不能也看到真实用户的ip呢?
44 
45 [root@lvs-master conf.d]# cat fxproxy.conf                
46 server {
47     listen       80;
48     server_name  10.0.0.136;                            #根据环境介绍,nginx server ip
49 
50     location / {
51            proxy_pass http://10.0.0.137;                #被代理的服务器ip
52            proxy_set_header  X-Real-IP  $remote_addr;    #多了这行
53                  }
 1 [root@lvs-master conf.d]# service nginx restart
 2 [root@kvm ~]# tail /var/log/httpd/access_log
 3 10.0.0.136 - - [08/Jun/2016:16:10:53 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7
 4 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
 5 
 6 #改了之后还是显示的是代理服务器的ip,我们去web-server上修改下配置
 7 [root@kvm ~]# vim /etc/httpd/conf/httpd.conf
 8 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
 9 LogFormat "%h %l %u %t \"%r\" %>s %b" common
10 LogFormat "%{Referer}i -> %U" referer
11 LogFormat "%{User-agent}i" agent
12 
13 #修改为:(%h指的的访问的主机,现在改为访问的真实主机ip)
14 LogFormat "%{X-Real-IP}i</span> %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
15 LogFormat "%h %l %u %t \"%r\" %>s %b" common
16 LogFormat "%{Referer}i -> %U" referer
17 LogFormat "%{User-agent}i" agent</span>
18 
19 
20 [root@kvm ~]# service httpd restart
21 停止 httpd:                                               [确定]
22 正在启动 httpd:                                           [确定]
23 
24 [root@kvm ~]# tail /var/log/httpd/access_log
25 10.0.0.136 - - [08/Jun/2016:16:10:53 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7
26 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
27 <span >10.0.0.139</span> - - [08/Jun/2016:16:16:01 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7
28 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
29 #已经变成了真实的访问地址

  代理多个web服务器:

  

 1 [root@lvs-master conf.d]# cat fxproxy.conf
 2 server {
 3     listen       80;
 4     server_name  10.0.0.136;
 5 
 6     location / {
 7            proxy_pass http://10.0.0.137;
 8            proxy_set_header  X-Real-IP  $remote_addr;
 9                 }
10     location /web2 {                            #多加个location
11            proxy_pass http://10.0.0.111;
12            proxy_set_header  X-Real-IP  $remote_addr;    
13                 }
14 
15 [root@lvs-backup ~]# cd /var/www/html/   #进入10.0.0.111这个web-server2
16 [root@lvs-backup html]# mkdir web
17 [root@lvs-backup html]# echo "<html>10.0.0.111</html>" > index.html
18 #我们去client上访问试试:
19 [root@elk ~]# curl 10.0.0.136/web2/
20 <html>
21 10.0.0.111
22 </html>
23 #访问成功

二、负载均衡

1、概念

  负载均衡(Load Balance),意思就是分摊到多个操作单元上进行执行;

  通过一定的调度算法将流量分发到不同的应用服务器上面,同时对应用服务器做周期性的健康检查,从应用服务器集群中动态的剔除故障节点,保证应用的高可用。

2、分类

  负载均衡又分为四层负载均衡和七层负载均衡

  四层负载均衡,主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器;

  七层负载均衡,也称为“内容交换”,主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器;

  七层负载均衡,可以对客户端的请求和服务器的响应进行任意意义上的修改,极大的提升了应用系统在网络层的灵活性;

  七层负载均衡,更具有安全性,SYN攻击在负载均衡设备上就截止,不会影响后台服务器的正常运营;

  正反向代理、负载均衡、Nginx配置实现

3、负载均衡算法

  轮询及加权轮询

  • 轮询(Round Robbin)当服务器群中各服务器的处理能力相同时,且每笔业务处理量差异不大时,最适合使用这种算法。 轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
  • 加权轮询(Weighted Round Robbin)为轮询中的每台服务器附加一定权重的算法,权值越大概率越高。比如服务器1权重1,服务器2权重2,服务器3权重3,则顺序为1-2-2-3-3-3-1-2-2-3-3-3- ......

  IP地址散列

  • 通过管理发送方IP和目的地IP地址的散列,将来自同一发送方的分组(或发送至同一目的地的分组)统一转发到相同服务器的算法。当客户端有一系列业务需要处理而必须和一个服务器反复通信时,该算法能够以流(会话)为单位,保证来自相同客户端的通信能够一直在同一服务器中进行处理。

  最小连接及加权最小连接

  • 最少连接(Least Connections)在多个服务器中,与处理连接数(会话数)最少的服务器进行通信的算法。即使在每台服务器处理能力各不相同,每笔业务处理量也不相同的情况下,也能够在一定程度上降低服务器的负载。
  • 加权最少连接(Weighted Least Connection)为最少连接算法中的每台服务器附加权重的算法,该算法事先为每台服务器分配处理连接的数量,并将客户端请求转至连接数最少的服务器上。

  URL散列

  • 通过管理客户端请求URL信息的散列,将发送至相同URL的请求转发至同一服务器的算法。

4、负载均衡实现

  默认情况

 1 [root@lvs-master conf.d]# cat ../nginx.conf
 2 http {
 3     include       /etc/nginx/mime.types;
 4     default_type  application/octet-stream;
 5 
 6     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
 7                       '$status $body_bytes_sent "$http_referer" '
 8                       '"$http_user_agent" "$http_x_forwarded_for"';
 9 
10     access_log  /var/log/nginx/access.log  main;
11 
12     sendfile        on;
13     #tcp_nopush     on;
14 
15     keepalive_timeout  65;
16 
17     #gzip  on;
18 upstream 1.2.3.4 {
19     server 10.0.0.111:80;
20     server 10.0.0.137:80;
21     }
22     include /etc/nginx/conf.d/*.conf;
23 }
24 
25 [root@lvs-master conf.d]# cat slb.confserver 
26 { 
27 location / { 
28      proxy_pass http://1.2.3.4; proxy_set_header X-Real-IP $remote_addr; 
29            }
30 #注,upstream是定义在server{ }之外的,不能定义在server{ }内部。定义好upstream之后,用proxy_pass引用一下即可。
 1 #结果
 2 [root@elk ~]# curl 10.0.0.136
 3 <html>
 4 10.0.0.111
 5 </html>
 6 [root@elk ~]# curl 10.0.0.136
 7 <html>
 8 10.0.0.137
 9 </html>
10 [root@elk ~]# curl 10.0.0.136
11 <html>
12 10.0.0.111
13 </html>
14 #结果是server1,2交替出现,说明默认是轮询方式的负载均衡。

设置超时时间次数等

 1 [root@lvs-master conf.d]# cat ../nginx.conf
 2 http {   
 3     include       /etc/nginx/mime.types;
 4     default_type  application/octet-stream;
 5 
 6     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
 7                       '$status $body_bytes_sent "$http_referer" '
 8                       '"$http_user_agent" "$http_x_forwarded_for"';
 9 
10     access_log  /var/log/nginx/access.log  main;
11 
12     sendfile        on;
13     #tcp_nopush     on;
14 
15     keepalive_timeout  65;
16 
17     #gzip  on;
18     upstream 1.2.3.4 {
19     server 10.0.0.111:80 weight=1 max_fails=2 fail_timeout=2;
20     server 10.0.0.137:80 weight=1 max_fails=2 fail_timeout=2;
21     }
22     include /etc/nginx/conf.d/*.conf;
23     }
24 [root@lvs-master conf.d]# service nginx restart
 1 #结果
 2 [root@kvm httpd]# service httpd stop  #关闭web-server1服务
 3 [root@elk ~]# curl 10.0.0.136
 4 <html>
 5 10.0.0.111
 6 </html>
 7 [root@elk ~]# curl 10.0.0.136
 8 <html>
 9 10.0.0.111
10 </html>
11 #现在只能访问web-server2了。
12 
13 [root@kvm httpd]# service httpd start   #打开web-server1服务
14 [root@elk ~]# curl 10.0.0.136           
15 <html>
16 10.0.0.111
17 </html>
18 [root@elk ~]# curl 10.0.0.136
19 <html>
20 10.0.0.137
21 </html>
22 [root@elk ~]# curl 10.0.0.136
23 <html>
24 10.0.0.111
25 </html>

ip_hash的负载均衡

 1 [root@lvs-master conf.d]# cat ../nginx.conf
 2 upstream 1.2.3.4 {
 3     ip_hash;
 4     server 10.0.0.111:80 weight=1 max_fails=2 fail_timeout=2;
 5     server 10.0.0.137:80 weight=1 max_fails=2 fail_timeout=2;
 6     }
 7 [root@lvs-master conf.d]# service nginx restart
 8 停止 nginx:                                               [确定]
 9 正在启动 nginx:                                           [确定]
10 
11 [root@elk ~]# curl 10.0.0.136
12 <html>
13 10.0.0.137
14 </html>
15 [root@elk ~]# curl 10.0.0.136
16 <html>
17 10.0.0.137
18 </html>
19 #配置这种负载均衡后,>每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,
20 #有效解决了动态网页存在的session共享问题。(一般电子商务网站用的比较多)