概念
什么是反向代理其与正向代理有什么区别?
正向代理是指客户端与目标服务器之间增加一个代理服务器,客户端直接访问代理服务器,在由代理服务器访问目标服务器并返回客户端并返回。这个过程当中客户端需要知道代理服务器地址,并配置连接。
如图:
反向代理是指客户端访问目标服务器,在目标服务内部有一个统一接入网关将请求转发至后端真正处理的服务器并返回结果。这个过程当中客户端不需要知道代理服务器地址,代理对客户端而言是透明的。如图:
正向代理与反向代理的区别:
Nginx的反向代理
Nginx正向代理只需要配置 location 中配置proxy_pass 属性即可。其指向代理的服务器地址。正如我们上一篇文章配置的百度的代理:
这是一个经典的正向代理的例子。
下面配置一个反向代理的例子,首先启动两个应用,端口分别是8010和8020,访问/hello:
然后我们在nginx中,首先反向代理一个地址:
可以看到,监听80端口,代理的是8010的端口地址,路径是/hello。然后在配置一下本地host:
然后访问可以看到反向代理成功:
可以看到正向代理和反向代理在配置上区别不大,主要区别是被代理的服务的位置,一个是远程(百度),一个是局域网内部(本机8010)。
来看代理相关参数:
- proxy_pass # 代理服务
- proxy_redirect off; # 是否允许重定向
- proxy_set_header Host $host; # 传 header 参数至后端服务
- proxy_set_header X-Forwarded-For $remote_addr; # 设置request header 即客户端IP 地址
- proxy_connect_timeout 90; # 连接代理服务超时时间
- proxy_send_timeout 90; # 请求发送最大时间
- proxy_read_timeout 90; # 读取最大时间
- proxy_buffer_size 4k;
- proxy_buffers 4 32k;
- proxy_busy_buffers_size 64k;
- proxy_temp_file_write_size 64k;
反向代理还有一个用途就是在多个站点配置多个二级域名,比如百度的搜索引擎是 www.baidu.com,百度图片是 image.baidu.com,百度翻译是 fanyi.baidu.com,可以看到,一级域名一样,二级域名不同,代表了不同的系统。这种方式利用nginx的反向代理也可以实现,
可以看到,两个不同的二级域名分别访问两个不同的端口地址,访问效果如下:
这样可以做到在一个服务器上部署多个项目,分别使用有意义的二级域名。
负载均衡
通过proxy_pass 可以把请求代理至后端服务,但是为了实现更高的负载及性能, 我们的后端服务通常是多个, 这个是时候可以通过upstream 模块实现负载均衡。下面来配置一个upstream:
可以看到把两个服务地址都定义到了一个upstream中,并起名为wwwdemocom,下面设置反向代理:
反向代理的配置中,只配置upstream的名字即可,刷新页面,可以看到同一个地址,不停的分别访问两个项目:
这样如果我们部署多个相同的系统,可以把所有的并发流量分到多个上面,从而达到提高并发的目的。
这时候两个系统切换着访问,策略默认是轮训的,也就是无论几个系统都轮着循环访问。如果想让两台机器的访问数量按照1比2分配,那么可以设置权重:
刷新页面可以看到,8010访问一次,紧接着8020访问两次,这种是按照权重分流,改变了原来默认的轮训策略。这种适合机器性能有区别的情况。
下面看一下upstream 相关参数:
- service反向服务地址加端口
- weight 权重
- max_fails 失败多少次认为主机已挂掉则,踢出
- fail_timeout 踢出后重新探测时间
- backup 备用服务
- max_conns 允许最大连接数
再来看一个使用backup参数演示备份服务的例子,在服务器上再启动一个8030的服务:
将此服务作为一个备份服务,有服务意外停止的时候,这个顶上去!来看nginx配置:
重启nginx,先刷新页面查看效果,发现还是配置的8010和8020两个在做负载均衡,现在停止8010和8020,可以看到8030顶上来了:
注意:关闭一个服务不会触发备用服务,只有8010和8020全都意外停止,8030才会顶上来!
如果再把8010重新启动,那么备份服务就不会起作用了,访问的还是8010:
再来说一下max_fails和fail_timeout两个参数,nginx在原来的8010服务器重新启动以后,能很快检测到原来的8010恢复了,并投入使用,是因为nginx和8010之间有类似心跳检测的机制,实时监控8010是否能用。上面的max_fails参数就是设置失败多少次后,认为已经挂了,就剔除,fail_timeout参数就是剔除后从新检测这个属性也是设置恢复时检测的时长间隔,比如设置一分钟,那么服务恢复后得隔一分钟才能检测到并投入使用。可以想象,如果实时去检查的话,会很消耗性能,所以这两个参数非常有用。下面我们把失败最大重试次数设置成10次,恢复检测时长设置成30秒:
重新加载,然后停止8010和8020,访问页面,可以看到加载了一会才会出现8030的结果,如果重试次数设置成100次,加载时间会更明显。我们把8010启动起来,可以看到前面三十秒左右还是8030,后面又开始访问8010:
这两个参数也是很重要的参数,在实际生成环境中会用到。要合理设置重试次数和等待时间。
max_conns是项目服务允许的最大连接数,这个很好理解。
负载均衡算法
上面介绍了简单的负载均衡,也涉及到了简单的轮训的负载均衡和加权重的负载均衡算法,下面专门介绍一下upstream 负载均衡算法:
- ll+weight: 轮询加权重 (默认) 缺点是,其中一个连接满了,nginx还是会加连接过去导致连接越来越多,速度越来越慢,不够自动化和智能化
- ip_hash : 基于Hash 计算 ,用于保持session 一至性,解决分布式session同步问题,缺点是现在很多小区或者学校都是用的一根光纤,大部分人的ip是一样的,容易导致某个服务连接数量过多,出现负载不均衡的情况,而且机器挂掉,会话随着会丢失
- url_hash: 静态资源缓存,节约存储,加快速度(第三方),和ip_hash的计算方法一样,应用场景不同,通过这种算法可以把一些静态资源平均分布到各个服务中,节省空间
- least_conn :最少链接(第三方),可以优先把请求分给和nginx连接最少的服务,最大化的利用资源
- least_time :最小的3响应时间,计算节点平均响应时间,然后取响应最快的那个,分配更高权重(第三方),可以充分利用性能好的机器
上面演示的都是轮询加权重的,下面看下ip_hash算法:
注意,除了把权重去掉,还有把backup的服务注释掉,两个不能同时用,现在重新加载看一下效果:
效果就是,在一个地方访问,只会出现一个服务的结果,不再访问其它的服务,这是ip_hash算法的效果。使用其它机器访问,也会出现只访问其中一个的效果: