引用:http://melin.iteye.com/blog/701652
項目需要統計在線用戶數量,系統部署在集群環境下,使用會話粘貼的方式解決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 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);
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());
}
}
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());
}
}