版权所有,转载请注明出处 http://soartju.iteye.com/blog/1850031
作者:高飞(Kao.field,Soartju)
三、互联网主要技术产品介绍
3.2互联网大并发处理技术产品-Nginx
3.2.1 Nginx是啥、能做啥、为什么用它
首先来说说大并发的问题,当然这是个系统性问题,需要应用服务器、数据库、缓存等等方面统一配合才能支持大并发,不过为了简单,我们现在就假设数据库没瓶颈、IO没瓶颈。
我们都知道,一台web服务器(tomcat、resin等),它能处理的并发请求量肯定是有个上线的,超了这个量,你就算把服务器咋了,它也顶不住。开多个实例?我靠别抬杠,说的就是单台,开再多实例,那也是有个承受上线的。
好吧,单台有个封顶上线,要是访问量很大,并发很多,怎么办?这就引出了我们的一个互联网技术产品-Nginx,Nginx是个什么东西呢,简单的说,他就是个代理,他可以同时代理多台代码逻辑完全一样的web服务器,请求来了(访问个url地址就会发请求哈), 他先接收然后找到后面的真正web服务器来处理。本来请求是发给单个web服务器的,现在都发到nginx了,然后它在分发到后面的多台web服务器。假如nginx代理了3台web服务器,那现在的并发处理能力就是原来单个web服务器的三倍(3台web性能一样的情况)。这里有两个问题,一是web服务器为啥要一样?是啊,不一样其实也ok,不过对于同一个请求,你要是都只有一台服务器提供服务器,那性能是没什么提升的,要是多台一样的提供服务,就可以分配给多台承担压力了。二是,nginx是怎么找到后台的真正web服务器,并让他们之间均等的?这个问题呢,就是nginx的实现了,nginx提供了轮询的方式(还有其他方式了),这种方式最常见,能保证后面的web服务器被均匀的访问到,这个通过配置nginx就可以实现了。
有些朋友可能会问,nginx没有瓶颈吗?能代理无限个web服务器?好问题,nginx也有瓶颈,但是代理4-5个web服务器还是比较很轻松的,单台nginx的瓶颈问题,还有其他方式解决,这里只给个概念,就先不扩展了,DNS轮询、LVS都能将请求分发到多个nginx上。
3.2.2 Session共享、用户识别跟踪
我在刚接触nginx时,有个最让我费解的问题,就是nginx代理的web服务器, 他们之间的session是怎么共享的?本来单机的时候,之间用session就行了,这好多台web服务器,每台web服务器上都有各自的session,完全不一样啊,那不是乱套了?(session是通过cookie中的seesionid识别的,不同的web服务器分配的sessionid不同,那到不同的web服务器上也就没法拿到其它服务器的session了,而且session也不在一台web服务器上,怎么共享?不了解session原理的同学先去找找资料哈),怎么做的呢?
我当时也是找了一堆资料,什么memcache共享session啊,no session啊,看的那叫云里雾里。现在反过来看,人家说的还真对,不过我是感觉把简单问题说复杂了,还搞了一堆名词,显着那么高深。其实不管是memcache共享还是no session,就是让web服务器在用户的cookie里,记录一个唯一标识,通过这个唯一标识,所有的web服务器都可以拿到用户的其他信息。这里一定要记得,所有web服务器是一样的代码,所以彼此之间生成的唯一标识规则是一样的,也就都能够识别这个唯一标识,有了唯一标识,那就想做啥做啥了,你想查用户的任何信息,那都ok了。什么?你的session中还存了除了用户信息以外的其他信息?哥们,那你就得改了,把用户信息和他的其他信息绑定(怎么绑定?靠,userid+绑定信息id呗),存到一个全局唯一的地方,就可以访问到了。再或者,直接把session信息保存到全局唯一的缓存中,如memcache,通过sessionId这个唯一标识,每次去memcache中获取session信息。不过session能不能序列化,是个大问题,您还是改程序结构吧。
具体的说,就是所有web服务器都是一样的,当用户登陆后,往用户的cookie中记录一段标识用户的信息,如userinfo = 加密1(userid,nickname,email,age),当后继用户有请求过来时,web服务器通过获取用户cookie中的userinfo,再用解密算法拿到明文的userid等信息,拿到userid后,你就可以识别用户了,要么到数据库里去查用户信息,要么从已经缓存的memcache中查找用户信息。OK,session共享的问题就这样解决了,其实session共享,就是为了解决不同服务器间,识别用户和数据共享的问题,放在一个全局唯一的地方,如数据库、memcache缓存中就可以了。
3.2.3 URL重定向及页面静态化
均衡的问题、共享的问题解决了,还有一个比较常用的技术就是页面静态化。想当年,当我第一次听说这个名词的时候,那叫一个神奇啊,居然还能把一个动态页面(jsp之类的),弄成一个静态html页面,对说这话的人(忘了谁了)那也是无比的敬仰啊。后来当我用了之后,才发现,嗨,用的就是人家的现有技术产品,只是用了一下下而已,没那么深奥。
好了,回到正题,首先来说说,为什么要用页面静态化?我们在访问网站时,经常会有一些页面,更新少,但是读的多,或者没有必要马上访问到最新的变动数据,尤其是新闻文章页面、blog文章页面等等,基本上很少去更新的,既然是这样,每次要是都动态请求web服务器,占用服务器的计算,那就没什么必要了,尤其是当访问量非常大时,如果都让web服务器动态计算,别说web服务器,每次从数据库访问数据都能让数据库秒挂。所以就出来这么个概念,对于读多写少的页面,就可以把整个页面缓存成静态html文件,直接访问html页面就行了,而不需要再跑到web服务器上去动态生成页面。
那这就涉及到一个问题,本来是个jsp页面或者其他的动态页面, 用户每次访问的是.jsp结尾的url,如果缓存成html,怎么让用户再去访问那个html呢?嘿嘿,nginx已经设计好了,既可以满足让用户始终访问同一个url,又可以满足缓存需求和动态生成页面需求。如何做到的?举个例子就全明白了。
首先,Nginx提供了url重定向的功能,你就把它想象成你访问的地址是urlA,但是nginx会把它转换成urlB,urlA呢是用户访问nginx时的url,但是nginx访问webserver时就变成了urlB,用户只能看到urlA,但看不到urlB,urlB只对nginx可见。好晕啊,没事,我们拿例子说话。
假如我们现在访问一篇新闻,如果是原来的动态页面方式,访问web服务器时url可能是这样的:http://192.168.1.1/getArticle.jsp?articleId=123,注意其中的参数articleId=123。用了nginx就不一样了,我们就可以在nginx上配置一个虚拟的url:http://kao.field.com/Article/123.html,通过配置,nginx可以识别出此url最后的参数123(123.html中的123哦,url前缀格式自己定义,能识别出来是访问文章页就行了),然后重定向到后端web服务器上真正的url,也就是上面的url地址http://192.168.1.1/getArticle.jsp?articleId=123。因为只有nginx对用户可见,web服务器用户是看不到的,所以用户只能访问http://kao.field.com/Article/123.html,此请求到达nginx后,nginx就会根据配置情况,拿到参数123,然后再去web服务器上请求对应的url地址http://192.168.1.1/getArticle.jsp?articleId=123。nginx上的配置应该类似下面这样:
rewrite "^/Article/(.*)\.html$" /getArticle.jsp?articleId=$1 break; //$1就是前面的(.*)
(还是上代码直接)
因此访问http://kao.field.com/Article/123.html静态页面,其实最终访问的就是后端的http://192.168.1.1/getArticle.jsp?articleId=123动态页面。 既然有了html页面,nginx就可以针对http://kao.field.com/Article/123.html静态页面配置缓存时间了,你可以根据实际情况,缓存 2分钟还是1小时之类的。对于新闻类文章,可能更新慢一点可以接受(也就是你改了文章,2分钟后看到效果也ok),那缓存2分钟就行了,那在2分钟内,用户看到的始终是上一次到web服务器上生成的动态页面,过了两分钟,静态页面失效,请求会再次穿透nginx到后端的web服务器访问jsp,重新动态生成页面并缓存成html页面,也就是说2分钟内,是始终不会到web服务器的,2分钟后静态页面失效,才会再次来到web服务器,然后在缓存,周而复始。
至于nginx是怎么把后端一个jsp,缓存成html的,这个不在我们话题内。反正呢,最后可以把jsp返回的内容,生成一个html,nginx把这个html缓存到本地磁盘或者内存,当下次用户在访问这个html时,只要nginx上的html缓存还在,就直接返回这个html页面,否则就到web服务器请求动态页面,然后再把生成的动态页面保存为静态html缓存起来。
有的朋友可能会问,那要是实时呢?方法很多,你去掉缓存就实时了,不过其他节点能不能提得住就是个问题了,需要引入其他一些技术手段才能保证整体系统都能扛得住,以后再聊。
3.2.4 小结
好了,经过第一个互联网技术产品的引入,我们的web服务器集群已经显现了,服务能力已经是单机的N倍,主要的用户跟踪及Session共享问题已经解决,我们简单画下原型图,以后的架构就在这上面逐渐扩展开来。
图 1 nginx+webserver集群