改造tomcat6.x支持SNA(一)实践

本文介绍如何通过自定义Tomcat的StandardManager和StandardSession类实现跨Tomcat实例的会话复制(SNA),并提供了MemcachedManager和MemcachedSession的具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

改造tomcat6.x支持SNA(一)实践

参考BLOG
http://www.iteye.com/topic/81641

tomcat StandardManager API文档
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/session/StandardManager.html

tomcat StandardSession API文档
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:
package com.sillycat.easytomcatplugin.sna;
import java.io.IOException;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Session;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.session.StandardSession;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
public class MemcachedManager extends StandardManager {
// memcached客户端
protected MemCachedClient mc = null;
// Sock池
protected SockIOPool pool = null;
protected String sockPoolName = "snasessionsock";
// 服务器队列
protected String serverlist = "127.0.0.1:11211";
protected String snaidPrefix = "snaid";
protected String snaidFlag = "true";
public MemcachedManager() {
super();
}
// 重写父类findSession方法,将snaidPrefix加入到SESSIONID中当前缀,先试图从memcached中取出session
public Session findSession(String id) throws IOException {
Session session = super.findSession(id);
if (session == null && id != null) {
try {
Object sid = mc.get(this.getSnaidPrefix() + id);
if (sid != null) {
session = createSession(id);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return session;
}
// 创建session,并初始化进memcached
public Session createSession(String sessionId) {
Session session = super.createSession(sessionId);
mc.set(this.getSnaidPrefix() + session.getId(), session);
return session;
}
// 创建session
protected StandardSession getNewSession() {
return new MemcachedSession(this, mc);
}
protected void initPool() {
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 (Exception ex) {
log.error("error:", ex);
}
}
} catch (Exception ex) {
log.error("error:", ex);
}
if (mc == null) {
mc = new MemCachedClient();
// mc.setPoolName(sockPoolName);
mc.setCompressEnable(false);
mc.setCompressThreshold(0);
}
}
protected void closePool() {
if (mc != null) {
try {
} catch (Exception ex) {
log.error("error:", ex);
}
mc = null;
}
if (pool != null) {
try {
pool.shutDown();
} catch (Exception ex) {
log.error("error:", ex);
}
}
}
public String getSockPoolName() {
return sockPoolName;
}
public String getServerlist() {
return serverlist;
}
public String getSnaidPrefix() {
return snaidPrefix;
}
public String getSnaidFlag() {
return snaidFlag;
}
public void setSockPoolName(String sockPoolName) {
this.sockPoolName = sockPoolName;
}
public void setServerlist(String serverlist) {
this.serverlist = serverlist;
}
public void setSnaidPrefix(String snaidPrefix) {
this.snaidPrefix = snaidPrefix;
}
public void setSnaidFlag(String snaidFlag) {
this.snaidFlag = snaidFlag;
}
protected String generateSessionId() {
if (this.getJvmRoute() != null) {
return java.util.UUID.randomUUID().toString() + '.'
+ this.getJvmRoute();
}
return java.util.UUID.randomUUID().toString();
}
// 启动
public void start() throws LifecycleException {
this.setPathname(""); // must disable session persistence across Tomcat
// restarts
super.start();
this.initPool();
}
// 停止
public void stop() throws LifecycleException {
super.stop();
this.closePool();
}
}

类MemcachedSession.java如下:
package com.sillycat.easytomcatplugin.sna;
import org.apache.catalina.Manager;
import org.apache.catalina.session.StandardSession;
import com.danga.MemCached.MemCachedClient;
public class MemcachedSession extends StandardSession {
private static final long serialVersionUID = -3520419866432555766L;
protected transient MemCachedClient mc = null;
//构造器
public MemcachedSession(Manager manager, MemCachedClient mc) {
super(manager);
this.mc = mc;
}
//得到属性
public Object getAttribute(String name) {
Object obj = super.getAttribute(name);
if (obj != null && !(obj instanceof java.io.Serializable)) {
return obj;
}
String key = name + this.getId();
obj = mc.get(key);
return obj;
}
//设置属性
public void setAttribute(String name, Object value) {
removeAttribute(name);
super.setAttribute(name, value);
if (value != null && value instanceof java.io.Serializable) {
String key = name + this.getId();
mc.set(key, value);
}
}
//删除属性
protected void removeAttributeInternal(String name, boolean notify) {
super.removeAttributeInternal(name, notify);
String key = name + this.getId();
mc.delete(key);
}
//超时过期
public void expire(boolean notify) {
mc.delete(((MemcachedManager) manager).getSnaidPrefix() + this.getId());
super.expire(notify);
}
}
我是部署在两个tomcat上的,分别是tomcat1和tomcat2,修改conf下面的context.xml配置文件如下:
<Manager className="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来做代理,配置的是循环访问模式:
backend logon_server
mode http
option httpchk GET /easylogon/ping.jsp
server app1 127.0.0.1:8080 weight 3 check
server app2 127.0.0.1:8081 weight 3 check
backend static_server
mode http
option httpchk GET /easystatic/ping.jsp
server app3 127.0.0.1:8080 weight 3 check
server app4 127.0.0.1:8081 weight 3 check
经过测试,虽然登陆访问后,server在tomcat1和tomcat2上不断切换,但是session中的数据可以很好的SNA。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值