轮询的困境与局限性
如果你干过后端或者前端,你一定写过类似这【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。样的代码:`setInterval(()【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】 => fetch(‘原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】/api/status’),未经授权,禁止复制转载。【本文首发于唐霜的博客】 3000)`。别急着否认,我们都干过。本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net轮询这东西,就像快餐——不健康,但方便、【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。便宜、随叫随到。项目早期,谁有空搞什么消本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。息队列、WebSocket、事件驱动?一【原创内容,转载请注明出处】【原创不易,请尊重版权】个定时器解决问题,多好。
转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。但业务一旦跑起来,轮询就开始还债了。
【版权所有,侵权必究】【未经授权禁止转载】转载请注明出处:www.tangshuang.net想象一个场景:页面上有 10 个任务需要【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net通过轮询来获取最新状态,每个都跑着一个 原创内容,盗版必究。【转载请注明来源】3 秒一次的轮询。算一下,每 3 秒就是原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】将近 30 个请求,而且其中 99% 的【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。请求返回的数据跟上次一模一样——服务器在【未经授权禁止转载】未经授权,禁止复制转载。那儿白忙活,带宽在那儿白白流,用户的设备【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】也在那儿白白耗电。
转载请注明出处:www.tangshuang.net【转载请注明来源】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。这还不是最糟糕的。当你的系统从单页面变成【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。多页面,从单终端变成多终端——手机上点了【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net”生成”,电脑上著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。想看进度——轮询就彻底抓瞎了。你开始在各未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net处补同步逻辑,今天这个页面加一段 `us转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。eEffect` 监听,明天那个组件加一【转载请注明来源】著作权归作者所有,禁止商业用途转载。个 `refetch` 调用,后天发现两未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。个页面的状态互相打架。代码库里到处散落着本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net”同步”的碎片,【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net像打地鼠一样,按下去了这个,那个又冒出来转载请注明出处:www.tangshuang.net【未经授权禁止转载】。
本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。WebSocket 固然是最好的,但是一转载请注明出处:www.tangshuang.net【版权所有,侵权必究】方面它一直占着一个长链接,用户一多,服务本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】器成本高。另一方面,前后端在接入 web未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。socket 时,需要协调好连接的建立、本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】维护和关闭,这给开发带来了额外的复杂性。【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。另外,还有一种 SSE 的方案,但是,仍【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。然有长链接占用服务器连接数,一旦出现高并【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。发就会导致服务器长期被占用,新用户进不来未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。的问题。相比之下,轮询更可控,更简单。
【未经授权禁止转载】未经授权,禁止复制转载。所以问题的本质不是”轮询好不本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net好”,而是我们需要一套系统性的方案来管理状态传播。轮询可以是这套方案的一部分,但不能是全【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。部。
著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。问题的本质:构建分层状态传播机制
先明确一下目标。我们要建的不是什么花哨的转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。实时通信系统,而是一套分层的状态传播机制。这个机制要能覆盖三种典型场景:
本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。第一种,日常状态。大部分时候系统很安静,没有任务在跑,没未经授权,禁止复制转载。【原创内容,转载请注明出处】有什么需要频繁更新的。这时候我们希望用最【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。低的成本来维持”感知能力【转载请注明来源】【关注微信公众号:wwwtangshuangnet】8221;——有变化了我能知道,没变化的本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net时候你别来烦我。事件通知天然适合干这个。
【原创内容,转载请注明出处】原创内容,盗版必究。第二种,忙碌状态。用户点了个”生成视频【原创不易,请尊重版权】【转载请注明来源】221;,进度条在那儿转,停止按钮随时可【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。能被按下去。这时候你不能等事件慢悠悠地来转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。,用户对延迟的容忍度几乎是零。需要局部的【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】、短周期的高频同步来保障体验。
【本文首发于唐霜的博客】【未经授权禁止转载】【本文首发于唐霜的博客】第三种,出了问题的时候。网络抖了,消息丢了,服务重启了——这种【原创内容,转载请注明出处】【原创内容,转载请注明出处】事一定会发生,区别只是早晚。你需要一个兜原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。底机制,在事件链路和同步链路都掉链子的时【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。候,还能把数据拉回来,保证最终一致性。
【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。这三层各司其职,互相补充。后面所有的设计【原创不易,请尊重版权】【未经授权禁止转载】决策,都是围绕这个三层模型展开的。
【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。核心设计原则:通知与数据解耦
在我见过的消息系统里,最容易犯的一个错误【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。就是往消息体里塞太多东西。任务状态变了?【版权所有,侵权必究】【本文首发于唐霜的博客】好,把整个任务对象塞进消息里。资源更新了原创内容,盗版必究。【作者:唐霜】?把完整的资源数据也带上。听起来挺方便—【原创内容,转载请注明出处】未经授权,禁止复制转载。—前端收到消息直接用,不用再发请求了,多本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net省事。
【原创内容,转载请注明出处】【本文受版权保护】【作者:唐霜】【版权所有】唐霜 www.tangshuang.net省事是省事了,但后患无穷。
著作权归作者所有,禁止商业用途转载。【本文受版权保护】首先,消息体一大,吞吐量就下来了。你本来【本文首发于唐霜的博客】未经授权,禁止复制转载。一秒能发一万条轻量通知,现在一条消息就几【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。 KB,同样的带宽能承载的量直接缩水。其【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。次,业务字段一变,消息协议就得跟着变。今本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。天加个字段,明天改个结构,消息的消费端全本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】得跟着改——这就是耦合的代价。最要命的是【版权所有,侵权必究】【未经授权禁止转载】,前端收到一个”大消息【转载请注明来源】【转载请注明来源】221;之后,到底要不要刷新?如果消息里【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】的数据已经是最新的了,那确实不用刷;但如【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。果消息在路上耽搁了一会儿,数据库又更新了【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。呢?你拿消息里的数据去渲染,反而是错的。
【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。所以正确做法是:消息只告诉你”哪里脏了【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。221;,具体脏成了什么样,你自己去查。
本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】原创内容,盗版必究。一条消息大概长这样:实体类型是̶【原创内容,转载请注明出处】【版权所有,侵权必究】1;项目”,实体 ID 是 本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net123,任务类型是”视频生成【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。”,时间戳是变更发生的时刻。【转载请注明来源】本文作者:唐霜,转载请注明出处。就够了。前端收到这条消息,知道̶原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net1;项目 123 的视频生成任务有变化&【转载请注明来源】【版权所有】唐霜 www.tangshuang.net#8221;,然后自己去拉最新的数据。消未经授权,禁止复制转载。【版权所有,侵权必究】息体小、协议稳定、前端按需刷新——三赢。
本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。幂等与去重:消息可靠性的基石
很多人在设计消息系统的时候,潜意识里假设【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】消息是可靠的——发一条,收一条,顺序还对【本文受版权保护】【版权所有,侵权必究】。但现实是:消息可能重复发送(网络超时触未经授权,禁止复制转载。未经授权,禁止复制转载。发了重试),可能乱序到达(走了不同的链路【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】),可能延迟很久才到(某个中间件卡了一下未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。)。如果你不考虑这些,用户就会看到进度条【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。先跳到 100% 又弹回 50%,或者一【原创不易,请尊重版权】【原创不易,请尊重版权】个已经完成的任务突然变成”进【原创不易,请尊重版权】【本文首发于唐霜的博客】行中”——这种体验,比没有通【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】知还糟糕。
转载请注明出处:www.tangshuang.net原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net所以在协议层面就要把去重和幂等做好。每条原创内容,盗版必究。【作者:唐霜】消息带一个单调递增的 `timestam【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netp`(注意,必须是业务更新的真实时间,不【本文首发于唐霜的博客】【本文首发于唐霜的博客】是消息发送的时间),前端收到消息后先跟本原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】地记录比一下:时间戳没前进?忽略。时间戳【版权所有】唐霜 www.tangshuang.net【本文受版权保护】前进了但 payload 一样?也忽略。原创内容,盗版必究。【原创内容,转载请注明出处】时间戳前进了且 payload 有变化?【本文受版权保护】原创内容,盗版必究。更新本地记录,触发刷新。
本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。还有一种常见的场景:短时间内同一个实体连本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】着来了好几条通知。比如一个视频生成任务,【关注微信公众号:wwwtangshuangnet】【本文受版权保护】先是”开始”,再本文作者:唐霜,转载请注明出处。【未经授权禁止转载】是”进度 30%”原创内容,盗版必究。本文作者:唐霜,转载请注明出处。;,再是”进度 60%本文作者:唐霜,转载请注明出处。原创内容,盗版必究。221;——三条消息在一秒内扎堆到达。你【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】不需要刷三次,合并成一次刷新就够了。这就原创内容,盗版必究。【转载请注明来源】是所谓的”通知合并̶本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】1;,在桥接层做。
【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】三层架构设计:采集、桥接与运行时
好,原则讲完了,来看具体的架构。整个系统【本文受版权保护】原创内容,盗版必究。分三层,从上到下分别是消息采集层、客户端转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】桥接层和页面运行时层。听起来挺唬人,其实本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】每层做的事情都很明确。
本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】第一层:消息采集层
这一层跑在后端,职责很简单:定期看看最近本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。有哪些实体发生了变化,整理成一个R【原创内容,转载请注明出处】【原创内容,转载请注明出处】21;脏列表”返回给前端。
【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】未经授权,禁止复制转载。你可能会问:这不是还是轮询吗?对,但它跟转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】页面的业务轮询有本质区别。页面轮询是转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】8221;我要查某个具体的东西有没有变&未经授权,禁止复制转载。【本文首发于唐霜的博客】#8221;,采集层是”有什未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net么东西变了告诉我”。前者是 本文版权归作者所有,未经授权不得转载。【转载请注明来源】N 个页面各轮询各的,后者是统一的、聚合【原创内容,转载请注明出处】【原创内容,转载请注明出处】的状态变更源。前端只需要跟这一个源头打交【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net道,不用关心后端有多少个业务模块在产生变【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】更。
【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。采集层吐出来的数据也很轻量:变更对象的类本文版权归作者所有,未经授权不得转载。【转载请注明来源】型和 ID、变更的范围(比如是资源变了还【本文受版权保护】【原创不易,请尊重版权】是任务状态变了)、任务类型、时间戳。就这【原创内容,转载请注明出处】未经授权,禁止复制转载。么几个字段,JSON 序列化完也就一两百著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net字节。
著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。第二层:客户端桥接层
这一层跑在前端,是整个系统的中枢。它全局【原创内容,转载请注明出处】【版权所有,侵权必究】监听采集层吐出来的脏列表,写入本地的 d【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。irty store,然后分发给各个页面【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。。
【转载请注明来源】【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】桥接层要做的四件事,我在前面其实都提过了原创内容,盗版必究。本文作者:唐霜,转载请注明出处。:去重(基于时间戳)、合并(同实体多次通【本文受版权保护】【原创内容,转载请注明出处】知合并成一个)、限频(短时间窗口内的突发【本文受版权保护】【作者:唐霜】通知攒一批再处理)、分发(转给对应的页面原创内容,盗版必究。【原创不易,请尊重版权】或模块)。这四件事做好了,下游的页面就不【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】用操心消息的可靠性问题了——你给它的就是原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】干净、去重、合并过的信号。
原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net第三层:页面运行时层
这一层是离用户最近的地方,也是最容易写出【本文受版权保护】【版权所有,侵权必究】面条代码的地方。
【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】本文版权归作者所有,未经授权不得转载。页面收到 dirty 信号后,要决定怎么【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net刷新。最直觉的做法是在事件回调里写一堆条未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。件判断:如果任务类型是 A 就刷这个接口本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】,如果是 B 就刷那个接口,如果两个都有著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net就都刷……写着写着,回调函数就膨胀成了几【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】百行的怪物,而且逻辑散落各处,谁也不敢改未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net。
转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net更好的做法是抽象出一个策略映射表。输入是任务类型、变更范围和当前页面的上【原创内容,转载请注明出处】【版权所有,侵权必究】下文(是不是忙态、页面可不可见、当前选中【转载请注明来源】原创内容,盗版必究。了什么),输出是一个明确的”本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】刷新计划”——需要刷哪些接口【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】、以什么粒度刷、串行还是并行。这样逻辑集【转载请注明来源】原创内容,盗版必究。中在一处,新增任务类型只需要加一行映射,本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】不用动流程代码。
【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。刷新执行完之后,还要做一次”未经授权,禁止复制转载。原创内容,盗版必究。收敛检查”——确认本地的状态原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。跟远端的状态一致了。如果不一致,说明中间【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net可能漏了什么,这时候就触发兜底拉取。
【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。系统工作流程:注册、采集与消费的完整链路
前面讲了三层架构各自负责什么,但光知道&原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net#8221;谁干什么”还不够【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net——你得看到数据是怎么从头到尾流转的,才原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。能真正理解这套系统为什么这么设计。
【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】【转载请注明来源】整个工作流程分六个步骤,先用一张图把全局本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。串起来:
【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。下面逐步拆解。
【作者:唐霜】本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net① 注册:业务模块告诉系统”本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。我能检测变化”
原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。这是整个流程的起点。每个业务模块在服务启未经授权,禁止复制转载。【本文首发于唐霜的博客】动的时候,向 MessageRegist【本文受版权保护】【版权所有,侵权必究】ry 注册自己:我叫什么名字(type)原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。,以及怎么检测变化(handler)。比【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。如通知模块注册了 `notificati原创内容,盗版必究。转载请注明出处:www.tangshuang.neton.announcement`,视频任【本文受版权保护】转载请注明出处:www.tangshuang.net务模块注册了 `video.genera【作者:唐霜】原创内容,盗版必究。tion`——每个模块只需要管好自己的 【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.nethandler,不用关心谁在消费这些消息本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】。
【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。handler 的接口很简单:给它一个用【原创不易,请尊重版权】原创内容,盗版必究。户 ID,它返回 `{ has_new:原创内容,盗版必究。【版权所有,侵权必究】 true/false, data: {【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。…} }`。至于”【未经授权禁止转载】【版权所有,侵权必究】;怎么判断有没有新消息”,那转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。是每个业务模块自己的事——查数据库也好,【作者:唐霜】本文版权归作者所有,未经授权不得转载。读缓存也好,MessageRegistr【本文首发于唐霜的博客】原创内容,盗版必究。y 不操心。
转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【本文受版权保护】② 采集:统一入口,并发调用所有 han著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。dler
【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net当前端发来 `GET /api/mess【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。ages` 请求时,API 层调用 `M【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】essageRegistry.colle未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。ct(uid)`。这个方法会遍历所有已注本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】册的 handler,用 `Promis【版权所有,侵权必究】原创内容,盗版必究。e.allSettled` 并发调用——【作者:唐霜】本文版权归作者所有,未经授权不得转载。注意是 `allSettled` 而不是【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】 `all`,意思是某个 handler【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net 挂了不影响其他 handler 的结果【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net。最后把 `has_new` 为 tru未经授权,禁止复制转载。【本文受版权保护】e 的消息筛出来返回。
本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。这就是”通知与数据解耦【原创内容,转载请注明出处】【原创不易,请尊重版权】221;的具体体现:返回的不是完整业务数本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。据,而是一个轻量的”有没有变本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。化”的信号。前端拿到这个信号【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。,再决定要不要去拉具体数据。
本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。③ 轮询:前端的统一心跳
未经授权,禁止复制转载。【转载请注明来源】本文版权归作者所有,未经授权不得转载。MessagePoller 是前端唯一跟著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。消息系统打交道的地方。它每 3 秒发一次原创内容,盗版必究。【原创不易,请尊重版权】 `GET /api/messages`本文作者:唐霜,转载请注明出处。【本文受版权保护】,不管页面上有多少个业务模块在等消息——本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。只需要这一个轮询就够了。跟之前̶转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】1;每个业务各轮询各的”相比【转载请注明来源】【关注微信公众号:wwwtangshuangnet】,请求量从 N 降到 1。
转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【转载请注明来源】返回的数据也很精简:一组 `{ type未经授权,禁止复制转载。未经授权,禁止复制转载。, has_new, data }` 加未经授权,禁止复制转载。原创内容,盗版必究。一个全局时间戳。如果没有任何变化,响应就本文作者:唐霜,转载请注明出处。原创内容,盗版必究。是空的,几乎不占带宽。
未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。④ 广播:把”脏信号R本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。21;分发出去
著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。Poller 收到响应后,遍历所有 `h【原创不易,请尊重版权】【本文首发于唐霜的博客】as_new` 的消息,通过 `glob【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】alEvent.emit(‘【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。MSG:${type}’, 原创内容,盗版必究。【转载请注明来源】data)` 广播出去。这一步就是本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。221;桥接层”在干活——它原创内容,盗版必究。未经授权,禁止复制转载。把后端的轮询响应转化成了前端内部的事件总【转载请注明来源】原创内容,盗版必究。线。
【作者:唐霜】著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。为什么要用事件总线而不是直接调各个模块的未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。方法?因为解耦。Poller 不需要知道【版权所有,侵权必究】原创内容,盗版必究。页面上有哪些模块在监听,也不需要知道每个转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】模块拿到消息后要干什么。它只管̶转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】1;谁有变化,就喊一嗓子”,【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。至于谁来听、听了之后做什么,各自负责。
著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】⑤ 订阅:各取所需,按类型监听
【版权所有,侵权必究】未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】每个业务模块在前端通过 `globalE【原创不易,请尊重版权】【未经授权禁止转载】vent.on(‘MSG:$本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net{type}’, handl【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】er)` 监听自己关心的消息类型。通知模本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net块听 `MSG:notification转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。.announcement`,视频任务模本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。块听 `MSG:video.genera本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。tion`——互不干扰,各自拿到各自的信【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】号。
转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。这种模式的好处是:新增一个业务模块,只需【版权所有,侵权必究】【原创内容,转载请注明出处】要在后端注册一个 handler、在前端转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】加一个 `on` 监听,不用改 Poll【版权所有,侵权必究】【原创内容,转载请注明出处】er、不用改 API、不用改任何其他模块【转载请注明来源】本文作者:唐霜,转载请注明出处。的代码。真正的”开闭原则原创内容,盗版必究。【原创不易,请尊重版权】8221;。
【原创不易,请尊重版权】【本文首发于唐霜的博客】【本文首发于唐霜的博客】【原创不易,请尊重版权】⑥ 拉取与渲染:按需获取完整数据
【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net【本文受版权保护】【本文受版权保护】Hook 收到”脏信号本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】221;之后,才去调具体的业务接口拉完整【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net数据——这就是所谓的”按需拉【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。取”。拉到数据后更新本地状态【本文受版权保护】本文作者:唐霜,转载请注明出处。,UI 组件自动响应式渲染。
【转载请注明来源】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。未经授权,禁止复制转载。整个链路串起来就是:业务模块注册 → Poller 轮询触发【转载请注明来源】【原创不易,请尊重版权】采集 → Registry 并发调用 h转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netandler → 返回脏信号 → Pol【本文首发于唐霜的博客】【本文首发于唐霜的博客】ler 广播 → Hook 订阅 → 按本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。需拉取 → UI 更新。每一步职责清晰,每一步都可以独立演进。
转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】并发控制:刷新风暴的防御策略
这是实际落地中很容易踩的坑。想象一下:用著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】户一口气提交了 10 个生成任务,每个任著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。务的状态变更都会触发刷新,短时间内你可能【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】面临几十次刷新请求同时发出的情况——这就著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。是刷新风暴。
【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【转载请注明来源】【未经授权禁止转载】有三个招可以防。
著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。第一招:请求合并(In-flight C【作者:唐霜】【关注微信公众号:wwwtangshuangnet】oalescing)。 同一个接口的请求如果在飞了(还没回来)转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】,后来的请求不要重复发,只打个标记。等前【转载请注明来源】原创内容,盗版必究。面的请求回来了,根据标记决定要不要再发一【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。次。这样就算一瞬间来了 10 个通知,同【原创不易,请尊重版权】【转载请注明来源】一个接口最多也就 2 次请求:一次处理已【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】有的变更,一次处理积攒的新变更。
著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net第二招:模式升级(Mode Escala未经授权,禁止复制转载。转载请注明出处:www.tangshuang.nettion)。 有时候一个”轻刷新R【原创不易,请尊重版权】【原创内容,转载请注明出处】21;(比如只拉任务状态)和一个R【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。21;重刷新”(比如拉完整的【原创内容,转载请注明出处】【转载请注明来源】资源列表)同时触发了。与其分别执行两次,【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】不如直接升级成重刷新一次搞定。反正重刷新【原创不易,请尊重版权】未经授权,禁止复制转载。的结果包含轻刷新的结果,做一次就够了。
【转载请注明来源】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。第三招:软超时兜底。 正常情况下,事件链路会自然收敛——任务原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。结束了,最后一轮刷新确认了状态,皆大欢喜【转载请注明来源】本文作者:唐霜,转载请注明出处。。但万一没收敛呢?比如最后一条消息丢了,【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。前端一直卡在”进行中R转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】21;。这时候需要一个软超时:如果过了指【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】定时间还没有收敛确认,就主动触发一次兜底未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。拉取,强行把状态拉对。注意是”著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】;软”超时——不是硬中断,而【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net是温和地补一次。
【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。生命周期策略:忙态与闲态的分治管理
如果你的系统在任何时候都以同样的策略运行【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】,那一定有什么地方在浪费。没有任务跑的时【转载请注明来源】【未经授权禁止转载】候,没必要每 3 秒同步一次;任务跑得正本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】欢的时候,你也不能指望事件通知能跟上用户未经授权,禁止复制转载。【本文受版权保护】对即时反馈的期望。
【原创不易,请尊重版权】【本文受版权保护】著作权归作者所有,禁止商业用途转载。所以需要区分两种状态:忙态和闲态。
【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net忙态就是有任务在跑的时候。这时候保持一个短周本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。期的局部同步(比如 2~3 秒一次),主本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】要为了保障进度条的即时更新、锁定状态的准【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。确显示、停止按钮的快速响应。这个同步范围【关注微信公众号:wwwtangshuangnet】【本文受版权保护】要尽量小——只同步当前关心的那个实体的任【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。务状态,不要全量拉。
未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】闲态就是没有活动任务的时候。这时候关掉高频同【本文受版权保护】本文版权归作者所有,未经授权不得转载。步,主要依赖事件通知来唤醒刷新。没变化就【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net什么都不做,有变化了事件会告诉你。
本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。关键在于怎么切换。进入忙态不能只看本地状态——用户可能在【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net另一个设备上启动了任务——必须结合远端状本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net态一起判断。退出忙态也不能急,必须确认状【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。态已经收敛了(本地状态跟远端状态一致了)【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】才能退,不然 UI 会抖。
著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net这里有个细节值得注意:退出忙态的时机太早本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。,用户会看到进度条突然跳回旧状态;太晚,著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】又白白多轮询了好几轮。实践中,我们会在最本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。后一轮同步确认”没有活跃任务【本文首发于唐霜的博客】【原创内容,转载请注明出处】”之后,再等一个周期做二次确【作者:唐霜】转载请注明出处:www.tangshuang.net认,然后才真正退出忙态。两轮确认,换来的本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net是 UI 的稳定。同时,为了在有新任务时【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。,避免闲态轮询间隔时间过长,我们可以在发【未经授权禁止转载】【本文首发于唐霜的博客】起新任务的地方,立即激活忙态,让轮询恢复原创内容,盗版必究。【本文受版权保护】较短间隔。
【版权所有,侵权必究】【未经授权禁止转载】【作者:唐霜】转载请注明出处:www.tangshuang.net数据一致性与异常场景处理
设计消息系统的时候,有一些边界情况特别容原创内容,盗版必究。【本文首发于唐霜的博客】易忽略,但一旦出问题就特别显眼。
本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】乱序问题。*消息 A 先发出,消息 B 后发出,但 未经授权,禁止复制转载。【本文受版权保护】B 先到了。如果你简单地”收【版权所有】唐霜 www.tangshuang.net【作者:唐霜】到就更新”,就会用旧数据覆盖转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】新数据。解决方案是永远以更新的版本为准—转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。—不是”后到为准”著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。;,而是”时间戳更大为准【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。8221;。
本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。停止的语义。 “用户点了停止”转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net;和”任务已经停了̶【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。1;是两个不同的状态。点了停止之后,任务著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】可能还需要一段时间才能真正停下来。如果 未经授权,禁止复制转载。【原创不易,请尊重版权】UI 在用户点完停止后就直接显示R【原创不易,请尊重版权】【本文受版权保护】21;已完成”,用户会以为结【原创不易,请尊重版权】【原创内容,转载请注明出处】果已经出来了;如果一直显示”本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。停止中”不动,用户又以为系统【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。卡死了。正确的做法是有一个明确的R本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。21;停止中”过渡态,等任务本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net真正停了再切换到最终状态。
原创内容,盗版必究。【本文受版权保护】【转载请注明来源】失败恢复。 刷新失败了怎么办?第一反应可能是立即重未经授权,禁止复制转载。【版权所有,侵权必究】试,但这是错的——如果失败是因为服务端过【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。载,立即重试只会让情况更糟。应该用指数退本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】避:第一次等 1 秒重试,第二次等 2 本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】秒,第三次等 4 秒……同时保留一个最小【转载请注明来源】未经授权,禁止复制转载。兜底路径,确保即使重试都失败了,用户下次【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】操作时也能拿到正确数据。别忘了打点记录失转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。败原因——这些数据在排查问题的时候是无价本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net之宝。
著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net可观测性设计:上线后的关键指标
系统做完了不是结束,是开始。没有可观测性【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】的消息系统,上线之后就是一个谁都不敢动的【本文受版权保护】著作权归作者所有,禁止商业用途转载。黑盒——出了问题不知道,知道了不知道为什转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。么,知道了为什么不知道怎么修。
本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。建议关注四组指标。
著作权归作者所有,禁止商业用途转载。【转载请注明来源】链路健康:消息采样成功率怎么样?`has_new【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】` 的命中率是多少(如果命中率太低,说明【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】采样周期内大部分时候都没变化,可以适当拉【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】长周期)?客户端消费成功率呢(有没有消息【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。到了前端但没被处理的情况)?
本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【转载请注明来源】【版权所有】唐霜 www.tangshuang.net性能:单用户每分钟的消息量是多少?单页面每分著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】钟的刷新请求量是多少?刷新的平均耗时和 【转载请注明来源】未经授权,禁止复制转载。P95 是多少?这些数字能帮你判断系统有原创内容,盗版必究。【本文首发于唐霜的博客】没有在”空转”。
【作者:唐霜】转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。正确性:兜底同步触发了多少次?如果兜底同步触发【未经授权禁止转载】原创内容,盗版必究。太频繁,说明主链路有问题。状态收敛超时率【未经授权禁止转载】【转载请注明来源】是多少?前端有没有”卡在运行【未经授权禁止转载】【本文首发于唐霜的博客】中”一直不恢复的情况?
本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。体验:从任务实际结束到 UI 显示更新,用户【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。等了多久?从用户按下”停止&【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】#8221;到看到停止反馈,又等了多久?本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】这两个延迟是用户最直接能感知到的。
【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。工程化落地路径
说了这么多,真正动手的时候应该从哪一步开原创内容,盗版必究。【本文首发于唐霜的博客】始?我建议按这个顺序来:
【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】先定义统一的 dirty 协议。这是整个本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。系统的基石,协议不定好,后面都白搭。然后原创内容,盗版必究。未经授权,禁止复制转载。搭服务端采集器,按 TTL 返回最近变化【未经授权禁止转载】转载请注明出处:www.tangshuang.net。接下来搭前端桥接层,把去重、合并、分发未经授权,禁止复制转载。【未经授权禁止转载】做好。这三步做完,基础设施就有了。
转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。然后抽象刷新策略映射表,把页面里的面条逻【本文受版权保护】原创内容,盗版必究。辑收拢。再接入页面运行时,实现忙态轮询和【版权所有】唐霜 www.tangshuang.net【作者:唐霜】闲态消息唤醒。加上 in-flight 【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】合并和软超时兜底之后,系统的可靠性就基本【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】有保障了。
原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。最后补观测指标和报警,做灰度验证,对比改本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。造前后的指标变化。千万别跳过灰度——消息【本文首发于唐霜的博客】【作者:唐霜】系统是底层基础设施,全量上线出问题就是全著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net局性的。
原创内容,盗版必究。【原创内容,转载请注明出处】常见反模式与规避策略
在结束之前,再聊几个我见过的典型反模式,【未经授权禁止转载】【作者:唐霜】希望你看了能绕开。
转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。把完整业务对象塞进消息体。 前面说过这个了,再说一遍是因为真的太常【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。见了。图一时方便,后面维护的时候就知道什【未经授权禁止转载】【本文受版权保护】么叫”牵一发而动全身R【本文受版权保护】著作权归作者所有,禁止商业用途转载。21;。
【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。页面里到处都是”收到通知就全转载请注明出处:www.tangshuang.net【未经授权禁止转载】量刷新”。 这种做法简单粗暴,短期内能跑,但请求量【版权所有,侵权必究】【转载请注明来源】大、用户体验差、服务器压力大。而且每个页【原创不易,请尊重版权】【转载请注明来源】面的刷新逻辑都是独立的,改一个地方容易,著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】改十个地方就呵呵了。
本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】不做去重。 重复通知触发重复请求,重复请求返回重复原创内容,盗版必究。原创内容,盗版必究。数据,重复数据触发重复渲染——这条链路每本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】一环都在浪费。
原创内容,盗版必究。【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。任务结束只靠单一信号判断。 比如只看”任务状态变成了 本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】completed”,但如果【转载请注明来源】未经授权,禁止复制转载。这条消息丢了呢?或者来了但被去重逻辑误判原创内容,盗版必究。【本文首发于唐霜的博客】了呢?必须有兜底手段。
著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】【原创不易,请尊重版权】用固定高频轮询覆盖所有场景。 不管有没有任务在跑,都 3 秒轮询一次未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】。这是偷懒的做法,对用户、对服务器都不友【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】好。
著作权归作者所有,禁止商业用途转载。【转载请注明来源】原创内容,盗版必究。小结
说到底,一套好的消息通知系统就在做三件事转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】:用事件减少无效同步的成本,用运行时策略著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。保障关键交互的体验,用兜底机制守住最终一本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】致性。
【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】它不是某个框架的特性,也不是某段代码的技【转载请注明来源】【原创不易,请尊重版权】巧,而是一种可以复制的工程化能力。只要你原创内容,盗版必究。原创内容,盗版必究。的系统存在”异步任务 + 状【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】态反馈 + 多端一致性”的问转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。题——说白了,只要你做过任何涉及异步状态【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。的 Web 应用——这套方案都能落地,而著作权归作者所有,禁止商业用途转载。【本文受版权保护】且能跟着业务一起演进。
【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】当然,这篇文章里的每一条都是过来人的经验著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】总结,不是什么金科玉律。你的业务场景可能原创内容,盗版必究。【本文受版权保护】有自己的特殊性,该调整的地方就调整。重要【原创内容,转载请注明出处】【原创不易,请尊重版权】的是理解背后的思路:分层、解耦、幂等、可【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。观测——这四个词记住了,设计出来的系统就著作权归作者所有,禁止商业用途转载。【转载请注明来源】不会差到哪里去。
原创内容,盗版必究。【原创不易,请尊重版权】2026-05-29 941



[…] 而轮询,则是作为顶替长链接的一种原始办法。我在《「消息桥」:从轮询到事件驱动的消息推送系统工程化落地》一文中,基于轮询设计了一套消息通知系统。 […]