做者: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