在多用户系统中SESSION管理是非常耗费服务器资源的一件事情,当用户达到100万时系统所承受的压力是巨大的,一个有100万用户信息的MAP表在内存里面,怎么来解决这一问题了,在当前对于大系统应用如果SNS社区,论坛,或者是移动互联网中的交友工具,服务器都不会使用原始的由容器来生成的SESSION管理用户信息,有很多实际上根本就不会用到SESSION,而直接使用COOKIE或者是客户端上的本地缓存数据库来管理用户信息,但对于安全度要求比较高的系统,这种方式就显得很不安全了,那么怎么来保存管理庞大的用户信息了,方法1就是用NOSQL数据库来模拟SESSION,在NODEJS里就是用MONGODB来模拟SESSION,方法2就是用分布式缓存在模拟SESSION,在这里我就给出一个以分布式缓存来实现SESSION的案例。
package com.session;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cached.SpyMemcachedServer;
import com.cached.SpyMemcachedManager;
import com.listener.SessionListener;
public class Session {
private SpyMemcachedManager manager = null;
//过期时间为-1时不过期
private long maxInactiveInterval = -1;
//活动时间
private long activitiTime = 0;
//sessionID
private String sessionId;
//事件句柄
private SessionListener listener = null;
public Session() {
try {
String[][] servs = new String[][] {
{ "localhost", "11211" },
// {"localhost", "11212"}
};
List<SpyMemcachedServer> servers = new ArrayList<SpyMemcachedServer>();
for (int i = 0; i < servs.length; i++) {
SpyMemcachedServer server = new SpyMemcachedServer();
server.setIp(servs[i][0]);
server.setPort(Integer.parseInt(servs[i][1]));
servers.add(server);
}
manager = new SpyMemcachedManager(servers);
manager.connect();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 介绍:SESSION初始化建立如果没有MAP创建后放入缓存中
* 参数:STRING:SESSIONID
**/
public void init(String sessionId) {
this.sessionId = sessionId;
Map<String, Object> sessionValue = (Map<String, Object>) manager.get(sessionId);
if(sessionValue == null) {
sessionValue = new HashMap<String, Object>();
//事件不为空时调用
if(listener != null) {
//创建SESSION
listener.sessionCreated(this);
}
}
manager.set(sessionId, sessionValue, 3000);
this.activitiTime = System.currentTimeMillis();
}
/**
* 介绍:装入值
* 参数:STRING:KEY OBJECT:VALUE
**/
public void setAttribute(String key, Object value) {
Map<String, Object> sessionValue = (Map<String, Object>) manager.get(this.sessionId);
sessionValue.put(key, value);
manager.set(sessionId, sessionValue, 3000);
}
/**
* 介绍:获取值
* 参数:STRING:KEY
**/
public Object getAttribute(String key) {
Map<String, Object> sessionValue = (Map<String, Object>) manager.get(this.sessionId);
return sessionValue.get(key);
}
/**
* 介绍:删除指定的值
* 参数:STRING:KEY
**/
public void removeSession(String key) {
Map<String, Object> sessionValue = (Map<String, Object>) manager.get(this.sessionId);
sessionValue.remove(key);
manager.set(sessionId, sessionValue, 3000);
}
/**
* 介绍:清除所有的值
* 参数:无
**/
public void clearSession() {
Map<String, Object> sessionValue = (Map<String, Object>) manager.get(this.sessionId);
sessionValue.clear();
sessionValue = null;
manager.set(sessionId, sessionValue, 3000);
}
/**
* 介绍:销毁SESSION
* 参数:无
**/
public void sessionDestroy() {
if(listener != null) {
//销毁SESSION
listener.sessionDestroyed(this);
}
manager.delete(sessionId);
}
public long getActivitiTime() {
return activitiTime;
}
public void setActivitiTime(long activitiTime) {
this.activitiTime = activitiTime;
}
public void setMaxInactiveInterval(long maxInactiveInterval) {
this.maxInactiveInterval = maxInactiveInterval;
}
public long getMaxInactiveInterval() {
return this.maxInactiveInterval;
}
public String getSessionId() {
return sessionId;
}
public void addSessionListener(SessionListener listener) {
this.listener = listener;
}
public SessionListener getListener() {
return listener;
}
}
SESSION实现代码
package com.session;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SessionManager {
private static Map<String, Session> sessionMap = new ConcurrentHashMap<String, Session>();
private static ExecutorService exs = null;
static {
exs = Executors.newSingleThreadExecutor();
exs.execute(new Runnable() {
@Override
public void run() {
while(!Thread.interrupted()) {
System.out.println("clear time out");
List<String> clearList = new ArrayList<String>();
for(String sessionId : sessionMap.keySet()) {
Session session = sessionMap.get(sessionId);
if(session.getMaxInactiveInterval() != -1) {
long currentTime = System.currentTimeMillis();
long activitiTime = session.getActivitiTime();
//SESSION过期时清除
if((currentTime - activitiTime) >= session.getMaxInactiveInterval()) {
session.sessionDestroy();
//记录清除的ID
clearList.add(sessionId);
}
}
}
for(String sessionId : clearList) {
//清除MAP信息
sessionMap.remove(sessionId);
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
});
}
/**
* 介绍:通过系统本生的SESSIONID来创建分布式内存SESSION
* 参数:STRING:SESSION
**/
public static Session getSession(String sessionId){
//每个SESSIONID创建一个实例
Session session = sessionMap.get(sessionId);
if(session == null) {
session = new Session();
session.init(sessionId);
sessionMap.put(sessionId, session);
}
return session;
}
public static void main(String[] args) {
SessionManager.getSession("xxxx");
}
}
管理SESSION
package com.listener;
import com.session.Session;
public interface SessionListener {
public void sessionCreated(Session session);
public void sessionDestroyed(Session session);
}
事件接口
以上代码只是对工作中所开发的代码进行了简化,对于安全级别要求更高的系统该代码还有很多不足的地方,但是对于一般的应用如SNS社区或者是开发手机的应用,可以直接使用,能很好的支撑平台,该SESSION可以用于SERVLET,SPRING MVC(和SPRING系统集成需要做一些修改以符合SPRING的配置需要),STRUTS2。
源码下载地址
https://github.com/reaganjava/session.git
源码下载地址
https://github.com/reaganjava/session.git