Tomcat集群下获取memcached缓存对象数量,统计在线用户数据量
项目需要统计在线用户数量,系统部署在集群环境下,使用会话粘贴的方式解决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()); } }