2012 年预告的「谁在线」名单,现在上线了
2012 年 8 月 25 日,本博客的一篇文章宣布统计字段已经开始自动刷新,并以这样一句话收尾:「计划中的功能——'Who is online' 列表即将推出!」
那篇文章至今仍在。它预告的那份名单,花了十四年才到。现在它存在了,而那篇文章链接的那个计数器,这十四年一直在跑。
它显示了什么
统计页面上有一个实时面板:显示此刻有多少人正在这个网站上,并列出其中最新的几位——他们连接自哪个国家、在能确定的情况下来自哪座城市、正在浏览站内的哪个页面,以及距上次被观测到过去了多久。每次显示十二条,最新的排在最前面。
「此刻」指的是最近五分钟。一小时之后,这些记录就会被彻底删除。
「who」并不代表什么
名单里的任何人都不会被识别出身份。它的构建方式基于关于不使用 Cookie 计数的那篇文章中所描述的同一种 16 字节每日哈希值——名单中的每一行背后,都没有姓名、没有账户、没有 Cookie,也没有存储任何 IP 地址。
它保留的也只是页面的路径,而不是完整地址:例如 /shop/boots,而不是带有搜索引擎或邮件订阅在末尾附加的各种参数的完整链接。
如果同一座城市有两个人在看同一个页面,系统里就只会是两行记录。系统没有任何办法分辨,这究竟是两位读者,还是同一位读者先后用手机和笔记本电脑各看了一次。这不是留待日后版本修正的疏漏,而是有意为之的设计,也是计数器在其他各处都遵循的同一种权衡:足够有用,但不足以追踪任何人。
无需保持连接,也能做到实时
如今构建这类功能的常规做法是使用 WebSocket,或是 server-sent events——浏览器保持一条连接不断开,服务器一有更新就通过这条连接推送下来。这是优雅的解决方案,但放在这里就会是错误的选择。
本站的网页服务器为每个打开的连接分配一个进程,而它真正的工作是响应来自数千个网站的计数请求。一个保持打开的连接,就意味着一个无法响应其他任何人的进程。如果有五十个人同时盯着自己的实时页面,就意味着五十个进程闲置在那里,等着传送一个每隔几分钟才会变化一次的数字。
所以页面采用的是主动询问的方式,每十五秒一次,获取一小块 JSON 数据。围绕这一点,还有三个比时间间隔本身更重要的设计决定:
- 如果请求开始失败,频率会自动放缓到每分钟一次——而不是持续猛攻一台显然已经吃紧的服务器。
- 切换到后台标签页时,它会完全停止请求,而在标签页重新回到前台的瞬间立即刷新。没有人会盯着一个隐藏的标签页看,而那样的请求成本和一次有用的请求完全相同。
- N 秒前更新这一行文字,是在本地每秒计数一次,完全不产生任何成本。只有数据本身发生变化时才需要一次请求,数字变「旧」并不需要。
这些做法都算不上聪明,只是「相称」——而在一台小型服务器上,相称比聪明更有价值。一个实时视图,运行成本不应该超过它所监测的那件事本身。
有一部分没有回归
2015 年 9 月,有一篇文章介绍了 Users 标签页新学会的本领:分辨出正在主动阅读页面的人,与那些把页面开在后台标签页、早就忘了它存在的人。
这项区分功能还没有回归。目前的名单只知道某位访客上一次被观测到是什么时候,并不知道他们是否正在看页面。这个信息其实很值得掌握——毕竟任何网站的「访客」里,有相当一部分只是一个被遗弃的标签页——所以它已经被列入待开发清单。
希望这次不用再等十四年。
亲自试试
2012 年的那篇文章最后链接了一个实时示例作结,这篇文章似乎也该这样收尾才对。顺带一提,那个原始链接如今依然有效:它背后的计数器一直在运行,访问量已经超过 130 万次。
这里就有一个实时示例,查看无需账户。