Nginx正向代理和反向代理
大家对Nginx反向代理并不陌生,但是很少有人用过Nginx的正向代理。先来通过一组图了解什么是正向代理和反向代理。
本质上无论是正向代理还是反向代理,Nginx都处于客户端和服务端的中间,它充当着一个中间代理的角色。正向代理服务器,你可以认为是客户端一方的资源,客户端知道这个代理的存在,而反向代理服务器,你可以认为是服务端一方的资源,客户端不知道这个代理是否存在。
正向代理使用场景不算多,在这里我列举一个:如果在机房中,只有一台机器可以联网,其他机器只有内网,内网的机器想用使用yum安装软件包,在能联网的机器上配置一个正向代理即可。
配置正向代理时,因为要访问的域名不固定,所以需要使用Nginx的默认虚拟主机,即任何域名访问正向代理服务器都会到这个虚拟主机,配置内容如下:
server {
listen 80 default_server;
resolver 119.29.29.29;
location /
{
proxy_pass http://$host$request_uri;
}
}
说明:
1)resolver
语法:resolver address;
address为DNS服务器的地址,国内通用的DNS 119.29.29.29为dnspod公司提供。 国际通用DNS 8.8.8.8或者8.8.4.4为google提供。 其他可以参考 http://dns.lisect.com/
2)proxy_pass 该指令用来设置要代理的目标url,正向代理服务器设置就保持该固定值即可。
反向代理使用场景非常多,比如域名没有备案,可以把域名解析到香港一台云主机上,在香港云主机做个代理,而网站数据是在大陆的服务器上。反向代理的配置要比正向代理复杂了很多,配置如下所示:
server
{
listen 80;
server_name www.yuntaoshu.com;
location /
{
proxy_pass http://47.10.222.16/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
配置说明: 1)proxy_pass 格式很简单: proxy_pass URL; 其中URL包含:传输协议(http://, https:// 等)、主机名(域名或者IP:PORT)、uri。
示例如下:
proxy_pass http://www.yuntaoshu.com/;
proxy_pass http://47.10.222.16:8080/uri;
proxy_pass unix:/tmp/www.sock;
对于proxy_pass的配置有几种情况需要注意。
示例1:
location /test/
{
proxy_pass http://47.10.222.16;
...
}
示例2:
location /test/
{
proxy_pass http://47.10.222.16/;
...
}
示例3:
location /test/
{
proxy_pass http://47.10.222.16/linux/;
...
}
示例4:
location /test/
{
proxy_pass http://47.10.222.16/linux;
...
}
假设server_name为www.yuntaoshu.com 当请求http://www.yuntaoshu.com/test/a.html 的时候,以上示例1-4分别访问的结果是
示例1:http://47.10.222.16/test/a.html
示例2:http://47.10.222.16/a.html
示例3:http://47.10.222.16/linux/a.html
示例4:http://47.10.222.16/linuxa.html
结论:
a)location后面跟的目录名可以和proxy_pass指向的url跟的目录不一样;
b)proxy_pass指向的url跟的目录最后面带/和不带/结果不同;
c)建议proxy_pass指向的url带目录时要带上/,不带目录时(只有一个IP地址或IP地址:端口)不要带/。
2)proxy_set_header
proxy_set_header用来设定被代理服务器接收到的header信息。语法:proxy_set_header field value,其中field为要更改的项目,也可以理解为变量的名字,比如host,value为变量的值。
如果不设置proxy_set_header,则默认host的值为proxy_pass后面跟的那个域名或者IP(一般写IP), 比如示例3,请求到后端的服务器上时,完整请求uri为:http://192.168.1.10/linux/a.html
如果设置proxy_set_header,如 proxy_set_header host $host; 比如示例3,请求到后端的服务器上时,完整uri为:http://www.yuntaoshu.com/linux/a.html
proxy_set_header X-Real-IP proxy_add_x_forwarded_for; 用来设置被代理端接收到的远程客户端IP,如果不设置,则header信息中并不会透传远程真实客户端的IP地址。
Nginx负载均衡
Nginx的负载均衡本质上也是Nginx的反向代理,只不过代理的后端服务器为多台。先来看一个最简单的配置:
upstream www {
server 172.37.150.109:80;
server 172.37.150.100:80;
server 172.37.150.111:80;
}
server {
listen 80;
server_name www.yuntaoshu.com;
location / {
proxy_pass http://www;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
说明:当被代理的机器有多台时,需要使用upstream来定义一个服务器组,其中www名字可以自定义,在后面的proxy_pass那里引用。这样nginx会将请求均衡地轮询发送给www组内的三台服务器。
大多时候,我们并不想把请求非常均匀的分发到后端的服务器上,而是想对某一台分发的多一些,某一台少一些,这个需求可以通过给后端服务器设置权重来实现,配置如下:
upstream www {
server 172.37.150.109:80 weight=50;
server 172.37.150.100:80 weight=100;
server 172.37.150.111:80 weight=50;
ip_hash;
}
server {
listen 80;
server_name www.yuntaoshucom;
location / {
proxy_pass http://www;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
说明:可以给www组内的三台机器配置权重,权重越高,则分配到的请求越多。ip_hash为nginx负载均衡算法,原理很简单,它根据请求所属的客户端IP计算得到一个数值,然后把请求发往该数值对应的后端服务器上,也就是说同样的客户端会请求同一个服务端。所以,ip_hash能够达到保持会话的效果。
nginx调度算法
调度算法 概述
轮询 按顺序逐一分配到不同的后端服务器(默认)
weight 加权轮询, weight值越大,分配到的访问几率越高
ip_hash 每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器
url_hash 按照访问URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn 最少链接数, 那个服务器连接数少就分发给那个服务器
upstream还有其它相关配置,如下:
upstream www {
server 172.37.150.109:80 weight=50 max_fails=3 fail_timeout=30s;
server 172.37.150.101:80 weight=100;
server 172.37.150.110:80 down;
server 172.37.150.110:80 backup;
}
说明:down,表示当前的server不参与负载均衡;backup,为预留的机器,当其他的server(非backup)出现故障或者忙的时候,才会请求backup机器;max_fails,允许请求失败的次数,默认为1。当失败次数达到该值,就认为该机器down掉了。
后端Web服务器在前端Nginx负载均衡调度中的状态
状态 概述
down 当前的server暂时不参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
fail_timeout 经过max_fails失败后, 服务暂停时间
max_conns 限制最大的接收连接数
Nginx负载均衡属于应用层(网络OSI七层模型),所以我们可以实现一些比较复杂的需求,比如当请求aa.html时分配后端机器为A机器,请求bb.html时分配后端机器为B机器。配置文件如下所示:
upstream aa.com {
server 192.168.0.121;
server 192.168.0.122;
}
upstream bb.com {
server 192.168.0.123;
server 192.168.0.124;
}
server {
listen 80;
server_name www.yuntaoshu.com;
location ~ aa.php
{
proxy_pass http://aa.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ bb.php
{
proxy_pass http://bb.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /
{
proxy_pass http://bb.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
同样也可以针对请求目录来分发后端机器,配置如下:
upstream aaa.com
{
server 192.168.111.6;
}
upstream bbb.com
{
server 192.168.111.20;
}
server
{
listen 80;
server_name www.yuntaoshu.com;
location /aaa/
{
proxy_pass http://aaa.com/aaa/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /bbb/
{
proxy_pass http://bbb.com/bbb/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /
{
proxy_pass http://bbb.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
也可以通过条件判断来实现访问不同的资源池,例如:不同设备调度到不同的资源池
upstream pc_pools {
server 192.168.111.7:8080;
}
upstream ios_pools {
server 192.168.111.8:8080;
}
upstream ad_pools {
server 192.168.111.9:8080;
}
server {
listen 80;
server_name www.yuntoshu.com;
location / {
proxy_pass http://pc_pools;
include proxy_params;
if ($http_user_agent ~* "Iphone") {
proxy_pass http://ios_pools;
include proxy_params;
}
if ($http_user_agent ~* "Android") {
proxy_pass http://ad_pools;
include proxy_params;
}
if ($http_user_agent ~* "msie") {
return 200 "Biche";
}
if ($http_user_agent ~* "rv") {
return 200 "Biche";
}
}
}
Nginx配置SSL
SSL即https,比http多了一个加密、解密的过程,即数据在传输过程中是加密的,这样可以防止"坏人"半路截取数据包,所以https是一种安全的http。虽然https比较安全,但是使用它的站点目前还是一小部分,这主要是因为https比http耗费时间更久,而且https需要购买合法的CA证书,这对站长或者企业来说也算是一个成本支出。
要配置Nginx的SSL,首先需要获得一对合法的CA证书,目前你可以到http://freessl.org/ 获取免费的CA证书(1年有效期),这个足够你做实验了,甚至可以配置在生产环境中。关于如何申请,我就不再描述,最终,你将会得到两个文件(1个.crt后缀的文件和1个.key后缀的文件)。
Nginx配置文件是这样的:
server
{
listen 443 ssl;
server_name www.yuntaoshu.com;
index index.html index.php;
root /data/wwwroot/yuntaoshu.com;
ssl on;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!DH:!EXPORT:!RC4:+HIGH:+MEDIUM:!eNULL;
ssl_prefer_server_ciphers on;
}
说明:
1)443端口为ssl监听端口。
2)ssl on表示打开ssl支持。
3)ssl_certificate指定crt文件所在路径,如果写相对路径,需要以nginx.conf文件作为参考路径。
4)ssl_certificate_key指定key文件所在路径。
5)ssl_protocols指定SSL协议。
6)ssl_ciphers配置ssl加密算法套件,多个套件之间用:分隔,ALL表示全部套件,!表示不启用该套件,+表示将该套件排到最后面去。
7)ssl_prefer_server_ciphers 如果不指定默认为off,当为on,在使用SSLv3和TLS协议时,服务器加密算法将优于客户端加密算法。