如何基于Key/Value键值对动态路由消息到微服务实例
可行实现方案
你需要的动态路由能力有三种落地性很高的方案,可根据你的集群规模、改造成本选择:
1. 基于动态规则反向代理实现(完全符合你的需求)
目前主流的七层反向代理都支持热更新路由规则,不需要重启实例,推荐两个成熟选型:
- Envoy
借助其原生支持的*RDS(路由发现服务)*能力实现动态路由:- 自研一个轻量RDS服务,接收hardware gateway实例的上报:每当设备和某一个gateway实例建立/断开websocket连接时,gateway主动上报设备UUID和自身实例地址到RDS服务
- Envoy配置为从RDS服务动态拉取路由规则,规则配置为匹配请求头中的
X-IoT-Device-UUID字段,转发到对应的gateway实例 - 所有上游服务的推送请求统一发送到Envoy入口,只需要在请求头带上目标设备的UUID即可,不需要感知任何KV存储、gateway实例信息
该方案的规则更新延迟通常低于1s,路由转发性能损耗小于5%,适合大规模IoT集群使用。
路由规则示例:
routes: - match: headers: - name: X-IoT-Device-UUID exact_match: "xxx-xxx-设备UUID" route: cluster: "hardware-gateway-实例1" - APISIX/OpenResty
比Envoy更轻量的选型,不需要单独维护RDS服务:- 每当设备连接状态变更时,hardware gateway直接调用APISIX的Admin API,新增/更新/删除对应UUID的路由规则
- 规则默认存在APISIX内置的etcd中,自动同步到所有APISIX节点
该方案改造成本极低,1000条以下路由规则的更新延迟可控制在200ms以内,适合中等规模集群使用。
2. 现有KV架构优化方案(改造成本最低)
如果不想引入新的反向代理组件,可在现有架构基础上做最小改动解决上游依赖问题:
- 新增一层无状态的路由转发层,该层唯一依赖你现有的KV存储,同时加本地LRU缓存缓存UUID到实例的映射关系
- 所有上游服务的推送请求统一发送到转发层,由转发层负责查询映射、路由到对应的gateway实例
- 缓存失效策略可设置为10s/30s,就算出现缓存失效,转发失败后重试一次查最新KV即可,因为设备漂移本身是低概率事件,整体额外延迟可控制在1ms以内,上游服务完全不需要感知KV存储的存在。
关于消息代理的补充
你调研后认为RabbitMQ这类消息代理不适配是正确的:这类方案需要为每一个设备绑定专属队列,设备漂移时要做队列解绑、重绑定操作,十万级以上设备规模下,队列资源开销、规则更新开销都会远高于反向代理方案。
内容的提问来源于stack exchange,提问作者Pebabom
相关产品推荐
相关产品推荐

