session 原理以及 session 共享

本贴最后更新于 1634 天前,其中的信息可能已经时过境迁

说 session 之前一定离不开 cookie

cookie 是存储在浏览器中的一小段文本格式如:

a=xxx;b=xxxx;c=xxx

浏览器

浏览器端在发送请求时可能会带上 cookie,如下:

Request Headers
:authority: www.cnblogs.com
:method: GET
:path: /ajianbeyourself/ajax/CommentForm.aspx?postId=4900140&_=1589522080185
:scheme: https
accept: text/html, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9,zh-TW;q=0.8
cookie: _ga=GA1.2.958031816.1554176988; __gads=ID=c05e695fe0ecf4df:T=1554176998:S=ALNI_MYjFCirz0z4LlEeAjPh8DENgWhU2w;
referer: https://www.cnblogs.com

服务端

有些 cookie 是浏览器端主动生成,然后在请求服务端时发送的,还有一些是在服务端生成然后告知给浏览器的

当服务端需要告诉浏览器存储并且往后的所有请求都带上某个 cookie 时,会在 response 中添加如下 header:

Set-Cookie:value [ ;expires=date][ ;domain=domain][ ;path=path][ ;secure]

[ ] 中的值时可选项,value 是必选的,入之前所述 value 的格式一般是 a=xxx;b=xxxx 但却不是必须的

当浏览器发现响应头中有 Set-Cookie 这个 header 那么就会把 cookie 存储,以后对该服务器的所有请求都会带上这个 cookie


session

session 是和 cookie 配合使用的,可以这么说 session 就是用一个 map 的数据结构,而 cookie 就是 key

一般用户登录后,服务器会存储一些登录信息在缓存中,然后生成一个 cookie 其实就是一个key 返回给前端,前端以后访问时会带上这个 key 其实就是带上cookie,这个是浏览器自动帮我们做了的操作,服务端就可以对这次请求进行一些检查操作了,比如说检查用户是否已登录

session 共享

传统的 session 是直接存储在内存中的,如果是单机部署应用肯定没问题,集群就不行了

比如说小明在登录时,被负载均衡后交由 server A 处理,server A 处理后会把 session 存储在本机的内存中,然后返回登录成功

接着,小明在网站进行一些其他操作,比如说查看好友列表,此时这个请求被负载均衡器交由 server B 处理,server B 拿到 cookie,然后根据 cookie 去查找 session,肯定找不到于是就认为小明没有登录,返回 400。。

针对这种问题有很好的轮子可以解决:Spring Session

这个问题出现的根本原因是各个服务器都把 session 缓存在自己的内存中,所以只需要把 session 集中在一个地方存储就行了,Spring Session 就是这样做的。

Spring Session 常用的一种方案是把 session 存储在 redis 中,各个服务器公用同一个 redis

spring session 的原理以及设计可以看我另一篇文章

内部服务调用 session 共享

上面的问题只是解决了客户端调用服务时 session 可以共享

server A1,server A2,server A3是一个服务集群,提供相同的服务
小明登录后,请求任意一个server都没问题

现在有了新的问题,则是内部服务之间的调用,比如

有服务server A和server B,他们提供不同的服务
小明通过server A进行登录,然后查看好友列表
`查看好友列表`这个操作需要客户端调用server A,然后server A调用server B

在 server A 中肯定能够拿到小明登录后的信息,但是 server B 则不行。

解决办法很简单,如下:

  • server A 和 server B 使用 spring session,公用同一个 redis 存储 session
  • server A 调用 server B 时,把 cookie 取出来然后传递给 server B

之前说过了 cookie 就是 key,server B 有了 cookie 肯定能拿到 session 的值了

这是 spring session 帮我们做的,虽然我没仔细看过源码,但是其步骤肯定如下:

  • 检查请求头中是否有 cookie
  • 检查是否有 SESSION=ABCDEFGHXXXX 的 cookie
  • 若有则根据 ABCDEFGHXXXX 去 redis 中查询数据,然后存放在 HttpSession 中
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3186 引用 • 8212 回帖 • 1 关注
  • Session
    14 引用 • 6 回帖
  • Cookie
    21 引用 • 63 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...