做者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs
java
前段时间,我花了很多时间来寻求一种方法,把新开发的代码推送到到生产系统中部署,生产系统要可以零宕机、对使用用户零影响。nginx
个人设想是使用集群来搞定,经过通知负载均衡Nginx,取下集群中的Tomcat节点,而后对Tomcat上的应用进行升级,再通知负载均衡Nginx,把Tomcat节点从新加载上去。依次这么作,把集群中的全部Tomcat都替换一次便可。git
那么问题来了,在取下Tomcat节点和加载新Tomcat节点时如何作到对用户无影响呢?方法很简单,共享Session。
下面,咱们用实例来讲明此方案。咱们的例子使用了一台Nginx作负载均衡,后端挂接了两台Tomcat,且每台Tomcat的Session会话都保存到Redis数据库中。其中,Nginx配置为non-sticky运行模式,也即每个请求均可以被分配到集群中的任何节点。当要上线新代码时,只需简单地取下Tomcat实例,此时全部的访问用户会被路由到活动的Tomcat实例中去,并且因为会话数据都是保存在Redis数据库中,因此活跃用户并不会受影响。当Tomcat更新完毕,又能够把此节点加入到Nginx中。github
安装Nginxredis
# sudo rpm -ivh nginx-1.4.2-1.el6.ngx.x86_64.rpm
修改配置文件/etc/nginx/nginx.conf,并添加下面的内容:数据库
http { upstream tomcat { server localhost:8080 weigth=10; server localhost:8081 weigth=10; } include /etc/nginx/mime.types; default_type application/octet-stream;
修改配置文件/etc/nginx/conf.d/default.conf并替换location部分的内容:windows
location / { proxy_pass http://tomcat; }
重启Nginx后端
# sudo service nginx restart
接下来,安装两个Tomcat实例。因为咱们是在同一台服务器上作的演示,要让两台Tomcat不发生冲突,须要修改第二个Tomcat实例的端口号。因为Nginx配置为non-sticky运行模式,对每一个请求采用的是Round-robin负载均衡方式,这意味着它会为每一个请求都抽奖一个新会话。tomcat
接着,下载并安装Redis。步骤省略,很简单。服务器
最后,咱们须要配置Tomcat,让Tomcat把会话Session保存到Redis数据库。
咱们要使用tomcat-redis-session-manager这样的第三方库,主页见:
https://github.com/jcoleman/tomcat-redis-session-manager
要注意此库并不是开箱即用的,使用时须要作一些调整。你须要下载源码,并在更新了依赖库的版本后,重建项目。好比我使用了commons-pool2-2.2.jar和jedis-2.6.1.jar依赖库。要记住把这些jar文件复制到每个Tomcat实例的lib子目录下。
在更新了commons-pool、jedis和tomcat版本这些库后,你可使用build.gradle来构建整个项目。构建完毕后,复制新生成的tomcat-redis-session-manager-1.2.jar到每个Tomcat实例的lib子目录下。并在修改每个Tomcat实例的context.xml配置文件:
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" host="localhost" port="6379" database="0" maxInactiveInterval="60" />
重启Tomcat实例。能够检查到Redis确实保存了Tomcat的会话。而后咱们对Tomcat实例取下或恢复时,访问用户确实没受影响。
我在windows下进行了试验,具体须要redis,tomcat7,nginx,两个tomcat下各部署了一个应用,在第一应用下登录后,第二个也会登录。
实例下载地址:http://pan.baidu.com/s/1jHnE1vC