改造tomcat6.x支持SNA(一)实践
改造tomcat6.x支持SNA(一)实践
参考BLOG
tomcatStandardManagerAPI文档
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/session/StandardManager.html
tomcatStandardSessionAPI文档
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/session/StandardSession.html
下载老版本的TOMCAT(tomcat3-5)
http://archive.apache.org/dist/jakarta/
tomcat6.x下载
http://tomcat.apache.org/download-60.cgi
先参考网上资料,实现TOMCAT的扩展,其中比较核心的两个类StandardManager和StandardSession,代码清单如下:
MemcachedManager.java:
packagecom.sillycat.easytomcatplugin.sna;
importjava.io.IOException;
importorg.apache.catalina.LifecycleException;
importorg.apache.catalina.Session;
importorg.apache.catalina.session.StandardManager;
importorg.apache.catalina.session.StandardSession;
importcom.danga.MemCached.MemCachedClient;
importcom.danga.MemCached.SockIOPool;
publicclassMemcachedManagerextendsStandardManager{
//memcached客户端
protectedMemCachedClientmc=null;
//Sock池
protectedSockIOPoolpool=null;
protectedStringsockPoolname="snasessionsock";
//服务器队列
protectedStringserverlist="127.0.0.1:11211";
protectedStringsnaidPrefix="snaid";
protectedStringsnaidFlag="true";
publicMemcachedManager(){
super();
}
//重写父类findSession方法,将snaidPrefix加入到SESSIONID中当前缀,先试图从memcached中取出session
publicSessionfindSession(Stringid)throwsIOException{
Sessionsession=super.findSession(id);
if(session==null&&id!=null){
try{
Objectsid=mc.get(this.getSnaidPrefix()+id);
if(sid!=null){
session=createSession(id);
}
}catch(Exceptionex){
ex.printStackTrace();
}
}
returnsession;
}
//创建session,并初始化进memcached
publicSessioncreateSession(StringsessionId){
Sessionsession=super.createSession(sessionId);
mc.set(this.getSnaidPrefix()+session.getId(),session);
returnsession;
}
//创建session
protectedStandardSessiongetNewSession(){
returnnewMemcachedSession(this,mc);
}
protectedvoidinitPool(){
try{
if(pool==null){
try{
pool=SockIOPool.getInstance(sockPoolName);
pool.setServers(serverlist.split(","));
pool.setInitConn(5);
pool.setMinConn(5);
pool.setMaxConn(50);
pool.setMaintSleep(30);
pool.setNagle(false);
pool.initialize();
}catch(Exceptionex){
log.error("error:",ex);
}
}
}catch(Exceptionex){
log.error("error:",ex);
}
if(mc==null){
mc=newMemCachedClient();
//mc.setPoolName(sockPoolName);
mc.setCompressEnable(false);
mc.setCompressThreshold(0);
}
}
protectedvoidclosePool(){
if(mc!=null){
try{
}catch(Exceptionex){
log.error("error:",ex);
}
mc=null;
}
if(pool!=null){
try{
pool.shutDown();
}catch(Exceptionex){
log.error("error:",ex);
}
}
}
publicStringgetSockPoolName(){
returnsockPoolName;
}
publicStringgetServerlist(){
returnserverlist;
}
publicStringgetSnaidPrefix(){
returnsnaidPrefix;
}
publicStringgetSnaidFlag(){
returnsnaidFlag;
}
publicvoidsetSockPoolName(StringsockPoolName){
this.sockPoolName=sockPoolName;
}
publicvoidsetServerlist(Stringserverlist){
this.serverlist=serverlist;
}
publicvoidsetSnaidPrefix(StringsnaidPrefix){
this.snaidPrefix=snaidPrefix;
}
publicvoidsetSnaidFlag(StringsnaidFlag){
this.snaidFlag=snaidFlag;
}
protectedStringgenerateSessionId(){
if(this.getJvmRoute()!=null){
returnjava.util.UUID.randomUUID().toString()+'.'
+this.getJvmRoute();
}
returnjava.util.UUID.randomUUID().toString();
}
//启动
publicvoidstart()throwsLifecycleException{
this.setPathname("");//mustdisablesessionpersistenceacrossTomcat
//restarts
super.start();
this.initPool();
}
//停止
publicvoidstop()throwsLifecycleException{
super.stop();
this.closePool();
}
}
类MemcachedSession.java如下:
packagecom.sillycat.easytomcatplugin.sna;
importorg.apache.catalina.Manager;
importorg.apache.catalina.session.StandardSession;
importcom.danga.MemCached.MemCachedClient;
publicclassMemcachedSessionextendsStandardSession{
privatestaticfinallongserialVersionUID=-3520419866432555766L;
protectedtransientMemCachedClientmc=null;
//构造器
publicMemcachedSession(Managermanager,MemCachedClientmc){
super(manager);
this.mc=mc;
}
//得到属性
publicObjectgetAttribute(Stringname){
Objectobj=super.getAttribute(name);
if(obj!=null&&!(objinstanceofjava.io.Serializable)){
returnobj;
}
Stringkey=name+this.getId();
obj=mc.get(key);
returnobj;
}
//设置属性
publicvoidsetAttribute(Stringname,Objectvalue){
removeAttribute(name);
super.setAttribute(name,value);
if(value!=null&&valueinstanceofjava.io.Serializable){
Stringkey=name+this.getId();
mc.set(key,value);
}
}
//删除属性
protectedvoidremoveAttributeInternal(Stringname,booleannotify){
super.removeAttributeInternal(name,notify);
Stringkey=name+this.getId();
mc.delete(key);
}
//超时过期
publicvoidexpire(booleannotify){
mc.delete(((MemcachedManager)manager).getSnaidPrefix()+this.getId());
super.expire(notify);
}
}
我是部署在两个tomcat上的,分别是tomcat1和tomcat2,修改conf下面的context.xml配置文件如下:
<Managerclassname="com.sillycat.easytomcatplugin.sna.MemcachedManager"
serverlist="127.0.0.1:11211"snaidPrefix="snaid"snaidFlag="true">
</Manager>
其中的serverlist以,号分隔不同的server,另外这个snaidPrefix在不同的tomcat上要写成snaid1,snaid2;最后这个snaidFlag虽然有标示,应该是一个使能,但是程序明显没有使用。
另外要将两个memcached用到的jar包拷贝到tomcat/lib中,分别是:
log4j-1.2.15.jar
memcached-2.0.1.jar
另外就是我们写的这两个类:
easytomcatplugin-1.0.jar
在redhat上,我是使用的haproxy来做代理,配置的是循环访问模式:
backendlogon_server
modehttp
optionhttpchkGET/easylogon/ping.jsp
serverapp1127.0.0.1:8080weight3check
serverapp2127.0.0.1:8081weight3check
backendstatic_server
modehttp
optionhttpchkGET/easystatic/ping.jsp
serverapp3127.0.0.1:8080weight3check
serverapp4127.0.0.1:8081weight3check
经过测试,虽然登陆访问后,server在tomcat1和tomcat2上不断切换,但是session中的数据可以很好的SNA。