设计一个功能开关服务,听起来像道送分题。用过LaunchDarkly或Unleash的候选人往往这么想——直到面试官追问:"你的SDK跑在10万个生产进程里,它们怎么知道开关变了?"
naive答案会先画负载均衡器。正确答案是在画任何架构图之前,先重新定义协议本身。
![]()
这个系统的负载形态严重不对称。写入极少:产品经理一天切几次开关。读取无处不在:你集群处理的每个请求至少问一次"这个用户能看到这个功能吗",有时甚至几十次。
10万SDK客户端不是用户数,是进程数。5000个pod,每个pod一个SDK实例,就是5000。移动App日活百万,每台设备跑SDK,就是百万。面试官说"10万"是给中等SaaS一个锚点。但你要追问:SDK跑在后端集群还是终端设备?协议选择完全不同。
问题的核心在于:开关配置很小(KB级),变更极少,怎么让全球每个SDK在1秒内看到新值,同时不把源站压垮?
如果你开始画MySQL和GET /flags/:key端点,就答错了。面试官想让你意识到:这是带发布-订阅形态的读取分发问题,不是CRUD应用。
第一反应是GET /api/flags,SDK每30秒轮询。切换延迟被轮询间隔框死。算笔账:10万客户端,30秒间隔,平均3333请求/秒。可持续。但问题在于启动浪涌:5000个pod的部署90秒完成,几千次轮询堆叠在一起。flag端点的p99延迟飙升,SDK启动超时,应用无标志启动,全是默认值——静默事故。
轮询间隔压到5秒,持续负载2万请求/秒。边缘缓存能扛,但开关切换最坏5秒才传播。面试不及格。
间隔拉到5分钟?事故响应彻底崩了。SRE拍下急停键,等5分钟坏代码才停。出问题的实验产品经理已经在开会了。
规律很明显:轮询强制在传播延迟和源站负载之间做权衡,且随客户端数线性恶化。没有最优解。协议本身错了。
Server-Sent Events。每个SDK一条长连接,启动时打开,服务端保持,只在开关变更时写入。开关切换变成O(N)次写,而非O(N)次轮询。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.