项目需要统计在线用户数量,系统部署在集群环境下,使用会话粘贴的方式解决Session问题。要想得到真实在线用户数,必须是所有节点的总和。
这里考虑使用memcached存放用户登录数据,key为userid统计在线用户数据,只需要统计key的总数。memcached因为性能的缘故,
没有提供遍历整个缓存当中对象的功能,不过memcached也提供了很多命令来监控memcached的状态,例如stats命令就有:
使用命令【stats items】查询查询到所有的slab,再使用命令【cachedump 1 0】命令找出所有的Key信息。但过期的key也会被查询出来,所以需要对all keys执行一遍查询,过滤掉过期的key。也可以通过【cachedump 1 0】命令查询出来的key过期时间与当前时间进行比较。判断是否过期。这里的过期时间为session.getMaxInactiveInterval()的值。
接下来说说,用户信息怎么放入memcached中。主要利用HttpSessionListener和HttpSessionAttributeListener来监听对Session的操作。
不多写了,贴上代码就很清楚了:
这里考虑使用memcached存放用户登录数据,key为userid统计在线用户数据,只需要统计key的总数。memcached因为性能的缘故,
没有提供遍历整个缓存当中对象的功能,不过memcached也提供了很多命令来监控memcached的状态,例如stats命令就有:
stats
stats reset
stats malloc
stats maps
stats sizes
stats slabs
stats items
stats cachedump slab_id limit_num
stats detail [on|off|dump]
使用命令【stats items】查询查询到所有的slab,再使用命令【cachedump 1 0】命令找出所有的Key信息。但过期的key也会被查询出来,所以需要对all keys执行一遍查询,过滤掉过期的key。也可以通过【cachedump 1 0】命令查询出来的key过期时间与当前时间进行比较。判断是否过期。这里的过期时间为session.getMaxInactiveInterval()的值。
Iterator<Map<String, String>> iterSlabs = client.getStats("items").values().iterator();
Set<String> set = new HashSet<String>();
while(iterSlabs.hasNext()) {
Map<String, String> slab = iterSlabs.next();
for(String key : slab.keySet()) {
String index = key.split(":")[1];
set.add(index);
}
}
//统计
List<String> list = new LinkedList<String>();
for(String v : set) {
String commond = "cachedump ".concat(v).concat(" 0");
Iterator<Map<String, String>> iterItems = client.getStats(commond).values().iterator();
while(iterItems.hasNext()) {
Map<String, String> items = iterItems.next();
list.addAll(items.keySet());
}
}
return client.getBulk(list);
接下来说说,用户信息怎么放入memcached中。主要利用HttpSessionListener和HttpSessionAttributeListener来监听对Session的操作。
不多写了,贴上代码就很清楚了:
HttpSessionAttributeListener:
public void attributeReplaced(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
if(SESSION_KEY.endsWith(event.getName())) {
MemcachedClient client = (MemcachedClient)SpringBeanHolder.getBean(MEMCACEHD_BEAN_NAME);
SessionContext context = (SessionContext)session.getAttribute(SESSION_KEY);
String username = "";
try {
username = context.getDocument().getElementsByTagName("operatorName").item(0).getFirstChild().getNodeValue();
String json = "{username: '"+username+"'}";
client.set(context.getUserID(), session.getMaxInactiveInterval(), json);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class UserSessionListener implements HttpSessionListener {
private static final String SESSION_KEY = "sessionContext";
private static final String MEMCACEHD_BEAN_NAME = "memcachedClient";
public void sessionCreated(HttpSessionEvent event) {
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
MemcachedClient client = (MemcachedClient)SpringBeanHolder.getBean(MEMCACEHD_BEAN_NAME);
SessionContext context = (SessionContext)session.getAttribute(SESSION_KEY);
System.out.println("【Destroy Session】 User:"+context.getUserID());
//删除对应用户在memcached的数据
client.delete(context.getUserID());
}
}