第 4 章 · 多台服务器第 3 页,共 5 页
换了一台服务器,为什么我被退出登录了?
登录以后,网站要记住「你已经登录」。可下一个请求落到另一台服务器上,它还认得出你吗?
为什么需要
百家菜可以登录了,登录以后才能收藏菜谱、发评论。你只登录一次,之后打开别的页面,网站都知道是你。可第 1 章讲的 本身不记事:每个都单独理解,和前一个没有关系。网站得自己记住你,才能把一个个请求连起来。
网站为你记下的这段记录,叫(session)。你平时说的「会话」多指一段聊天;这里指网站为你保存的一段记录,记着「你已经登录」「你是谁」这类事。网站认出你的过程是这样的:
- 你登录时,核对密码,建一条会话记录,再生成一个(session ID):一串随机的字符,本身不写着你是谁。
- 服务器把会话编号放进 ,随响应交给你的浏览器,也就是你用来打开网页的程序。Cookie 是网站存在你浏览器里的一小段文字,之后你每次访问这个网站,浏览器都自动带上它。网页上常见的「接受 Cookie」提示,问的就是能不能存这样的文字;英文 cookie 的日常意思是饼干,这里只是个名字。
- 之后每个请求都带着会话编号,服务器拿它去找会话记录:找到了,就当你已经登录;找不到,就把你当成没登录的访客。
会话记录放在哪里?最省事的是记在替你登录的那台服务器的里。系统为了接着往下做、要记住的此前发生过的事,叫;你平时说的「状态」多指身体或心情,这里指「这位读者已经登录」这类事。像这样把读者的状态记在自己身上的服务器,是的。只有一台时这没问题;现在有好几台,下一个请求未必落到同一台。
被认出来:每次刷新落到哪一台,认不认得出你
先看这里先登录,再连刷五次,数一数记录里认出了你几次。
还没登录。先按「登录」。
还没有记录。按「登录」开始。
「每次可能落到任何一台」:负载均衡器一台接一台地分,可中间夹着许多别的读者的请求,你的请求落到哪一台就像是随机的(每次打开都一样)。「按用户算号」与上一页相同:一台停机时,只有分给它的读者改送另一台(图里是名单上的下一台),它恢复以后再回来。图里假定负载均衡器一停机就知道,下一页讲它怎样发现。
怎样做
图里看得出两种办法。第一种,让把同一位读者一直送到同一台,叫(sticky session),「粘」就是把这位读者固定在一台上,例如上一页的按用户算号。程序不用改,却很脆弱:那台一停,分给它的读者被送到别的服务器,全被退出登录;它恢复以后,这些读者又被送回来,可它的内存已经清空,于是又被退出一次;台数一变,大多数读者都要换服务器(上一页)。在上图里试试:负载均衡器换成「按用户算号」,登录、刷新,让接待你的那台停机再刷新;在新的那台上重新登录,再让原来那台恢复、刷新。
第二种,让服务器不把读者的状态记在自己身上,这叫(stateless):会话记录统一放进一个所有服务器都查得到的地方,叫(session store)。请求落到哪一台,那一台就拿着会话编号去会话存储查,于是每一台都认得出你,加机器、减机器、换掉坏机器,都不会把谁退出登录。在上图里把会话换到「会话存储」,登录、刷新,再让哪一台停机都试试。会话存储可以是一个,也可以是第 5 章讲的,按用途叫它会话存储就行。
流传很广的网站程序写法指南《十二要素应用》(The Twelve-Factor App)也这样建议:程序本身不保存状态,会话数据很适合放进到了设定的时间就自动删掉记录的存储。
代价是什么
代价是每个请求多一次查询,比读服务器自己的内存慢一些。会话存储也成了关键的组件:它一停,所有读者都可能被当成没登录,所以它自己也要可靠,常见的办法是多存几份,第 8 章讲的就是其中一种。
资料来源
以下资料均于 2026-10-22 至 2026-10-23 访问。
- RFC 9110: HTTP Semantics
- Using HTTP cookies
- RFC 6265: HTTP State Management Mechanism
- Session Management Cheat Sheet
- Module ngx_http_upstream_module
- The Twelve-Factor App: VI. Processes
- REL05-BP06 Make systems stateless where possible
- Architecture strategies for optimizing scaling and partitioning
- How to use sessions