【mq】从零开始实现 mq-07-负载均衡 load balance
前景回顾
【mq】从零开始实现 mq-02-如何实现生产者调用消费者?
【mq】从零开始实现 mq-03-引入 broker 中间人
【mq】从零开始实现 mq-06-消费者心跳检测 heartbeat
【mq】从零开始实现 mq-07-负载均衡 load balance
为什么需要负载均衡
大家好,我是老马。
这一节让我们看一下如何实现 MQ 的负载均衡。
为什么需要负载均衡呢?
作用
负载均衡最核心的作用:
(1)可以避免单点故障
(2)可以让请求均分的分散到每一个节点
实现思路
负载均衡实现的方式比较多,最简单的就是随机选择一个。
拓展阅读:
从零手写实现负载均衡 http://houbb.github.io/2020/06/19/load-balance-03-hand-write

MQ 中用到负载均衡的地方
生产者发送
生产者发送消息时,可以发送给任一 broker。
broker 推送给消费者
broker 接收到消息以后,在推送给消费者时,也可以任一选择一个。
消费者的消费 ACK
消费者消费完,状态回执给 broker,可以选择任一一个。
消息黏连
有些消息比较特殊,比如需要保证消费的有序性,可以通过 shardingKey 的方式,在负载的时候固定到指定的片区。
代码实现
生产者发送
统一调整获取 channel 的方法。
@Override
public Channel getChannel(String key) {
// 等待启动完成
while (!statusManager.status()) {
log.debug("等待初始化完成...");
DateUtil.sleep(100);
}
RpcChannelFuture rpcChannelFuture = RandomUtils.loadBalance(this.loadBalance,
channelFutureList, key);
return rpcChannelFuture.getChannelFuture().channel();
}
工具类实现为核心实现:
/**
* 负载均衡
*
* @param list 列表
* @param key 分片键
* @return 结果
* @since 0.0.7
*/
public static <T extends IServer> T loadBalance(final ILoadBalance<T> loadBalance,
final List<T> list, String key) {
if(CollectionUtil.isEmpty(list)) {
return null;
}
if(StringUtil.isEmpty(key)) {
LoadBalanceContext<T> loadBalanceContext = LoadBalanceContext.<T>newInstance()
.servers(list);
return loadBalance.select(loadBalanceContext);
}
// 获取 code
int hashCode = Objects.hash(key);
int index = hashCode % list.size();
return list.get(index);
}
如果指定了 shardingKey,那么根据 shadringKey 进行 hash 判断。
如果没有,则进行默认的负载均衡策略。
Broker 消息推送给消费者
消费者订阅列表的获取:
@Override
public List<Channel> getSubscribeList(MqMessage mqMessage) {
final String topicName = mqMessage.getTopic();
Set<ConsumerSubscribeBo> set = subscribeMap.get(topicName);
if(CollectionUtil.isEmpty(set)) {
return Collections.emptyList();
}
//2. 获取匹配的 tag 列表
final List<String> tagNameList = mqMessage.getTags();
Map<String, List<ConsumerSubscribeBo>> groupMap = new HashMap<>();
for(ConsumerSubscribeBo bo : set) {
String tagRegex = bo.getTagRegex();
if(hasMatch(tagNameList, tagRegex)) {
//TODO: 这种设置模式,统一添加处理 haven
String groupName = bo.getGroupName();
List<ConsumerSubscribeBo> list = groupMap.get(groupName);
if(list == null) {
list = new ArrayList<>();
}
list.add(bo);
groupMap.put(groupName, list);
}
}
//3. 按照 groupName 分组之后,每一组只随机返回一个。最好应该调整为以 shardingkey 选择
final String shardingKey = mqMessage.getShardingKey();
List<Channel> channelList = new ArrayList<>();
for(Map.Entry<String, List<ConsumerSubscribeBo>> entry : groupMap.entrySet()) {
List<ConsumerSubscribeBo> list = entry.getValue();
ConsumerSubscribeBo bo = RandomUtils.loadBalance(loadBalance, list, shardingKey);
final String channelId = bo.getChannelId();
BrokerServiceEntryChannel entryChannel = registerMap.get(channelId);
if(entryChannel == null) {
log.warn("channelId: {} 对应的通道信息为空", channelId);
continue;
}
channelList.add(entryChannel.getChannel());
}
return channelList;
}
核心逻辑:RandomUtils.loadBalance(loadBalance, list, shardingKey); 获取,其他的保持不变。
消费者 ACK
消费者也是类似的,获取 channel 的方式调整如下:
public Channel getChannel(String key) {
// 等待启动完成
while (!statusManager.status()) {
log.debug("等待初始化完成...");
DateUtil.sleep(100);
}
RpcChannelFuture rpcChannelFuture = RandomUtils.loadBalance(loadBalance,
channelFutureList, key);
return rpcChannelFuture.getChannelFuture().channel();
}
小结
负载均衡在分布式服务中,是必备的特性之一。实现的原理并不算复杂。
希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。
我是老马,期待与你的下次重逢。
开源地址
The message queue in java.(java 简易版本 mq 实现) https://github.com/houbb/mq
拓展阅读
rpc-从零开始实现 rpc https://github.com/houbb/rpc
【mq】从零开始实现 mq-07-负载均衡 load balance的更多相关文章
- Oracle RAC 服务器端连接负载均衡(Load Balance)
Oracle RAC服务器端的负载均衡是根据RAC中各节点的连接负荷数情况,将新的连接请求分配到负荷最小的节点上去.当数据库处于运行时,RAC中各节点的PMON进程每3秒会将各自节点的连接负荷数更新到 ...
- Oracle RAC 客户端连接负载均衡(Load Balance)
实现负载均衡(Load Balance)是Oracle RAC最重要的特性之一,主要是把负载平均分配到集群中的各个节点,以提高系统的整体吞吐能力.通常情况下有两种方式来实现负载均衡,一个是基于客户端连 ...
- "高可用方案工具包" high availability toolkit 1.2 公布了。version 1.2 新增了 负载均衡 load balance 的技术实现
"高可用方案工具包" high availability toolkit 1.2 公布了. version 1.2 新增了 负载均衡 load balance 的技术实现. 项目 ...
- 【高可用HA】Nginx (1) —— Mac下配置Nginx Http负载均衡(Load Balancer)之101实例
[高可用HA]Nginx (1) -- Mac下配置Nginx Http负载均衡(Load Balancer)之101实例 nginx版本: nginx-1.9.8 参考来源: nginx.org [ ...
- 【高可用HA】Apache (4) —— Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_jk
Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_jk httpd版本: httpd-2.4.17 jk版本: tomcat-connectors-1.2.41 参考 ...
- 【高可用HA】Apache (3) —— Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_proxy
Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_proxy httpd版本: httpd-2.4.17 参考来源: Apache (1) -- Mac下安装Apac ...
- 章文嵩博士和他背后的负载均衡(LOAD BANLANCER)帝国
案首语: 阿里集团技术大牛,@正明,淘宝基础核心软件研发负责人.LVS创始人.阿里云首席科学家章文嵩博士从阿里离职,去追求技术人生另一段历程,让阿里像我一样的很多热爱技术的工程师都有一丝牵动和感触. ...
- 【消息队列MQ】各类MQ比较
目录(?)[-] RabbitMQ Redis ZeroMQ ActiveMQ JafkaKafka 目前业界有很多MQ产品,我们作如下对比: RabbitMQ 是使用Erlang编写的一个开源的消息 ...
- 消息队列MQ】各类MQ比较
目前业界有很多MQ产品,我们作如下对比:RabbitMQ 是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级 ...
随机推荐
- Netty学习摘记 —— 心跳机制 / 基于分隔符和长度的协议
本文参考 本篇文章是对<Netty In Action>一书第十一章"预置的ChannelHandler和编解码器"的学习摘记,主要内容为通过 SSL/TLS 保护 N ...
- 运筹学之"最大最大决策标准"和"最大最小决策标准"
一.最大最大决策标准的解题思路就是:先比较出所有行的最大值,在最大值中选出最大值,最后这个最大是那行的就选哪个方案 二.最大最小决策标准的解题思路就是:先比较出所有行的最小值,在最小值中选出最大值,最 ...
- 单例模式 | C++ | Singleton模式
Singleton 模式 单例模式(Singleton Pattern)是 C++/Java等语言中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式实 ...
- 一个模型预测控制(MPC)的简单实现
1 生活中的启示 情景如下:你们团队每天早晨开一次例会,主要会议内容是你汇报工作进度,领导根据工作目标和工作进度,制定当天的工作计划,你领到工作计划后开始工作.每天都这样周而复始,从领导的角度看,这件 ...
- AD软件Bug和自我失误的对战
说说我近期犯的两大过失,让我无语的过失,要购买重大责任险呀 一大过失:上图,看了下面的图想必大家都明白了,TOP层元件只有位号和焊盘,丝印边框哪去了? 别急,在这里,下图 为何他跑这里来了呢?我尝试了 ...
- 五款轻量型bug管理工具横向测评
五款轻量型bug管理工具横向测评 最近正在使用的本地bug管理软件又出问题了,已经记不清这是第几次了,每次出现问题都要耗费大量的时间精力去网上寻找解决方案,劳心劳力.为了避免再次出现这样的情况,我决定 ...
- prometheus之查询语言
PromQL(Prometheus Query Language)是 Prometheus 自己开发的表达式语言,语言表现力很丰富,内置函数也很多.使用它可以对时序数据进行筛选和聚合. 一.PromQ ...
- xml中的<![CDATA[]]>和转义字符
被<![CDATA[]]>这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>表示文本内容"<". 此标记用于xml文档中,我们先 ...
- Blazor组件自做六 : 使用JS隔离封装Baidu地图
1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加baidu子文件夹,添加baidumap.js文件 2.1 跟上一篇类似,用代码方式异步加载API,脚本生成新的 body > ...
- Ubuntu安装开发者平台Backstage
Ubuntu安装开发者平台Backstage 什么是Backstage? Backstage是一个构建开发者门户的开源平台.通过支持一个集中的软件分类,Backstage可以保存并发布你的微服务和基础 ...