http://blog.jobbole.com/84669/
关于大型网站技术演进的思考(十八):网站静态化处理—反向代理(10)
反向代理也是一种可以帮助实现网站静态化的重要技术,今天我就来讲讲反向代理这个主题。那么首先我们要了解下什么是反向代理。和反向代理相对应的是正向代理,正向代理也就是我们常说的代理服务,正向代理是非常常见的,例如在某些公司里我们想使用互联网,那么我们就得在浏览器里设置一个代理服务器,通过代理服务器我们才能正常使用互联网,而这个代理服务器就是一个正向代理服务器。正向代理更加让人熟悉的使用场景估计还是在FQ技术里的使用,我们使用一个放置在国外的代理服务器来访问那些在国内无法正常访问的网站,这其实也是在使用一个正向代理服务。
其实不管是正向代理还是反向代理,这两个概念的定义都是以浏览器侧为基准进行的,正向代理是代理浏览器来访问互联网,反向代理是指代理不再是代理浏览器侧了,而是反过来代理浏览器需要访问的应用服务器。那为什么我们要使用正向代理服务器了?答案当然不是为了FQ了,下面我来列举些实例来说明这个问题了。
例如公司里使用代理服务器主要是为了安全的考虑,很多公司内部都有自己的局域网,一般我们称之为内网,内网里有公司的各种资源,如果公司员工的电脑随意连接到互联网,假如碰到那些别有用心的黑客,通过攻击员工的工作电脑截取了公司重要的文件资料,那样就会造成公司的重大损失,正向代理除了能防范外部的黑客攻击外还能监控和控制公司内部员工将公司重要文件通过互联网传递给不恰当的人,因此公司让员工使用代理上网基本都是出于安全的角度来考虑的。
正向代理的合理使用还能帮助一些企业提升自己产品的核心竞争力,例如在移动端有一款非常流行的浏览器,它之所以非常受用户的欢迎,是因为使用该浏览器上网速度比其他浏览器明显的快多了,那么这款浏览器是如何做到这点的呢?奥秘就是这家公司为自己的浏览器对应建立一个十分强大的代理服务器集群,用户使用该浏览器访问网站时候用户首先访问的是该公司的代理服务器,而这些代理服务器使用缓存技术缓存了海量的网站信息,再加上使用一些web加速的技术例如CDN技术,这就让该浏览器访问网站的效率明显快于其他浏览器。
反向代理和正向代理从技术角度上基本上是一致的,区别主要是代理的内容不一样了,反向代理代理的是应用服务器。反向代理技术也基本上是互联网公司的一个标配技术,但是反向代理能否正确使用,能否更进一步的发挥它的实用价值,我觉得并不是所有公司都能做好的,下面我来总结一下反向代理的使用目的吧,具体如下:
使用目的一:反向代理可以隐藏真实的应用服务器。该目的属于安全的范畴,反向代理隐藏真实的应用服务器,那么就可以让别有用心的黑客很难掌握正确的应用服务器,从而增加黑客的攻击难度。
使用目的二:反向代理可以实现负载均衡的功能,例如在java的web开发里有一种很简单的实现集群的手段,这个手段就是使用apache加上tomcat的组合,用户请求先到达前置的apache服务器,apache再使用负载均衡策略将请求分配给后台不同的tomcat服务器上。
使用目的三:反向代理可以起到动态调节应用服务器并发数的目的,一般用作反向代理的服务器都是静态资源服务器,这样的服务器在并发处理能力上要远强于后台的web应用服务器,那么可以通过控制web应用服务器前置的反向代理服务器,这样就可以动态调节后台服务的负载的大小,这个做法的好处可能很多朋友都不太了解,这里我列举个例子,一个网站最需要稳定性的部分是哪个部分呢?很多朋友会说是数据库,的确数据库是最重要的,因为数据库做分布式很难,很容易形成单点故障,要是数据库挂了基本一切都没法玩了,那么除了数据库之外还有别的吗?当然有,那就是用于处理业务的应用服务器了,应用服务器如果做了集群,集群中其中一台服务器挂了其影响面会比数据库挂掉低多了,但是一个网站的做业务处理的应用服务器挂掉,对公司的损失还是很大的,而web应用服务器前面的用作反向代理的静态资源服务器挂掉问题就会小多了,至少不会产生公司业务无法正常完成的事情了,因此当网站负载过高,让过载的请求被反向代理拦截或者阻止,这对应用服务器的稳定性提升有莫大的好处。当然反向代理调节应用服务器的负载水平的用途不仅仅这些,有兴趣的朋友可以在网络上找找相关的介绍。
使用目的四:反向代理可以缓存静态数据,一般用作反向代理的服务器都是使用像apache或者是ngnix这样的静态资源服务器,因此我们可以把web应用里的静态资源缓存在反向代理服务器上,从而达到提升请求处理的速度问题。反向代理的这个功能就和本系列的主题网站静态化处理切合了。
分析完反向代理的使用目的后,我们现在将反向代理应用到项目里,这里应用的一个前置限定就是将反向代理应用到网站静态化的处理之上,首先是第一个应用方式,如下图所示:
第一种反向代理应用方式就是让反向代理和应用服务器一一对应,也就是每台应用服务的部署服务器上都对应部署一台反向代理服务器,这么做有怎样的好处呢?首先我们来讲第一个好处,如果我们将网页做了动静分离,那么反向代理服务器就可以负责对请求中的静态资源访问进行处理,同时反向代理还可以承担动静资源整合的目的。这里要特别说明下,前文里我说道动静资源会因为我们使用的动静策略而发生转化,那么有些动态内容在一定条件被转化为静态资源后,我们可以将这些做了转化的静态资源在服务器上缓存起来,这个时候上图展示的架构模型就会发生变化,如下图所示:
我们看到反向代理服务器和应用服务器之间会形成一个cache层,反向代理访问cache层的效率会比直接访问应用服务器要高的多,这等于是给应用服务器做了一个加速操作,同时通过缓存我们可以减少应用服务器的运算压力,从而达到提升应用服务器性能的目的。以前有朋友问我这么做会不会增加应用服务器的压力,因为一台服务器上部署了两台可以处理web请求的服务器,那么它们之间一定会有发生冲突的时候,不过我想产生冲突肯定是我们没有很好的处理二者关系所致,所以我们要理清在同一台服务器上部署反向代理和应用服务器后,它们之间的关系到底是怎样的?
其实反向代理和应用服务器从物理形态角度上它们是两个不同的东西,但是二者在逻辑上其实是一个整体,它们共同完成一个逻辑性的应用服务器的功能,只不过二者因为应用场景不同而形成了一种分工合作的关系,反向代理服务器主要完成对静态资源请求的处理,而应用服务器则是负责业务逻辑的处理,它们最终形成一个强大的合力使得整体的逻辑性应用服务器的性能得到显著的提升。
除此之外,这个反向代理还可以发挥动态调节应用服务器的并发数的目的,但是上面的技术方案却没有发挥反向代理的负载均衡以及安全性这两个方面的作用。为了让反向代理四个使用目的得到充分的发挥,那么我们该如何来做了?
方法很简单就是把反向代理的部署地点从应用服务器所在的物理服务器上迁移出来,放到一台独立的物理服务器上,但是这个做法会有性能上的损失,同时还会增加整个技术架构的复杂性。为什么性能会损失呢?因为原来的反向代理服务器和应用服务器部署在同一个物理服务器上,那么它们之间的通讯都是以内存共享的方式进行的,这样的通讯效率是非常高,现在换成了通过网络通讯进行沟通,而网络通讯是IO设备里效率最差,可靠性最差的,因此单独部署反向代理服务器或多或少都会造成一定性能的损失。
为什么说单独部署反向代理会增加整个网站技术架构的复杂性了?我们把反向代理服务器单独部署,那么单独部署时候我们还会是使用一一对应的策略吗?先不谈这么做,从技术和业务角度的好处和坏处,但从成本这个考虑就是会让很多公司望而却步,因为这个做法就会导致用于部署应用服务器的成本翻倍的增加,而增加的服务器用于反向代理,这样的做法怎么体会都不是觉得物有所值,再说用于反向代理的静态资源服务器本身处理请求的并发能力是普通应用服务器的数百倍,一一对应本身也没有完全发挥反向代理服务器的潜力,因此最好的解决方法就是把反向代理服务器做成一个反向代理服务器集群(zpf:这里你给我解释解释,将反向代理与web服务器分开后,没能充分发挥反向代理的性能,然后解决方法就是部署成反向代理集群?呵呵,一台反向代理性能还能充分发挥,部署成集群,部署成多台反向代理,就能充分发挥性能了?),做成集群问题又来,集群里每台反向代理缓存的数据是不是要保持一个同步了?这就好比处理应用服务器的session同步问题,如果真的这么做会不会导致反向代理服务器上缓存大量使用率不高的数据从而导致缓存的利用率很差,同时同步操作本身也会影响到反向代理集群的性能,所以要设计一个好的反向代理集群是一件十分复杂的事情,其实合理的反向代理集群的做法就是在集群里在进行分组,每个分组应该是和后端的SOA服务相匹配,这个时候反向代理集群的效率才能得到最大的发挥,同时资源利用率也会更加的合理。其实使用反向代理集群方式,也会给生产部署造成麻烦,如果网站进行了静态化处理,那么反向代理需要承担对静态资源的处理操作,这个时候反向代理和对应的应用服务器结合起来才能形成一个完整的应用服务器,但是现在我们将一个完整的逻辑应用服务器分开部署了,那么当我们发布新应用的时候就得面临更加复杂的情况,这就增加了部署和运维的风险和难度。
我如此批评单独部署反向代理的问题,但是我并不是说这种做法完全不可取(zpf:我有问题:你批评单独部署反向代理,但是你记得你怎么提到单独部署反向代理的吗,你说之前方案没有发挥反向代理的负载均衡以及安全性这两个方面的作用。为了让反向代理四个使用目的得到充分的发挥,才单独部署,然后单独部署会有性能和技术的问题,那我要问题,你批评,就是说你不建立单独部署,那负载均衡与安全性怎么解决?),而是想告诉大家这种做法其实是一种高级的做法,但是也是一个复杂的做法,要做好这个集群是很麻烦的一件事情的,我觉得只有当我们的网站业务量和请求量很大的时候,同时原有方案出现了瓶颈时候可以认真考虑反向代理集群方案的实现,不过将反向代理形成集群会给网站的安全性带来莫大的好处,反向代理可以隐藏后台的应用服务器,这种隐藏就是客户端只需要访问代理服务器即可,应用服务器对外都是以反向代理来展示的,但是如果反向代理和应用服务器一一对应,那么恶意黑客找准了某台反向代理服务器后,对这个反向代理服务器进行反复的攻击,那么这个攻击也就等于攻击与之对应的应用服务器,这就导致反向代理隐藏真实应用服务器的作用就没有得到有效的发挥,而集群这块就可以很好的处理这个问题,不过我们如果觉得使用集群代价太高,我们也有变通的方法,那就是在所有逻辑应用服务器前面再放置一个反向代理服务器,这个反向代理服务器不再承担缓存的功能,而只是用来做负载均衡和安全处理,这样一一对应的策略安全性也可以得到保证,不过如果公司技术能力好可以考虑使用LVS这种软件化的负载均衡技术方案,假如公司还很有钱还可以考虑使用更加高级的硬件负载均衡设备例如F5设备。
如果我们网站除了使用网站静态化技术还使用了前后端分离技术,当然这个前后端分离技术应该是使用nodejs的前后端分离技术,那么nodejs应该放置在生产部署的什么位置上了?上篇文章里我曾列举了一个nodejs的应用实践场景,在这个实践场景里我曾经提到如果在原有的网站生产架构下引入nodejs会增加一个请求处理环节,而nodejs使用主要是为了满足前后端分离而非增加网站性能,因此增加的环节可能会让请求处理的性能下降,因此我最后提出一种变通手法,就是nodejs项目发布时候编译源代码,然后将编译出的javascript和html文件干脆推移到浏览器端处理,这样就变相形成了前端MVC框架,这个做法总是有点不伦不类的意味,假如我们真的想把nodejs引入到应用生产的网络架构里,我们不希望无端的增加请求处理环节,那么最好是让nodejs服务器替换某个部分。按照这个思路思考,那么我觉得nodejs在生产的引入最好是和反向代理相关,最简单的方式就是让nodejs和反向代理一一对应,这样就可以很好的降低引入nodejs带来的问题,当然复杂点的就是反向代理集群对应的应用服务器应该是nodejs的应用服务器,而不是用来做业务处理的业务级别的应用服务器。
不管怎么说,我认为在网站静态化方案里我们一定要考虑反向代理的运用,如果静态化技术方案里没有反向代理的身影,那么这个网站静态化处理可能很难达到我们预期的效果。
好了,今天就写到这里,最后祝大家晚安。