Ngix的四层架构
大并发仍能连上服务器
早期,客户端浏览器直接访问tomcat服务器,由于大量的访问可能集中在查询商品模块上,由于查询模块占用了并发使得整个服务不可用,于是考虑将服务进行模块化拆分,中间通过一台服务器将客户的请求转发到服务模块上。
请求转发服务器不同于lvs负载均衡,lvs不会跟客户端进行三次握手,而请求转发服务器会与客户端进行三次握手,连接建立后,再调用服务模块进行计算,获得返回的数据后转发给客户端。 这样用户的连接过来都与请求转发服务器进行连接,并发的压力在转发服务器上。
由于转发服务器需要与客户端握手,采用普通的tomcat只能同时有千级别的并发量,Nginx可以单台有5万的并发量。tomcat需要启动jvm处理请求,翻译字节码文件在应用级别上提供服务;而Nginx是通过c语言实现,直接调用内核让客户端和后端的服务模块建立io流,快速的进行数据的转发,提高了并发性能。
Apach 处理客户端请求是来一个请求fork一个一个线程处理,而Nginx是一个进程处理所有请求,少了进程间的切换的花销。
因此将请求转发服务器替换成Nginx服务器,并且配置Nginx服务器集群进行请求转发到相应的服务器,在他们前面放一个lvs将请求负载到Nginx服务器上,这样解决了用户因为并发太大连不上服务器的问题。
快速获得计算结果
高并发下用户能连接上了服务器,这时候请求的压力又到了后面第四层的服务模块,我们可以通过服务模块集群再在前面加一层lvs进行负载均衡。但是因为Nginx的反向代理,不仅可以将请求分发到不同的模块上,还可以在模块间进行负载均衡。解决了用户连接上服务器后,快速获得计算返回结果的矛盾。
总结一下Nginx的作为webserver的两个功能:
1)识别用户过来的url进行转发
2)负载均衡
session 一致性
当Nginx基于反向代理做负载均衡到了不同的后台服务上,每次请求后端的服务器都不认别的服务器放的session,会重新发一个session到浏览器的cookie中。如何解决多台服务器间的session一致性问题呢,避免用户不断登出。
数据同步:不同服务器间的数据同步session数据
数据共享:中间引用数据库或者文件系统共享session等,但是必须要各个服务器做时钟同步,避免过期问题。
但是这样IO增加,拖慢计算应答,尽量使用内存数据库,规避IO问题,可以使用redis、memchached来实现session一致性。
具体方法网上很多,例如配置tomcat的context.xml,指定它的session存储位置。例如配置tomcat的session共享
这种方法服务器只能使用 tomcat ,但网上有针对 memcached 和 redis 实现,直接配置就行了。
memcached 实现:
网址:http://code.google.com/p/memcached-session-manager/
修改 tomcat 的 conf 目录下的 context.xml 文件:
<Manager className=“de.javakaffee.web.msm.MemcachedBackupSessionManager”
memcachedNodes=“n1:localhost:11211 n2:localhost:11212”
failoverNodes=“n2”
requestUriIgnorePattern=".*.(png|gif|jpg|css|js)$"
sessionBackupAsync=“false”
sessionBackupTimeout=“100”
transcoderFactoryClass=“de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory”
copyCollectionsForSerialization=“false” />
以上是以 1.3 版为例子,需要用的 jar 包:
memcached-session-manager-1.3.0.jar
msm-javolution-serializer-1.3.0.jar
javolution-5.4.3.1.jar
memcached-2.4.2.jar
后台的tomcat做session共享,不需要Nginx修改配置。
session 过期: session过期是指,客户浏览器存储的session存储的时间,小于服务器上session的一段时间,表示客户端超过一定时间没有登陆了。而当客户端一登录,服务器会用服务器的时间更新客户端session的时间。 如果有两台服务器,一台时间是2018年,一台是1970年。 客户端访问1970年时,不会过期,但是会将客户端的session时间更新为1970年,此后Nginx路由请求到了2018年的服务器上,会发现客户端过期了,重新登录并将客户端session改为2018年。下一次再请求1970年的服务器时,不会过期,但是又会把客户端的session更新成1970年,周而复始。