Session详解及集群共享

Session的介绍

  • *:会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制,session在网络协议(例如telnet或FTP)中是非常重要的部分
  • 存储位置: 服务器内存(重点),区别客户端中的Cookie
  • 如何产生: web容器根据session机制实现
  • Tomcat路径 实现类是Apache Tomcat库下的catalina.jar里面的org.apache.catalina.session包下的StandardSession,对外接口是javax.servlet.http下的HttpSession
  • 设计模式: 外观模式

历史背景:(随便看看)

早期的web应用或者说早期的网站都是一种处理静态资源的网站,功能主要是查看文档,看看图片,而现在的web应用和早期的差别已经很大,互联网的网站更准确的定义应该是互联网软件即网站就是软件,网站所代表的软件和早期软件的定义是不一样的,早期的软件都是在单机环境下运行,而互联网的普及让软件和网络技术融合在一起,这就要求网站所代表的软件应该要有一个对事务处理的记忆功能,事务处理的记忆功能就是我们常说的要有状态。而实现web应用技术的核心http协议是一个无状态的协议,http这种设计也许是历史遗留问题,也许无状态的http是最简单也是最有效的通讯方式,但是当网站成为软件后,状态的保持就是一个很重要的功能。因此在web应用开发里就出现了保持http链接状态的技术:一个是cookie技术,另一种是session技术。



cookie技术是客户端的解决方案(当然随着html5的出现,比cookie更为强劲和安全的技术出现了,但是鉴于html5的普及度不够,就不做本文讨论的内容了),Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings[用户名]\Cookies目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。session技术则是服务端的解决方案,它是通过服务器来保持状态的。

这里明确一下Session的含义。首先,我们通常都会把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称。要使用Session,第一步当然是创建Session了。

Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id(SessionId由你的IP决定,应该是=^=),而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session(所以你代码里向session存"user",不同PC用户访问执行,并不会覆盖),从而再次使用之。用户的状态也就得以保持了。

集群中的Session问题及参考方案 (有错误之处,欢迎斧正)

当下很多网站为了提高并发量,和负载能力,部署的服务器往往不止一台,那就会有不同的web容器,而一台pc通过访问浏览器访问Server,比如:最早打开浏览器,是访问A服务器,就会在A服务器的web容器产生一个SessionId。过一会,请求被分发到B服务器,这时候B服务器的web容器并没有这个SessionId的信息,无法识别。针对这种情况,先列举以下3种应对做法(不建议):

  • 在代码中判断session状态,找不到就放弃。 什么?你在逗我吗?(与Session初衷本末倒置)
  • 截获客户端发送过来的sessionId,根据这个id找到产生这个session的服务器,将请求直接发送给这台服务器。实质: 将集群系统最终变回了单点系统,如果处理请求的web容器挂掉了,那么用户的相关会话操作也就废掉了。(与集群初衷本末倒置)
  • 类比单点登录(可以看做一种跨站共享session的特殊情况),在SSO认证中心进行改造?(理论上,待验证)

综上所述,session一共有两个问题需要解决:

1) session的存储应该独立于web容器和该web容器所在的服务器

2)如何进行高效的session同步。

在讲到解决这些问题之前,我们首先要考虑下session该如何存储?将session数据存储到内存是最佳的选择。因此最好的解决方案就是使用分布式缓存技术,例如:memcached和redis(单点,需要人为实现分布式),将session信息的存储独立出来也是解决session同步问题的方法。

至此,能够拟出的应对方案有以下几种:

上一篇:Java多线程基础知识总结笔记


下一篇:C语言实现过滤ASCII在0~127范围内的字符,并去除重复的字符