使用Memcached实现集群间session共享

java集群中session共享有多种方案,比如可以使用tomcat的session复制的功能来实现集群session共享,但这样做的缺点也很明显,每台服务器上都需要存相同的session,性能随着服务器增加急剧下降,而且容易引起广播风暴。

最近学习了使用Memcached缓存服务器实现session集群共享,下面是学习笔记:


在开发阶段可以使用原生的本地session,在项目上线时再全部切换成远程session。


为了完成这个功能,可以先定义一个SessionProvider接口,项目中有关session的操作都通过调用这个接口的方法来实现。当在开发阶段时,使用实现SessionProvider接口的HttpSessionProvider类实现项目中有关session的操作,当项目上线时,把spring中配置的HttpSessionProvider换成使用Memcached api的CacheSessionProvider类,这样项目中注入的SessionProvider就是CacheSessionProvider了。


①首先是session供应接口:

public interface SessionProvider {

	//往Session设置值
	public void setAttribute(HttpServletRequest request,HttpServletResponse response, String name,Serializable value);
	
	//从Session中取值
	public Serializable getAttribute(HttpServletRequest request,HttpServletResponse response,String name);
	
	//退出登陆
	public void logout(HttpServletRequest request,HttpServletResponse response);
	
	//获取SessionID
	public String getSessionId(HttpServletRequest request,HttpServletResponse response);
}
②本地session实现类:

其中,request.getSession()方法默认参数为true,意思就是如果cookie中有JsessionId就去request中找,找到则使用,如果找不到就新建一个session。

因此request.getSession(false);的意思就是只找老的session,如果此JessionId没有对应的session,也不创建新的,返回null值。

public class HttpSessionProvider implements SessionProvider{

	@Override
	public void setAttribute(HttpServletRequest request,HttpServletResponse response, String name,
			Serializable value) {
		HttpSession session = request.getSession();
		session.setAttribute(name, value);
	}

	@Override
	public Serializable getAttribute(HttpServletRequest request,HttpServletResponse response, String name) {
		HttpSession session = request.getSession(false);
		if(session != null){
			return (Serializable) session.getAttribute(name);
		}
		return null;
	}

	@Override
	public void logout(HttpServletRequest request,HttpServletResponse response) {
		HttpSession session = request.getSession(false);
		if(session != null){
			session.invalidate();
		}
		//Cookie JSESSIONID 
		
	}

	@Override
	public String getSessionId(HttpServletRequest request,HttpServletResponse response) {
		return request.getSession().getId();
	}

}
在Spring的配置文件里配置:


③存放在Memcached缓存服务器中的session功能实现类:
public class CacheSessionProvider implements SessionProvider{
	@Autowired
	private MemCachedClient memCachedClient;
	private int expiry = 30;//分钟,这里有个参数可以在spring配置文件里进行缓存时间修改
	private static final String  JSESSIONID = "JSESSIONID";
	
	//放值
	@Override
	public void setAttribute(HttpServletRequest request,HttpServletResponse response, String name,
			Serializable value) {
		Map session = new HashMap();
		session.put(name, value);
		//保存远程了
		//这种自定义map代替session的方式不会自动生成jsessionid,所以需要调用下面的getSessionId方法
		memCachedClient.set(getSessionId(request,response), session, expiry*60);
	}

	//取值
	@SuppressWarnings("unchecked")
	@Override
	public Serializable getAttribute(HttpServletRequest request,HttpServletResponse response, String name) {
		Map session = (Map) memCachedClient.get(getSessionId(request,response));
		if(null != session){
			return session.get(name);
		}
		return null;
	}

	@Override
	public void logout(HttpServletRequest request,HttpServletResponse response) {
		// TODO Auto-generated method stub
		if(memCachedClient.keyExists(getSessionId(request, response))){
			memCachedClient.delete(getSessionId(request, response));
		}
	}

	@Override
	public String getSessionId(HttpServletRequest request,HttpServletResponse response) {
		//所有的Cookie
		Cookie[] cookies = request.getCookies();
		if(null != cookies && cookies.length > 0){
			for(Cookie c : cookies){
				if(JSESSIONID.equals(c.getName())){
					return c.getValue();
				}
			}
		}
		//生成一个
		String sessionId = UUID.randomUUID().toString().replaceAll("-", "");
		Cookie cookie = new Cookie(JSESSIONID,sessionId);
		cookie.setMaxAge(-1);
		cookie.setPath("/");
		response.addCookie(cookie);
		return sessionId;
	}

	public void setExpiry(int expiry) {
		this.expiry = expiry;
	}
	

}
然后 在Spring的配置文件里更改配置:
	
	
	
		
	





你可能感兴趣的:(JavaWeb)