龙空技术网

理解Nginx的反向代理与负载均衡

Java武学秘籍 154

前言:

眼前兄弟们对“apache代理翻墙”大约比较注重,兄弟们都需要分析一些“apache代理翻墙”的相关知识。那么小编在网上搜集了一些对于“apache代理翻墙””的相关内容,希望大家能喜欢,大家一起来学习一下吧!

点击上方☝Java编程技术乐园,轻松关注!及时获取有趣有料的技术文章

文章很长,耐心阅读,记得点赞和关注哦~



Nginx 简介初次发布

Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

性能概览

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,Nginx的并发能力在同类型的网页服务器中表现较好。

与旧版本的Apache不同,Nginx不采用每客户机一线程的设计模型,而是充分使用异步逻辑(这一点与NodeJS采取了相同的做法,支持高并发,Nginx在官方测试的结果中,能够支持五万个平行连接,而在实际的运作中,是可以支持二万至四万个平行链接),削减了上下文调度开销,所以并发服务能力更强。整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。

Nginx的反向代理理解反向代理

要使用Nginx的反向代理的特性,首先就是要理解什么是反向代理,为此我们先从最简单的C/S架构说起,C/S架构,也即是Client-Server的架构。而最简单的C/S架构,也即是以单个节点作为后端Server的C/S架构。

C/S架构中的单点Server

在普通的开发当中,单点Server的服务方式非常常见,比如使用Django框架做后台服务的时候,就可以通过简单的run server命令运行起一个临时的服务,接着通过地址就可以访问到这个服务了。当然了,对于Django而言,run server命令只是提供开发周期的调试使用的便捷工具,更一般的情况是通过uWSGI把这个Django服务跑起来,以获取并比run server更好的服务性能。
此时部署整一个架构图如下:


对于请求量非常少的服务,这样的部署不会有什么问题,但如果这个服务请求量上来的时候,这样部署的架构就很有问题了。

首先一个很客观的问题就是,如果单从服务器的物理特性来看,这个服务器就不能支持这么高的请求量。这种情况下,就迫使开发者去把服务迁移到一个CPU更强、内存更高,综合性能更好的服务器。通过更换服务器当然可以解决这个问题,在不考虑成本的条件下,总可以找到性能更好的服务器来替换原来的服务器以支撑服务,但这种理想的条件不在本文考虑范围之内。

第二个问题就是,如果服务Server单节点发生了故障,就必然会影响整个服务,因为对于众多的Client客户端都是连接的一个Server服务端,如果这个节点不可用了,势必会影响所有使用了客户端的用户。

为了解决这两个显而易见的问题,就必须提出一种可以横向拓展的部署架构,使得服务可以支撑的请求量可以随着服务的横向拓展而增加。因而就催生了如下的部署架构:

基于代理的可横向拓展的C/S架构

在这个部署的架构当中,除了Server节点,还多出了一个叫“Proxy”的节点,那么这个节点是干嘛的呢?
“Proxy”的这个节点,它把他接收的所有的请求都转发到他后面的Server节点当中,然后等待Server节点处理请求,再从Server节点取回执行结果返回到Client。所以,“Proxy”的这个节点,他实际上不处理任何的请求。
我们先来看这样子的架构怎么解决了以上的问题,再来思考“Proxy”的这个角色。
首先是第一个问题,服务器性能不足的问题,这个架构如何解决性能不足的问题呢?在这个架构里面,假设Server节点S1性能到达瓶颈了,不能处理更多的请求了。如果采用上面的这个架构,那么我们可以添加Server节点S2,同时告诉“Proxy”节点,让他把部分原来转发到S1节点的请求转发到我这里来。这样子通过服务分流减少压力的方法就可以解决原来S1节点性能不足的问题了。

接着是第二个问题,单点服务器挂掉了怎么办。还是考虑Server节点S1和S2,两者所能够提供的服务是一样的,假设某一个时候S1挂掉了,这时如果有“Proxy”节点的存在,并且“Proxy”节点能够察觉到S1挂掉了的话,那么让“Proxy”节点把原来要转发给S1节点的请求转发到S2进行处理就可以了,这样子通过服务冗余的方法就可以解决原来S1突然挂掉影响服务的问题。


解决了这两个问题,接下来我们再从这两个问题里面“Proxy”的角色来理解什么叫做代理。
在第一个问题里面,“Proxy”节点通过服务分流的方法来减少S1的压力,对于原来应该被S1服务的,却由于被“Proxy”节点转发而被S2服务的Client而言,Client他并不知道实际上是由S1处理的还是S2处理的,Client拿到的是一个从“Proxy”节点返回的结果,换言之,Client并不知道自己的请求实际上是被哪个处理的,他只需要往“Proxy”节点发送请求就好了,剩下的工作就由“Proxy”节点去解决。
也就是,“Proxy”节点相当于一个中介,或者说是一个代理,代理Client去寻找实际的Server节点去完成服务。这样子的模式在现实生活也非常常见,在买房子的时候,通常由房产中介帮助你完成和卖者之间的手续,而不需要你亲自去处理这些事情,你只需要协调好自己与中介之间的手续就好了,这里的中介,就和我们的“Proxy”节点所做的工作非常类似。
同样的,在第二个问题里面,也是相似的理解方式,Client并不需要感知S1是否还能正常工作,Client只需要把请求发送给“Proxy”节点,由它去帮忙处理就可以了。
因此,这里面的“Proxy”节点,也就是我们的代理节点。

正向代理与反向代理

理解了什么是“代理”,离我们理解什么是“反向代理”就只差“反向”两个字了,与“反向”相对的,就是“正向”,本质上来讲,代理都是存在于Client和Server之间,但是由于性质不同,所以也分为这两种。在这一个部分,我们将会学习,什么是反向代理,什么是正向代理。
直观的以两个例子去理解什么是正向代理和反向代理。假设由A、B和C三人,他们之间存在借钱的关系。
对于正向代理,理解起来就是:

A需要钱,A知道C由很多钱,想向C借钱但是A和C有矛盾,于是A想到通过B去借C借钱B向C借到钱了,C不知道是A的存在这样B就帮助A借到了Z的钱
在这个过程,B就充当了代理借钱的角色,并且是代替A去借钱的,这样就是正向代理。

接着是反向代理:

A需要钱,C有很多钱,A不知道C很多钱A找B借钱B知道C有很多钱B向C借钱,并把借到的钱给A,而没有使用自己的钱借给AA拿到钱以后,以为钱是B的,A不知道C的存在
在这个过程当中,B也充当了代理借钱的角色,不过这次不是代替A去借的,而是用C的钱借给A的,换言之即是代替C将钱借给了A,这就是反向代理。
在例子里面,把A换成Client,把C换成Server,就是计算机的例子了。两者区别服务对象不同正向代理,代理的是客户端,也就是例子中的A,服务端不知道实际发起请求的客户端反向代理,代理的是服务端,也就是例子中的C,客户端不知道实际提供服务的服务端

正向代理

反向代理

安全模型不同正向代理允许客户端通过它访问任意网站并且隐藏客户端自身,因此必须采取安全措施以确保仅为授权的客户端提供服务反向代理都对外都是透明的,访问者并不知道自己访问的是代理,访问者不知道服务节点的存在,认为处理请求的就是代理节点

总而言之,正向代理是从客户端的角度出发,服务于局域网用户,以访问非特定的服务,其中最典型的例子就是翻墙;反向代理正好与此相反,从服务端的角度出发,服务于所有用户,隐藏实际的服务节点,服务节点的架构对用户透明,以代理节点统一对外服务。

Nginx配置反向代理

(文末附完整nginx.conf配置)
为了演示Server节点, 我们使用Django快速启动一个项目,可以快速验证反向代理的配置是否ok。

django-admin startproject server1

接着我们启动一个内网地址,端口为8080。

python manage.py runserver 127.0.0.1:8080

接着配置Nginx,在Nginx的配置里面,主要是upstream块,和server块。

upstream httpserver{    server 127.0.0.1:8080;}

然后在server块配置转发到upstream。

location / {    proxy_pass ;}

如此,便完成反向代理的配置,接着通过命令nginx -s reload重新加载配置文件即可。若存在多个Server节点,在upstream域添加多个Server的地址即可。
我们另起一个django项目,服务启动在8081端口。
接着更新upstream的配置。

upstream httpserver{    server 127.0.0.1:8080;    server 127.0.0.1:8081;}

就可以完成两个节点的反向代理。

Nginx代理中的负载均衡

提到Nginx的反向代理,不得不提的就是Nginx的负载均衡,Nginx支持丰富的负载均衡算法,以提高使用Nginx部署的服务的综合性能。
在介绍负载均衡之前,我们先来看为什么需要负载均衡。

为什么需要负载均衡

需要负载均衡的一个最简单的诉求就是由Proxy代理的多个Server节点的性能并不完全相等的,也即是不同Server节点,他们处理请求的速度和容量都不相同,这就要求Proxy在转发的时候,能够因Server而异,给不同Server转发适合其处理性能的请求量,以防Server节点低负载浪费资源,或者过高负载引起宕机。
其次就是如果没有负载均衡算法,我们就无法避免很多请求被调度到一个Server节点从而把这个Server节点压垮的情况发生,因为我们没有一种机制保证不同Server节点所处理的请求量数均匀的或者是合理的。

负载均衡的算法

对服务器性能的考究有很多变量需要去关注:包括CPU的核数和频率、内存的容量速度、网络的质量、内核最大文件描述符、服务器的其他服务影响等等,因此在负载均衡算法上,也是非常丰富的,以下是几种常见的负载均衡算法。

随机算法

随机,顾名思义,就是随机概率的调度,每一个请求通过随机算法调度到不同的服务器,若调用量越大,不同服务器处理的请求数就越平均。
这种算法看是公平的,但是没有考虑到不同节点性能的差异,同时对随机算法也有一定的要求,要求随机算法在大量的随机事件后能够得到一个均匀的随机结果。

轮询算法

轮询算法也非常容易理解,请求到来的时候,按顺序把每个请求转发到多个Server节点当中,保证每个服务节点所处理的请求量都是均匀的。
虽然这种算法很公平,但是没有考虑到不同节点性能的差异。

最少连接算法

在多个服务器当中,优先将请求调度到处理连接数少的服务器上,即使每台服务器的处理能力各不相同,也能够在一定程度上降低服务器的负载。
这种算法能够考虑不同节点性能之间的差异,处理连接数在一定程度上能够反映其性能的差异,不过并非绝对,在一些条件下,其他原因也可限制处理连接数,比如网络性能、带宽压力等等。

权重轮询算法

这种算法要求在转发节点配置Server的时候,添加Server节点的权重信息,以表示不同Server节点的处理性能,在转发节点转发请求的时候,将按照权重的大小来分配转发的流量。
这种算法可以合理的转发请求,开发人员可以按照Server节点的性能参数、部署的服务来修改Server节点的权重,使得每一个Server节点都能够得到最合理的使用。
当然,除了开发人员手动配置权重以外,更为智能的一种方式是由代理的Server节点主动上报自己的能力,转发节点在接收到相关信息的时候再权衡不同Server节点的能力,按照权重进行转发。这样就不用人工介入,提高效率。不过这种方式对转发节点和Server节点都有一定的要求,需要开发者去开发相关的逻辑。

使用Nginx配置负载均衡

理解不同的负载均衡算法以后,接下来就是对Nginx配置负载均衡了。Nginx支持普通轮询算法和权重轮询算法的负载均衡配置。

轮询算法的负载均衡

其实基于普通轮询算法的负载均衡,在前面我们已经实现了,只不过当时重点不在负载均衡,所以没有提及。

upstream httpserver{    server 127.0.0.1:8080;     server 127.0.0.1:8081;}

这就是轮询算法的负载均衡的配置,在upstream配置块的多个server节点默认都有权重weight=1,也即是每个服务节点权重一样了。

权重轮询算法的负载均衡

在普通轮询算法的基础上,我们可以进行权重轮询算法的配置,配置如下:

upstream httpserver{    server 127.0.0.1:8080 weight=5;   # 权重为5    server 127.0.0.1:8081 weight=2;   # 权重为2    server 127.0.0.1:8082; # 默认权重为1}

如此添加weight关键字即可,接着你就可以在日志中看到,请求大致会以5:2:1的比例落到三个server中,这就是权重轮询算法的负载均衡。

总结

Nginx是一个高性能的部署服务端。支持HTTP部署、代理和反向代理、负载均衡、邮件服务等丰富的功能,是非常出色的一款软件,本文介绍了反向代理和负载均衡的概念,并介绍了使用Nginx配置反向代理和负载均衡的过程,希望看完这篇文章,大家对Nginx和相关概念有进一步的理解。
最后打个小广告,实战课程《Django 2.0+微信小程序打造个人助手》,除了使用Django和微信小程序这两款热门技术去开发个人助手以外,针对Django的服务高可用部署等知识点也有详细的介绍,感兴趣的同学可以参加学习,我们一起来探讨哦。

附:最简单Nginx的完整配置

user www-data;worker_processes auto;pid /run/nginx.pid;events {        worker_connections 768;}http {        ##        # Basic Settings        ##        sendfile on;        tcp_nopush on;        tcp_nodelay on;        keepalive_timeout 65;        types_hash_max_size 2048;        include /etc/nginx/mime.types;        default_type application/octet-stream;        ##        # SSL Settings        ##        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE        ssl_prefer_server_ciphers on;        ##        # Logging Settings        ##        access_log /var/log/nginx/access.log;        error_log /var/log/nginx/error.log;        ##        # Gzip Settings        ##        gzip on;        gzip_disable "msie6";        include /etc/nginx/conf.d/*.conf;        include /etc/nginx/sites-enabled/*;        upstream httpserver {                server 127.0.0.1:8080 weight=5;                server 127.0.0.1:8081 weight=2;        }        server {                listen 80;                server_name .dongcia.com;                charset utf-8;                location / {                       proxy_pass ;                }        }}


作者:咚咚呛
链接:
来源:慕课网

标签: #apache代理翻墙