采用Memcached实现分布式Session
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號(hào):朱小廝的博客。
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/backend/distributed-session-with-memcached/
?memcached-session-manager是一個(gè)開(kāi)源的高可用的Tomcat session共享解決方案,它支持Sticky模式和Non-Sticky模式。Sticky模式表示每次請(qǐng)求都會(huì)被映射到同一臺(tái)后端Web服務(wù)器,知道該Web服務(wù)器宕機(jī),這樣session可先存放在服務(wù)器本地,等到請(qǐng)求處理完成再同步到后端memcached服務(wù)器;而當(dāng)Web服務(wù)器宕機(jī)時(shí),請(qǐng)求被映射到其他Web服務(wù)器,這時(shí)候,其他Web服務(wù)器可以從后端memcache中恢復(fù)session。對(duì)于Non-Sticky模式來(lái)說(shuō),請(qǐng)求每次映射的后端Web服務(wù)器是不確定的,當(dāng)請(qǐng)求到來(lái)時(shí),從memcached中加載session;當(dāng)請(qǐng)求處理完成時(shí),將session再協(xié)會(huì)到memcached。
?以Non-Sticky模式為例,首先需要安裝memcached的服務(wù)器,這個(gè)在上一篇中已經(jīng)講述過(guò)了。然后在Tomcat的$CATALINA_HOME/conf/context.xml文件配置SessionManager,具體配置如下:
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:10.10.195.112:11211" sticky="false" sessionBackupAsync="false" sessionBackupTimeout="1000"lockingMode="auto" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" />?其中,memcachedNodes指定了memcached的節(jié)點(diǎn);sticky表示是否采用sticky模式;sessionBackuoAsync表示是否采用異步方式備份session;lockingMode表示session的鎖定模式;auto表示對(duì)于只讀請(qǐng)求,session將不會(huì)被鎖定,如果包含寫(xiě)入請(qǐng)求,則session會(huì)被鎖定;requestUriIgnorePattern表示忽略的url; transcoderFactoryClass用來(lái)指定序列化的方式,這里采用的是Kryo序列化,也是memcached-session-manager比較推薦的一種序列化方式。也可以采用其他序列化方式,譬如:javolution-serializer, xstream-serializer, flexjson-serializer。
?memcached-session-manager依賴(lài)于memcached-session-manager-{version}.jar,如果使用的是tomcat6,則還需要下載memcached-session-manager-tc6-{version}.jar,如果是tomcat7則采用memcached-session-manager-tc7-{version}.jar的包(博主采用的是tomcat7+jdk7)。還需要spymemcached-2.7.3.jar,在啟動(dòng)tomcat之前需要將這些jar包放到tomcat的lib目錄下。如果采用Kryo方式序列化,還需要加入其他一些包,所有包如下:
注意這些包的版本,搞錯(cuò)一下就不能實(shí)現(xiàn)其功能。這里博主已經(jīng)整理好了,可以在這里下載。
##常見(jiàn)錯(cuò)誤
1 啟動(dòng)tomcat出現(xiàn)錯(cuò)誤案例1
這個(gè)是包版本問(wèn)題,memcached-session-manager以及msm-kryo-serializer版本不對(duì)。
2 啟動(dòng)tomcat出現(xiàn)錯(cuò)誤案例2
嚴(yán)重: Error manager.start() org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[]]at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5501)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1245)at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1895)at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)at java.util.concurrent.FutureTask.run(Unknown Source)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) Caused by: java.lang.NoSuchMethodError: de.javakaffee.web.msm.MemcachedSessionService$SessionManager.getContainerClassLoader()Ljava/lang/ClassLoader;at de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory.createTranscoder(KryoTranscoderFactory.java:47)at de.javakaffee.web.msm.MemcachedSessionService.createTranscoderService(MemcachedSessionService.java:449)at de.javakaffee.web.msm.MemcachedSessionService.startInternal(MemcachedSessionService.java:425)at de.javakaffee.web.msm.MemcachedBackupSessionManager.startInternal(MemcachedBackupSessionManager.java:509)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)... 12 more這個(gè)也是包版本問(wèn)題,msm-kryo-serializer版本不對(duì)
3 在context.xml中配置failoverNodes節(jié)點(diǎn),如下
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:10.10.195.112:11211" sticky="false" failoverNodes="n1"sessionBackupAsync="false" lockingMode="auto" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" />啟動(dòng)tomcat報(bào)錯(cuò):
嚴(yán)重: Error manager.start() org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[/Architecture]]at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5501)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:672)at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1859)at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)at java.util.concurrent.FutureTask.run(Unknown Source)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) Caused by: java.lang.IllegalArgumentException: For a single memcached node there should/must no failoverNodes be specified.at de.javakaffee.web.msm.MemcachedNodesManager.createFor(MemcachedNodesManager.java:224)at de.javakaffee.web.msm.MemcachedSessionService.createMemcachedNodesManager(MemcachedSessionService.java:445)at de.javakaffee.web.msm.MemcachedSessionService.startInternal(MemcachedSessionService.java:410)at de.javakaffee.web.msm.MemcachedBackupSessionManager.startInternal(MemcachedBackupSessionManager.java:509)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)... 12 more可以看到報(bào)錯(cuò)中“Caused by: java.lang.IllegalArgumentException: For a single memcached node there should/must no failoverNodes be specified.”這句,需要把failoverNodes去掉。
##應(yīng)用舉例
?這里博主采用keepalived+lvs進(jìn)行負(fù)載均衡搭建。詳細(xì)可以參考LVS+Keepalived實(shí)現(xiàn)負(fù)載均衡和雙機(jī)熱備,不了解也沒(méi)關(guān)系,這個(gè)不是本篇的重點(diǎn)。
?(配的是雙機(jī)熱備+負(fù)載均衡,主備機(jī)會(huì)虛擬出一個(gè)訪(fǎng)問(wèn)的ip,當(dāng)主機(jī)宕機(jī)時(shí),會(huì)自動(dòng)切換到備機(jī),對(duì)于用戶(hù)而言完全透明。了解即可)
?在主備機(jī)web路徑的根目錄下放入test.jsp,代碼如下(備機(jī)的就把 10.10.195.107換成10.10.195.187):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <%@ page session="true" %> <%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Memcached-session-manager</title> </head> <body >10.10.195.107<%out.print("<br> SESSION-ID:"+session.getId()+"<br>");%> </body> </html>通過(guò)瀏覽器訪(fǎng)問(wèn):http://10.10.195.188:8080/test.jsp
可以看到頁(yè)面顯示:
在主機(jī)中輸入: sudo service keepalived stop之后(切換到備機(jī)),頁(yè)面顯示:
10.10.195.187 SESSION-ID:6F9B1255A1C9E3F7D5FC144DD81217CD-n1可以看到訪(fǎng)問(wèn)的頁(yè)面變了,但是session并沒(méi)有改變,因?yàn)樗嬖趍emcached服務(wù)器中。
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/backend/distributed-session-with-memcached/
參考資料:
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號(hào):朱小廝的博客。
總結(jié)
以上是生活随笔為你收集整理的采用Memcached实现分布式Session的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Memcached安装与配置
- 下一篇: Jedis对redis的操作详解