HTTP协议本身是无状态的,无状态的意思是浏览器发起的每个HTTP请求,对于服务端而言都是彼此独立的,即服务端无法直接通过HTTP协议将用户的多次HTTP请求联系在一起。这就好比顾客跟自动售货机的关系一样,无论你在一台自动售货机上购买了多少次商品,自动售货机都没法“记住”你,也就是说你每一次在该售货机上购买商品的时候,自动售货机都会把你当成一个陌生的顾客来对待。
然而在Web应用的很多场景下需要维护用户状态才能正常工作。典型的应用就是购物车。当你在网上商城购买商品的时候,每看到一个喜欢的商品可以把它先加入购物车,然后继续浏览其他商品,等浏览完商品后再进行商品的结算。在这个过程中,你与服务器的通信是通过多次HTTP请求完成的,浏览器必须通过某种机制识别出你发出的所有HTTP请求是来自同个计算机的同个浏览器,或者来自同一个账户。否则服务器就没办法将购物车里的商品跟某个人联系起来,因此也无法实现购物车功能。这种维持HTTP状态的机制就是会话机制。
会话机制一般有两种实现方案,一种是基于Session实现,一种是基于Cookie实现。这两种方案的本质区别是前者是将用户状态信息保存在服务端,后者是将用户状态信息保存在客户端。那么什么又是用户状态信息呢?以前面的购物车为例,状态信息就是商品信息。
一、基于Session实现会话保持
基于Session实现会话保持的原理是:在会话的开始(即客户端第一次向服务器发送HTTP请求时),服务器会将会话状态保存起来(一般保存在本机内存,当然也可以保存在其他存储系统),然后分配一个会话标识(也叫SessionId)给客户端,这个会话标识一般保存在浏览Cookie里,以后每次浏览器发送HTTP请求的时候,都会带上这个会话标识到服务器,服务器拿到这个会话标识之后就可以把之前存储在服务端的状态信息与该会话联系起来,因此也就实现了会话保持。当然如果遇到浏览器禁用了Cookie的情况,则可以通过url重写的方式将会话标识放在url的参数里,这样也可以实现会话保持。
二、基于Cookie实现会话保持
基于Cookie实现会话保持与上述基于Session实现会话保持的最主要区别是前者完全将会话状态信息存储在浏览器Cookie中,这样一来每次浏览器发送HTTP请求的时候都会带上状态信息,因此也就可以实现状态保持。以上述购物车应用为例,服务端可以将商品信息加密(也可以不加密,但为了安全性,一般会此对状态信息进行加密处理)后保存在浏览器的Cookie中,这样一来服务端就能知道你在浏览的过程中添加了哪些商品到购物车中了。
三、两者的优缺点
基于Session的会话保持的优点是具有安全性,因为状态信息是保存在服务端的,缺点是不便于服务器的水平扩展。大型网站的后台一般都不止一台服务器,可能几台甚至上百台,浏览器发送的HTTP请求一般要先通过负载均衡器才能到达具体的后台服务器,这就会导致每次HTTP请求可能落到不同的服务器上,比如说第一次HTTP请求落到server1上,第二次HTTP请求落到server2上。而Session默认是存储在服务器本机内存的,当多次请求落到不同的服务器上时,上述方案就不能实现会话保持了。
基于Cookie的会话保持的优点是服务器不用保存状态信息,减轻服务端存储压力,也便于服务端做水平扩展。缺点是不够安全,因为状态信息是存储在客户端的,这意味着不能在会话中保存机密数据,另一个缺点是每次HTTP请求都需要发送额外的Cookie到服务端,会消耗更多带宽。
总结
上述基于Session机制实现会话保持的方案中,当服务端有多台服务器的时候可能无法正常工作,那么是否有其他措施可以在服务端有多台服务器的时候基于Session实现会话保持呢?答案是肯定的。由于篇幅所限,在此不详述,后续会再次探讨这个问题。
如果觉得这篇文章对你有帮助,可以扫描下方二维码,关注本人公众号,获得更多优质文章推送。