标签:
最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行。那么大家(开发者和企业)为什么那么的迫切的希望.NET跨平台呢?第一个理由是便宜,淘宝号称4万多台服务器全部运行在Linux,Linux平台下还有免费的MySql,这些都是免费的,这些省下来直接就是利润呀,做企业的成本可以降低又没有任何损失,何乐而不为呢?第二个理由是在Linux系统下还有很多非常优秀的构架(当然同样也是免费的),分布式缓存Memcached, 大数据处理构架Hadoop等等,这些都为一些大型的分布式系统提供了很好的支撑,当然还有诸如Liniux系统本身的一些安全和网络方面的优势,等等。 所以也难怪大佬们都纷纷不约而同的没有选择.NET。
但是如果.NET也支持跨平台之后,那这样的格局可能就要发生变化了。上面所有的优势依然可以保留,并且加上它语法的优越性,以及快速的开发效率等,还是会为其争得一席之地的。
但是,是不是Windows平台下就不能实现这些大型的分布式系统呢?我相信这个问题已经被广泛讨论过,但是至少我没有看到比较清晰的,完整的案例。带着这些问题,我决定升级我的机器,自己从头到尾在windows平台下搭建一个高可扩展性的分布式网站出来。我经验尚浅,很多的东西还处于摸索阶段,所以如果有错误,还请大师多多指点。
负载均衡可以帮我们解决两个方面的问题,第一个即提高可用性。这里面的可用性主要是从WEB服务器,的角度来讲的,如果说我们只有一台Web服务器,而它遇到了某种未知的错误导致IIS无法启动,那么我们的网站就无法访问了,这就是一种比较低的可用性。那么利用负载均衡,放在我们Web服务器的前面,由它来收集所有的请求,然后转发给我们的Web服务器, 这时候我们就可以添加两台Web服务器,如果其中有一台坏了,至少还有另一台在工作,也不至于导致我们的网络无法访问。
当然,有人可能会问,如果那台Load balancer坏了怎么办?那不是还是访问不了网站么?我们这里讨论的是提高可用性,在做到365天*24小时不间断的服务,需要有另外的组件来支撑,我们留在后面讨论。除了可用性以外,负载均衡还可以帮助我们提高可扩展性,当然这个可扩展性同样是指的Web服务器层面。从网站性能的角度来讲,好几个程序员花上好几天的时间做了一些优化所带来的效果有时候可能还没有直接加一根内存条来的快。内存加完了没什么影响,我们还可以换更好的CPU,CPU换完了,我们还可以用固态硬盘,甚至很多公司已经开始直接把数据放到内存中了(注:具体场景具体对待)。 如果这些都不可以再加了呢?那就再加机器吧,一台服务器可以处理1000个并发,那么两台理论上是2000了,所以这就有了我们的横向扩展。
所有的请求首先全部到达Load balancer,再由它转发到具体的Web服务器,转发的方式分为以下几种:
我们还可以根据负载均衡器所使用的技术将它们分为以下几类:
我们可以从一个网站的最初级版本开始说起,最开始的时候我们决定搭建一个网站,但是我们也不知道效果会怎么样,光键是那时候,我们很穷,于是我们租用了一台托管主机,它可能承担了至少三个或以上的角色:WEB服务器、静态资源服务器,以及数据库服务器。我们可以用ASP.NET MVC4 + SQL 2008来做一个基本的电子商务网站,基本够用了。但是能够承载多大的访问量呢?下面我们来做一个简单的测试(注意:本文以后本系列所面所有的测试都是在虚拟机上进行的,忽略网络的因素,以及多台虚拟机同时运行时CPU资源的因素,所以测试结果只是一个参考)。
在我的机器上有一台虚拟机配置如下:
CPU: Intel Core I5- 4570, 3.19GHz,
内存: 4G
硬盘:20G (ShineDisk 固态硬盘)
测试页面没有什么复杂的逻辑,利用ASP.NET MVC4 + Entityframework 6.0 + SQL 2008 + IIS8.5来实现, 我们的页面也只是一个简单的列表页,列出系统里面所有的商品。
Home Controller 代码
Index.cshtml 代码
在数据库初始化的时候插入500条测试数据
连接字符串就使用本地连接就可以了。
1
2
3
|
<connectionStrings> <add name= "CarolContext" connectionString= "Server=localhost;database=carol;trusted_connection=true" providerName= "System.Data.SqlClient" /> </connectionStrings> |
我们使用的轻量级的ab来做压力测试,如果不熟悉ab的可以点这里,下面是测试的结果:
ab -n1000 -c100 http://192.168.1.131
通过测试发现,我们这单个服务器的吞吐率接近在110~130之间,而一旦并发数达到200以后,每个请求的处理时间就达到1.5s多了,400个并发用户的时候每个请求要花上3s多的时间。如果在真实的网络环境中可能会更差。由此我们可以得出我们这个服务器可能最大支持120人左右同时访问。
现在我们来做一个花费不是很大,又空间做的扩展,也不需要改任何架构,我们只是再加一台专门的数据库服务器。
下面我们再来看一下测试结果:
大家可以看到,这里我们的吞吐率(每秒处理请求数已经提升到了150左右),并发处理能力提升了50%,并且300和400并发的时候响应时间也比上面的架构要好一些。
上面我们一台独立的Web服务器和一台独立的数据库服务器的组合已经可以处理150左右的并发了,现在我们假想一下如果网站的的知名度越来越大,如果同时有400个用户来访问怎么办? 从上面的图中我们可以看到400个并发的时候服务器的处理时间为2582.637ms(实现上这是拿到响应的时间,因为我们是一台机器上的不同虚拟机,我是在主机上做测试,所以我们就忽略网络传输的时间,假设这个就是我们的服务器处理时间),这个服务器响应时间也就是我们通过F12->网络 中看到的等待时间 。
页面什么时候能拿到这个响应还要加上网络传输的时间,也就是Receiving。1ms的传输时间堪称神速啊!我家用的长城宽带10M,总是早上网络出奇的好,一到晚上就挂掉了,还有可能就是你们现在都没有上博客园 :)
用户体验黄金法则之一: 网站加载时间 = 用户体验,别说3S,可能等个2S你页面还不出来,用户准备离开了,下面是淘宝购物车页面的加载时间 。
国内很多大型的网站的响应时间基本上都控制在100ms以内,基本达到那种一输入地址敲回车,眨眼之间页面就出来了。当然这并不是光有个负载均衡加几台web服务器就能解决的,我们后来再来一步一步的实践下去。 话说回来,我们上面的测试结果基本上只有并发为10的时候响应时间是在100ms以内的, 看来我们还有很长的一段路要走啊。
正所谓“最好的架构是进化而来的,而不是设计出来的” ,面对我们现在的瓶颈暂时通过负载均衡添加多台Web服务器就可以了。我们上面讲到负载均衡器类型的时候有一种 Microsoft负载均衡,我们可以很轻松的通过服务器管理器来将这些组件安装到我们的服务器中。 安装我们就不讲了,就是通过服务器管理-> 添加角色和功能->在功能中选择“网络负载均衡” 然后安装就可以了。
注意:图中的Load balancer实际上是不存在的,因为只要我们2台Web服务器安装了网络负载平衡组件,在其中任意一台上建立群集就可以了,图是为了方便大家理解。
这样的话我们的服务器架构就成了下面这个样子:
192.168.1.254 就是我们暴露的外部IP地址,访问192.168.1.254的请求就会转发给后面的两台WEB服务器。
配置网络负载均衡
在我们为上面2台WEB服务器安装NLB之后,我们在其中任意一台上来新建群集,然后将另外一台加入到这个群集中即可,我们就在web-01(192.168.1.130)上来新建这个群集。在建立群集之前,我们要确保这2台服务器都是使用的静态IP,否则无法将他们加入到群集中。
现在我们就可以到我们的真实机器上去访问192.168.1.254了,也就是说马上我们就进入测试环节了。
本文中所有的测试结果都没有取第一次的结果,EF也需要预热,同样的查询在EF中也是有缓存的,所以第一次的结果会与后面的测试结果有很大的区别,后面的几次(在相同参数下)基本差别就不大了。
可以看到现在我们的吞吐率大概平均在230左右,与一台WEB服务器+一台DB服务器相比,处理能力又提高了50%,为什么不是100%呢?一台WEB服务器能处理150的并发,那两台应该是300才对呀?我能够想到以下原因:
为了验证一下,我再扩展了一台WEB服务器,我们使用3台WEB服务器+1台DB服务器看看是什么效果。
我们新建一台虚拟机web-03,然后将它也加入到我们的群集中。
测试开始!
在加入第三台WEB服务器之后,我们的吞吐率(每秒处理请求数)再次得到提升从230升至360,并发处理能力再次提升56%,并且大家可以看到,400并发以下的平均每请求处理时间都在1s以内,可喜可贺啊!
最后上两图让大家更直观的看一下这些性能的变化:
以上数据均来自本人机器上的测试,虚拟机全部采用与第一台服务器同样的配置。
在网站架构的不断演变中,负载均衡起着非常重要的位置,不仅仅为我们提升可靠性和可扩展性,有一些比较强大的硬件设备还能提供缓存,以及session机制。今天我们用到的负载均衡是Windows Server自带的一个组件,它是最简单实现负载均衡的方式,但是功能不是特别完善,而且一旦NLB本身发生错误那么将导致所有的网站都不能访问,我们后面就来通过引入APR(Application Request Router)来解决这个问题,想要真正了解大型网站的架构实现,而不是仅仅知道负载均衡,分布式缓存,数据库分离这些名词么?那就来跟我一起学习吧!另外我们今天只是用一个简单的页面做了压力测试,只有读数据的操作,还没有写的操作,也没有任何复杂的事务,但是别担心,我们一步一步来 :) 。
我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效果,可以说还是非常的理想的。同时我们也收集到了不少的问题,比如说如何在这种分布式的架构下使用Session,NLB中有一台服务器挂掉了会导致对外暴露的地址无法访问,如果实现服务器之间的同步,如果更好的进行热修复等等,还有我们在上一篇中也提到了NLB所提供的功能是非常简单的,为了回答我们前面提到的问题,也为了提供一个比较全面完整的负载均衡方案,我们来看看Windows平台下负载均衡的另一种实现APR (Application Request Router + Web Farm + Url Rewriter),希望可以为大家解决一些实现的问题。
话不多说,为了实现一个比较完整的负载均衡,我们要引入以下5个组件。
安装Web Fram 必须要先安装Web Deploy 和Web Platform,所以我把它们俩放在最前面,你也可以参考上面的顺序来安装,当然你首先得自己把IIS和ASP.NET 模块给装上。我们这次不会对这5个组件的原理做详细的介绍,大家知道怎么操作就可以了,如果有兴趣的同学可以继续深入。安装过程非常的简单,基本上每一个组件只需要点一下按钮就可以了,全部安装完之后,你就会在当前那台机器上的IIS下看到一个Server Farms的结点。
如果大家还有印象,在使用NLB配置负载均衡的时候,我们是不需要一台单独的机器来作为主入口的。 我们给所有的WEB服务器都安装上NLB,然后选择任意一台将其它的WEB服务器加进入同时设置一个单独的IP作为入口地址即可。 但是换成APR,情况就有点不一样了。我们需要一台单独的入口服务器来接收所有的请求,由它再把所有的请求根据配置的规则转发给其它真实的WEB服务器。
3 台Web 服务器我们还是用我们上次做过实验的那三台,我们再添加一台配置一样的虚拟机,然后给这4台服务器全部安装上APR(包括我们上面列出的5个组件)之后,我们就可以开始配置了。我们首先在我们的入口服务器上创建一个Web Farm。在IIS中右击Server Farms -> Create Server Farm,
我们勾上“Server farm is available for load balancing(在Web Fram中使用负载均衡)” ,下面的“Provision server farm”,我们也勾上,并为它输入一个账户,这个账户要求有权限可以访问这个Web Farm里面的所有服务器。Provision 主要是用来实现主-从服务器同步的,我们暂时先忽略它,后面再具体讲。
我们将192.168.1.130设置我们的主Web 服务器,一会我们结合Provision(俺不知道这个翻成中文该叫什么,直译“提供”好像很别扭) 功能就可以实现在主服务器上部署和更改配置就会被自动同步到其它的服务器上。完成创建Web Farm之后,我们就可以在IIS中进行后面的配置了。我们通过点击每一个Web Farm下的Servers来查看每一个Web服务器的状态,是不是连接正常等等 。
同时我们还可以点击每一个Web farm来进行以下功能的管理,这里我们就点击Mono。
配置Load Balance 算法
我们首先要做的就是进入 “Load Balance”,在这里你可以选择负载均衡的算法 :轮转调度,随机分配,URL参数,请求头等。如果不了解这些算法干什么 的,那就去复习上一篇吧。APR为我们提供了以下7种算法:
大家可以已经猜到,后面3种算法是可以利用来实现这种分布式环境下session的访问的,但是由于要涉及到其它的配置,所以我们后面再讲,让我们先专注于把这个负载均衡配置完,所以我们就里就先选择比较简单的Least response time,谁当前返回响应最快我们就把请求给它,验证了那句话,“能者多劳啊”。
配置转发规则
APR的机制是做为一个代理服务器,它负责接收请求,但是不做任何处理,而是直接将请求分发给具体的WEB服务器。同时我们还可以配置一些规则,有一些请求转发,有一些请求不转发,这就要感谢我们的url rewrite组件了。我们可以进入“Routing Rules”来进行相关的配置。
在实际的环境中,如果我们使用NLB在第一次部署的时候,就需要一个服务器一个服务器的部署,而且如果要对IIS进行其它的一些配置就会显得很烦琐。在APR中给我们提供的Provision功能,就可以帮助实现这样的同步功能。
在Server Farm的功能视图中,我们可以找到以下两种类型的Provision:
我们可以来做一个Platform Provisioning的例子,点击我们的Server Farm -> 在右边的功能视图中双击Platform Provisioning -> 勾选下面两个选项。
然后我们点击左右的Servers,选中我们的主服务器(Primary),在右边的操作列表中选择 “Install Product”,在弹出的窗体中安装的程序就会被自动安装到当前Server Farm中的所有其它服务器中。
和上面的思路一样,我们不需要每一个程序都部署一遍,我们只需要在主服务器上部署一遍就可以了,所有的内容以及IIS的设置都会被自动同步到其它服务器上,这就是Application Provisioning来帮我们实现的。我们可以通过点击我们的Server Farm ->在右边的功能视图中双击 “Applicaiton Provisioning” 然后勾选下面的两项即可。
接下来,我们只需要在我们的主服务器上建立我们的站点然后部署我们的网站即可,包括对网站进行一些应用程序池的配置也是只需要在主服务器上完成的,我们就不需要到每一台服务器上都去布置一遍了。
既然入口服务器不做任何处理只是转发请求的话,那我们还需要把我们的网站的内容放在入口服务器的IIS下么?这个就取决于不同的场景了,你可以建一个空的站点什么也没有,你也可以用它来做一个简单的文件服务器,在上一步中将静态文件不转发即可,让我们Web Farm中的服务器只处理动态的请求,也可以减轻他们的压力。当然如果你有单独的文件服务器那就更好了。作为测试用途我们在入口服务器上就不建任何网站了,直接使用安装IIS自带的那个默认网站即可。
有人可能会有疑问,因为我在配置Server Farm的时候同样也有这样的一个疑问。“所有的请求都是由入口服务器接收,然后再分发给Farm中具体的服务器的,那入口服务器的那个网站该如何配置呢? 是用80还是8080端口,如果我建了好几个网站,那到底哪一个网站的请求会被Farm拿到再进行转发呢?”
我在入口服务器中没有做任何网站的配置,也就是说本地有一个http://localhost的网站是可以访问的,对于外部来说它的地址就是 http://192.168.1.129/,那么为什么当外部访问 192.168.1.129的时候,它就会被Farm 中的服务器处理呢? 这就要多亏我们的Url Rewrite模块了,我们可以点击我们的Farm Mono,进入到功能视图->然后点击 Routing Rules -> 在Routing Rules 右侧的操作列表中点击 URL Rewrite... 对Routing Rules进行更详细的管理。
在我们的URL Rewrite窗口,我们就会看到已经为我们默认创建了一条入站的规则。
我们可以双击那条规则查看详细,或者进行编辑,我们可以看到这条规则实际上是用通配符匹配了所有的入站请求,然后转发给我们的Server Farm: Mono。原来是URL Rewrite在这里起了作用,当然我们也可能把 *改成 其它的通配符,以及使用正则表达式来匹配都是可以的,这些都是URL Rewite里面的功能,是可以直接搬过来用的。
URL Rewrite帮助我们匹配入站请求,然后转发给Farm,在Farm层面 APR根据 我们配置的负载均衡算法将请求转发给具体的服务器去处理请求。现在我们再回过头来看看我们最开始安装的5个组件都分别起到了什么作用。
到这里为止,我们用 APR + Web Farm搭建的负载均衡就完成了,最终结果是我们在外面访问 http://192.168.1.129的时候,实际上是由我们Farm中的3台Web 服务器处理的,口说无凭,我们来验证一下。验证的方法很简单,我们在每个服务器下放不同的文件用来标识当前是哪个服务器在处理响应(记得在部署文件的时候要先把Application provisioning关闭掉,不然主服务器上的文件会被同步到其它的服务器上去的)。
在web-02和 web-03上,分别返回不前的服务器的名字就可以了。但是在测试上可能会遇到一点小问题,那就是当我们访问http://192.168.1.129的时候,总是由web-01处理的,因为我们的页面帮简单,又只有一个用户在访问,所有后面两台服务器压根没有发挥作用。这时候我们就可以把web-01和 web-02从 Farm中移除掉,那么所有的请求就会被web-01来处理了。
就是这么简单,Web Farm给我们提供的这个功能非常的实用,我们可以在运行时随时动态的添加或移除服务器。还记得以前我们只有一台服务器的时候,为了尽可能的不影响用户,发布都选择在晚上的10点以后,所以经常是一发布就通宵。想想如果有这个功能,白天也可以发布了,只要先把一些机器从Web Farm中拿下来,发布好测试通过之后再放上去并且把别外那一些也拿下来发布就好了。当然这种场景只适合一些中小型的网站,一旦网站大了,那发布将会是一个非常严格的流程,而且一般会有专门的发布人员或者工具。
关于Session在分布式环境下的使用其实是有争议的,有人说老师都不让用Session了,但是有人又想方设法的想要使用它。我们暂且不讨论它的正确与否,因为没有最好的架构,只有最合适的架构,正所谓存在即合理。我们都不得不承认Session在很多管理系统,以及一些小型的网站的开发上带来了很大的便利性,开发快速同时又可以带来看得见的性能提升。所有个人认为,用还是不用那就看场景吧。但是我们从学习的角度出发,还是应该考虑到各种可行性,以及他们之间的利与弊,这样才能帮助我们在真实情况下做出最合适的决策。
在Farm的功能视图中,有一个Server Affinity的功能可以用来跟踪请求或者说提供一种服务器和客户端之间的粘性,当第一个请求被处理之后,这个请求所在客户端后面发起的所有请求都会交给同样的服务器来处理,这就是Server Affinity。APR为我们提供了两种选项:
原来在APR这种分布式架构下使用Session是这么的简单,而且我们可以根据实际情况,Client Affinitt 和 Host Name Affinity一起使用。
还记得我们在上一篇中提到的,引入负载均衡帮提高了两点:可靠性和可扩展性。多台服务器共同处理的情况下,哪怕其中部分出了问题也不会导致整个网站无法访问,提高了我们的可靠性。随时动态的添加和移除服务器而不影响网站的访问,提供了我们的可扩展性。但是这里还有一个问题,但是如果APR所在的那个服务器出了问题怎么办?虽然这种可能性比较低,因为我们的APR服务器只是做了很简单的转发请求的功能,并没有运行真实的网站,但仍然不排队会有其它的异常导致IIS或者Web Farm停止运行,对于像这样的问题,我们就可以通过部署多台APR服务器来再一次提升我们网站的可靠性。
一台APR服务器可以将请求分发给具体的服务器,如果是多台APR服务器,那谁来决定请求是由哪台APR服务器处理呢?
还记得我们上篇讲的NLB么?它不需要一台单独的服务器配置,只需要给目标机器都装上NLB,然后配置一个暴露给外部的地址就可以了。所以这次当我们访问外部地址的时候会有接下来的几步动作:
第二篇稍微来的晚了一点,对一直关注的朋友说声抱歉,最近个人的事情有点多,也是想把APR尽量呈现的全面一点:)。使用APR相对于NLB来说给我们提供了更全面的负载均衡功能,结合APR和NLB一起使用带来更高的可用性,但是由于APR采用的是代理的方式,所以性能会比NLB低一些,但是有时候稳定更重要,不是么?当然还有很多其它的方案我们都是可以去尝试的,比如说Ngnix很久以前就已经在开源社区获得了很好的声誉。我们这两篇算是让大家对负载均衡有一个比较感性的认识,真实的项目过程中还要考虑我们代码的架构,如何保证我们的系统能够在分布式环境下完美运行,并真正发挥分布式的力量,我们还有很长的一段路要走,用分布式缓存替代Session方案,数据库群集,服务群集和队列等,我们一个一个的攻破,欢迎大家持续关注!最后祝大家上班编码快乐 :)
标签:
原文地址:http://www.cnblogs.com/steven9801/p/4199343.html