一.什么是Nginx?
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用Nginx的网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
二.为什么要用Nginx?
提及Nginx,我们就需要了解下web应用服务器。在此,我们暂且以tomcat这款应用服务器为例来介绍。
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。由于Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
一般来说,用单机tomcat搭建的网站,在比较理想的状态下能够承受的并发访问量在150到200左右。按照并发访问量占总用户数量的5%到10%这样计算,单点tomcat网站的用户人数在1500到4000左右。对于一个为全国范围提供服务的网站显然是不够用的。
在互联网飞速发展的今天,大用户量高并发已经成为互联网的主体.怎样能让一个网站能够承载几万个或几十万个用户的持续访问呢?这是一些中小网站急需解决的问题。
为了解决这个问题,我们引入了负载均衡方法。负载均衡就是一个web服务器解决不了的问题可以通过多个web服务器来平均分担压力来解决,并发过来的请求被平均分配到多个后台web服务器来处理,这样压力就被分解开来。
目前,负载均衡服务器主要分为两种,一种是通过硬件实现的负载均衡服务器,简称硬负载,例如f5;另一种是通过软件来实现的负载均衡,简称软负载,例如apache和nginx。硬负载和软负载相比,前者作用的网络层次比较多,可以作用到socket接口的数据链路层,并且对发出的请求进行分组转发,但是价格成本也随之较贵;而软负载作用的层次在http协议层之上,可以对http请求进行分组转发,并且由于是开源的,所以几乎是0成本,当前,阿里巴巴,京东等电商网站使用的也是Nginx服务器。
我们接下来以一副示意图演示Nginx对tomcat的负载均衡配置:
三.tomcat如何配置首个启动工程?
在讲述Nginx负载均衡之前,我们先熟悉tomcat的配置。
以win7系统为例,我们平时在电脑上开启tomcat应用后,通过浏览器访问,会访问到tomcat的系统默认首页。那么,如何修改tomcat的首个启动工程呢?
以tomcat7为例,我们将一个名称为Demo1的java web项目导出为一个war文件,然后放在tomcat的webapps文件夹下,接着打开tomcat的conf文件夹下的server.xml文件,在<Host></Host>中加入
<Context docBase="E: ginx omcatAwebappsDemo1" path="" reloadable="true" crossContext="true"/>
然后重启tomcat,并在浏览器地址栏里输入http://localhost:8080,这时就会发现tomcat的默认首个启动工程变为Demo1。
四.如何在同一个tomcat上配置多个虚拟主机?
接下来,我们再看如何在一台服务器上设置多个域名,从而使得用户访问多个域名时,可以分别指向同一个tomcat应用服务器中配置的不同web工程。
首先,我们按照C:WindowsSystem32driversetc路径,打开该路径下的hosts文件,在里面配置下域名映射信息,如下:
127.0.0.1 www.baidudu.com
127.0.0.1 www.taobaobao.com
接着,我们另建两个java web项目,分别是Demo1和Demo2,然后再打开tomcat中的server.xml文件,在里面配置两个服务器主机信息,如下所示:
<Host name="www.baidudu.com" appBase="webapps" autoDeploy="true" unpackWARs="true"> <Context docBase="E: ginx omcatAwebappsDemo2" path="" reloadable="true" crossContext="true"/> </Host> <Host name="www.taobaobao.com" appBase="webapps" autoDeploy="true" unpackWARs="true"> <Context docBase="E: ginx omcatAwebappsDemo3" path="" reloadable="true" crossContext="true"/> </Host>
配置完毕后,我们再重启tomcat,分别访问新配置的两个域名,发现它们会各自指向相应的web工程,从而实现了用一个tomcat配置多个虚拟主机。
五.如何通过Nginx实现tomcat集群配置与负载均衡?
我们接下来看通过Nginx对多个tomcat进行集群配置。在这里,我暂且在一台电脑上用两个tomcat做下演示,同时将这两个tomcat分别命名为tomcatA和tomcatB。为了避免同一台电脑上开启多个tomcat引起端口冲突,我将tomcatA的http访问端口配置为8081,将tomcatB的http访问端口配置为8082,为了显示不同tomcat的访问区别,我暂且让tomcatA的默认首个启动工程为Demo1,让tomcatB的默认首个启动工程为Demo3。
接着,我们双击ningx中的nginx.exe文件,从而启动nginx服务。当然,我们这里还需要对nginx中的配置文件进行一番配置,所以,如果nginx处于开启状态,则暂且在DOS窗口中关闭nginx服务。如图所示:
接下来,我们打开nginx中的conf文件夹下的nginx.conf文件,我们在里面加入要配置的tomcat集群,同时,考虑到不同的服务器性能差别,可以配置相应的权重,从而实现服务器的负载均衡。如下图所示:
上图中,标注红框的部分是关键配置,然后,我们在浏览器的地址栏中输入localhost,会发现tomcatA和tomcatB的所承担的访问任务比重约为5:1,从而实现了nginx对tomcat的负载均衡配置。
六.如何处理Nginx负载均衡中的session会话信息丢失问题?
我们在通过nginx完成了对tomcat的集群与负载均衡配置后,还面临着一个关键问题,那就是如何解决session会话信息的共享问题。解决方法也很简单,需要两个步骤:
步骤一:在每个tomcat的server.xml中找到标签:
<Engine name="Catalina" defaultHost="localhost"> #.... #.... #.... </Engine>
在上面的<Engine></Engine>标签中加入下述代码,注意不要做任何更改:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
步骤二:在web项目的web.xml文件中,添加节点<distributable/>就可以了,如下所示:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <distributable/> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
到此,我们就解决了Nginx在tomcat集群配置中的session共享问题。这是基于tomcat自身的广播机制完成,虽然在功能上实现了session共享,但是运行效率相对较低。
为此,我们再介绍一种企业级解决方案,那就是引入redis缓存完成session共享。
那么,什么是redis呢?为此,我们要对NoSql有所了解。NoSql叫非关系型数据库,它的全名Not only sql,它不能替代关系型数据库,只能作为关系型数据库的一个良好补充。它是为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案。
NoSql可以有多种分类,如根据键值对(Key-Value)存储数据的数据库(如Redis),列存储型数据库(如Hbase),文档型数据库(如MongoDB),图形(Graph)数据库等。我们在这里用到的Redis就是NoSql数据库中的一种。Redis可以将数据储存在缓存中,极大地提高了访问数据的效率,还可以根据需要对数据进行持久化存储。
Redis中可以储存5种类型的数据,分别是:
1 String 2 hash 3 list 4 set 5 zset
言归正传,我们继续介绍运用Redis实现session共享。
首先,我们可以根据自己所用电脑的操作系统下载Redis文件,如下图所示:
我们以Windows系统为例,上面分别对应32位和64位的win7操作系统,我们选择对应的压缩文件,解压到电脑中的一个位置,如下图所示:
在上图中,我们可以对redis的配置做下修改,如设置数据持久化策略,配置端口号等,为了方便启动redis服务器,我们还可以写个批处理文件,通过双击该批处理文件即可启动redis。上图中的“启动redis服务器.bat”文件内容如下:
C:
cd C:UsersAdministratorDesktopwork
edis
redis-server redis.windows.conf
接下来,为了便于更好地模拟nginx集群配置tomcat时解决session共享的问题,我们先下载好nginx和两个tomcat,如下图所示:
然后,我们在每个tomcat中的server.xml里,删除原先通过tomcat广播机制配置的代码块,如下图所示:
然后,我们继续在server.xml中,找到<Context />标签,将其改成<Context></Context>,根据需要,在该标签中加入下面的信息:
<Context docBase="E: ginx omcatBwebappsDemo" path="" reloadable="true" crossContext="true"> <!--redis配置session共享--> <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" host="127.0.0.1" port="6379" maxInactiveInterval="600000" <!-- database="0" #optional: defaults to "0" sessionPersistPolicies="PERSIST_POLICY_1,PERSIST_POLICY_2,.." #optional sentinelMaster="SentinelMasterName" #optional sentinels="sentinel-host-1:port,sentinel-host-2:port,.." /> # optional --> /> </Context>
我们要在做集群配置的tomcat的server.xml中均做如上配置,同时确保在web项目的web.xml中添加上<distributable/>标签。
接着,我们把三个jar包放入每个tomcat根目录下的lib文件中,三个jar包如下图所示(您可以在网上download,如果找不到请给我留言,并留下您的邮箱,我会发给您):
至此,我们就运用redis技术做好了nginx集群配置tomcat中面临的session共享问题。
最后,我们依次开启tomcat,nginx,以及redis,就会发现session已经实现了共享。