最近重点关注了memcached和cookie的相关技术,这些技术在web开发中使用的相当频繁,alibaba也不例外。
cookie的场景:由于http协议本身是无状态的,两次http请求毫无关联,总不能每次登录都让用户重新输入用户名和密码,重新验证一次,也许很多人说可以在服务端建立sesseion,的确这是一个不错的选择,session具有独享性,存储的是单个用户的信息,每个浏览器的多次请求都会维护服务端的一个session。但是服务端有如此多的session,怎样将其与请求匹配?这时cookie里面的jsessionid便发挥了作用,通过sessionid可以唯一的区分服务端的session信息。
当然cookie的作用可远不止这个,cookie更多的是在客户端存储用户的信息,每次会随着客户端请求发送到服务器端,使用场景如“自动登录”等
memcached的场景:缓存的作用位置是在内存,虽然大多数数据是存储在数据库、文件系统等,单次读取的速率差异并不是特别明显(让用户无法接受),但是如果面对多用户访问,如此多的并发请求,基数一大,差异便会特别明显。解决这种问题的最好方式便是借助缓存,将大量的跨表甚至跨库的记录整合封装,临时存于内存中,下次使用时可直接读取,大大提高了数据的交互速率。
结合这两种技术,写了一个demo应用,领域下缓存的神奇。
结构类图:
表单提交时
读取服务端创建的session的sessionid
// 组建sessionId
String sid = request.getSession().getId() + "_" + Constants.serverName + "_" + person.getUserId();
存储cookie信息,其中的value是组建的sessionid
RequestUtils.setCookie(request, response, Constants.session_key_flag_of_cookie, sid, 30 * 60);
/**
* 设置COOKIE
* @param request
* @param response
* @param name
* @param value
* @param maxAge
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String name,
String value, int maxAge)
{
Cookie cookie = new Cookie(name, value);
cookie.setMaxAge(maxAge);
if(cookieDomain!=null && cookieDomain.indexOf('.')!=-1)
{
cookie.setDomain('.' + cookieDomain);
}
cookie.setPath(cookiePath);
response.addCookie(cookie);
}
缓存中放入的是一个map对象,该对象封装当前的session会话的key-value键值对
session的服务类,里面会初始化memcached的客户端
private SessionService()
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream input = cl.getResourceAsStream("memcached.properties");
Properties props = new Properties();
String serverlist = "127.0.0.1:11211";
try
{
props.load(input);
serverlist = props.getProperty("serverlist", "127.0.0.1:11211");
poolName = props.getProperty("poolname", "sidsock");
}
catch (Exception e)
{
e.printStackTrace();
}
String[] servers = serverlist.split(",");
pool = SockIOPool.getInstance(poolName);
pool.setServers(servers);
pool.setFailover(true);
pool.setInitConn(10);
pool.setMinConn(5);
pool.setMaxConn(250);
pool.setMaintSleep(30);
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setAliveCheck(true);
pool.initialize();
}
缓存信息的存操作
public void saveSession(String id, Map session)
{
MemCachedClient mc = this.getMemCachedClient();
if(mc.keyExists(id))
{
mc.replace(id, session,getExpiryDate());
}
else
{
mc.add(id, session,getExpiryDate());
}
}
memcached的取数据操作
public Map getSession(String id,boolean create)
{
MemCachedClient mc = this.getMemCachedClient();
Map session = (Map) mc.get(id);
if(session == null)
{
if(create)
{
session = new HashMap(5);
mc.add(id, session,getExpiryDate());
}
}
return session;
}
返回值是一个map对象,会封装到MemSession对象的map 全局变量中,供后面的操作使用
public class MemSession
{
//session会话 ID
private String sid = "";
//存放本会话的所有信息
private Map map = null;
public static MemSession getSession(String sid)
{
MemSession session = null;
session = new MemSession(sid,true);
return session;
}
补充:关于一个web工程的创建 及启动, http://hi.baidu.com/paper369/blog/item/afae7939886d7d38b9998f46.html
代码地址:https://mymemcached-cookie.googlecode.com/svn/trunk/