码云仓库:https://gitee.com/zhangxiaofan08/springboot-apache-dubbo.git
公司是做智慧酒店的,原来项目技术栈是Kotlin + Vertx + NSQ实现分布式服务,代码中充满了异步回调,阅读起来十分不遍,而且在国内使用不成熟,排查问题也十分痛苦,Vertx性能高但对开发人员要求也高,若不小心在主线程里阻塞了代码会得不偿失。NSQ的消息不能保证顺序,也没有返回值,不注意的话也够喝一壶的了。其实Vertx中有EventBus事件总线类似于队列的功能,但项目没有采用,不知道为啥,可能还是当初使用的不熟练吧。后来公司新分出来一个项目,大胆决定放弃原有技术栈,采用SpringBoot + Dubbo的方式。
原项目中有一个DevControl服务(简称DC),DC有专属到dcCode,DC服务启动时会向NSQ订阅一个基于自身dcCode的Channel,上层调用DC控制时会从设备信息中获取所属的dcCode,然后发布基于此dcCode的NSQ Channel。文件结构如下:
Hotel-------->Room-------->DevName
| | |
DC--------->HostMAC------->DevID
采用Dubbo后,遇到的一个大问题就是无法保证控制的设备控制指令准确的发送到指定到DC,经过两天摸索,终于调通,现简单记录一下Demo。
1、Demo架构
SpringBoot + Dubbo + zookeeper,我测试环境zookeeper是docker安装的,方便快捷。项目结构如下:

api模块是公共模块,提供公共api和其他通用类,其他模块在pom.xml引入api模块即可使用。




2、自定义负载均衡
下面解析一下自定义负载均衡的实现类DcCodeBalance,继承了AbstractLoadBalance,重写doSelect方法

3、测试
启动3个provider,provider-1和provider-3的dcCode都为dcCode1(集群),provider-2的dcCode为dcCode2:
当consumer的RpcContext.getContext().setAttachment("dcCode", "dcCode1")时,provider-2没有数据,provider-1和provider-3有数据,且是随机分布的;
当consumer的RpcContext.getContext().setAttachment("dcCode", "dcCode2")时,只有provider-2有数据。
当consumer的RpcContext.getContext().setAttachment("dcCode", "dcCode3")时,consumer抛出指定异常。
4、总结
小菜🐔第一次写分享文档,肯定会有很多不足,希望能抛砖引玉,让小伙伴们少走弯路。也欢迎大家来讨论。
网友评论