【mq】从零开始实现 mq-04-启动检测与实现优化
前景回顾
【mq】从零开始实现 mq-02-如何实现生产者调用消费者?
【mq】从零开始实现 mq-03-引入 broker 中间人
上一节我们引入了中间人 broker,让消息的生产者和消费者解耦。
这一节我们对初始化代码进行优化,便于后期拓展维护。

生产者启动优化
启动实现
整体实现调整如下:
@Override
public synchronized void run() {
this.paramCheck();
// 启动服务端
log.info("MQ 生产者开始启动客户端 GROUP: {}, PORT: {}, brokerAddress: {}",
groupName, port, brokerAddress);
try {
//channel future
this.channelFutureList = ChannelFutureUtils.initChannelFutureList(brokerAddress,
initChannelHandler(), check);
// register to broker
this.registerToBroker();
// 标识为可用
enableFlag = true;
log.info("MQ 生产者启动完成");
} catch (Exception e) {
log.error("MQ 生产者启动遇到异常", e);
throw new MqException(ProducerRespCode.RPC_INIT_FAILED);
}
}
看起来是不是比起原来清爽很多呢?
但是复杂性只会转移,不会消失。
答案就是封装到 initChannelFutureList 中去了。
initChannelFutureList
因为这里是生产者、消费者都会用到。
所以我们先放在统一的工具类中,实现本身和以前大同小异。
/**
* 初始化列表
* @param brokerAddress 地址
* @param channelHandler 处理类
* @param check 是否检测可用性
* @return 结果
* @since 0.0.4
*/
public static List<RpcChannelFuture> initChannelFutureList(final String brokerAddress,
final ChannelHandler channelHandler,
final boolean check) {
List<RpcAddress> addressList = InnerAddressUtils.initAddressList(brokerAddress);
List<RpcChannelFuture> list = new ArrayList<>();
for(RpcAddress rpcAddress : addressList) {
try {
final String address = rpcAddress.getAddress();
final int port = rpcAddress.getPort();
EventLoopGroup workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<Channel>(){
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline()
.addLast(new LoggingHandler(LogLevel.INFO))
.addLast(channelHandler);
}
})
.connect(address, port)
.syncUninterruptibly();
log.info("启动客户端完成,监听 address: {}, port:{}", address, port);
RpcChannelFuture rpcChannelFuture = new RpcChannelFuture();
rpcChannelFuture.setChannelFuture(channelFuture);
rpcChannelFuture.setAddress(address);
rpcChannelFuture.setPort(port);
rpcChannelFuture.setWeight(rpcAddress.getWeight());
list.add(rpcChannelFuture);
} catch (Exception exception) {
log.error("注册到 broker 服务端异常", exception);
if(check) {
throw new MqException(MqCommonRespCode.REGISTER_TO_BROKER_FAILED);
}
}
}
if(check
&& CollectionUtil.isEmpty(list)) {
log.error("check=true 且可用列表为空,启动失败。");
throw new MqException(MqCommonRespCode.REGISTER_TO_BROKER_FAILED);
}
return list;
}
这里的 check 为了避免 2 种情况:
(1)某一个 broker 不可用
(2)没有可用的 broker 信息。
消费者启动优化
消费者连接 broker 和生产者是类似的。
这里只是放一下实现,不做更多的赘述。
@Override
public void run() {
// 启动服务端
log.info("MQ 消费者开始启动服务端 groupName: {}, brokerAddress: {}",
groupName, brokerAddress);
//1. 参数校验
this.paramCheck();
try {
//channel future
this.channelFutureList = ChannelFutureUtils.initChannelFutureList(brokerAddress,
initChannelHandler(),
check);
// register to broker
this.registerToBroker();
// 标识为可用
enableFlag = true;
log.info("MQ 消费者启动完成");
} catch (Exception e) {
log.error("MQ 消费者启动异常", e);
throw new MqException(ConsumerRespCode.RPC_INIT_FAILED);
}
}
小结
这一小节的内容特别简单,对初始化部分做了优化,便于后期维护拓展。
希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。
我是老马,期待与你的下次重逢。
开源地址
The message queue in java.(java 简易版本 mq 实现) https://github.com/houbb/mq
拓展阅读
rpc-从零开始实现 rpc https://github.com/houbb/rpc
【mq】从零开始实现 mq-04-启动检测与实现优化的更多相关文章
- ubuntu11.04启动 及虚拟文件系统
虚拟文件系统(VFS)是由Sun microsystems公司在定义网络文件系统(NFS)时创造的.它是一种用于网络环境的分布式文件系统,是允许和操作系统使用不同的文件系统实现的接口.虚拟文件系统(V ...
- Android 性能优化之内存泄漏检测以及内存优化(中)
https://blog.csdn.net/self_study/article/details/66969064 上篇博客我们写到了 Java/Android 内存的分配以及相关 GC 的详细分析, ...
- 理解Tomcat架构、启动流程及其性能优化
PS:but, it's bullshit ! 备注:实话说,从文档上扒拉的,文档地址:在每一个Tomcat安装目录下,会有一个webapps文件夹,里面有一个docs文件夹,点击index.html ...
- website 性能检测 & 前端性能优化
website 性能检测 & 前端性能优化 https://cdn.xgqfrms.xyz/ https://mobile.xgqfrms.xyz/ PageSpeed Insights ht ...
- 四大MQ比较及MQ详解
消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之 一.当今市面上有很多主流的消息中间件,如老牌的Activ ...
- Ubuntu 16.04 启动错误 "a start job is running for hold until boot process finishes up"
老司机也差点翻船... 升级16.04的时候,将默认启动管理器(default display manager)选为gm3(gnome3)了(应该使用默认的lightgm)如果改成gm3,好像是nvi ...
- 【消息队列MQ】各类MQ比较
目录(?)[-] RabbitMQ Redis ZeroMQ ActiveMQ JafkaKafka 目前业界有很多MQ产品,我们作如下对比: RabbitMQ 是使用Erlang编写的一个开源的消息 ...
- U盘制作Ubuntu15.04启动盘失败
先用ubuntu15.04光盘在已有xp的电脑上安装成功 随后在Ubuntu安装labview说glibc没安装 但是ldd --version显示是安装的新版的 后来怀疑是86_64的原因 ...
- Ubuntu 18.04 启动root账号并授权远程登录
Ubuntu 18.04 刚刚上市2个月,下载安装,尝尝鲜~ 安装界面看上去舒服许多, 安装的速度也较之前17.04 和16.04 都快了许多.抱歉,未截图. Ubuntu 安装完成后默认不启动roo ...
随机推荐
- Redis String Type
Redis字符串的操作命令和对应的api如下: set [key] [value] JedisAPI:public String set(final String key, final String ...
- 什么是HTML 5?
HTML 5是HTML的新标准,其主要目标是无需任何额外的插件如Flash.Silverlight等,就可以传输所有内容.它囊括了动画.视频.丰富的图形用户界面等. HTML5是由万维网联盟(W3C) ...
- MyBatis Plus 2.3 个人笔记-03-Active Record
AR 语法糖 是一种领域模型模式,特点就是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一条记录 实现AR [在代码生成器中可以添加配置] import com.baomidou ...
- STM32 之 HAL库(固件库)
1 STM32的三种开发方式 通常新手在入门STM32的时候,首先都要先选择一种要用的开发方式,不同的开发方式会导致你编程的架构是完全不一样的.一般大多数都会选用标准库和HAL库,而极少部分人会通过直 ...
- Creating a File View
创建文件视图 为了映射一个文件的数据到进程的虚拟内存,你必须创建一个文件的视图.MapViewofFile和MapViewofFileEX使用CreateFileMapping返回的句柄,在虚拟地址空 ...
- js中一个函数调用另一个函数变量;判断鼠标按住/手指左右滑动
<script> function myFunction() { var x1=event.clientX;//只需要将被调用的变量前的var删除即可在下个函数调用: document.g ...
- ES6-11学习笔记--深拷贝与浅拷贝
Object.assign,只是进行了浅拷贝,并没有进行深拷贝. 而且会在复杂结构当中会丢失属性,如下代码: let target = { a: { b: { c: 3 }, e: 4, f: 5, ...
- C#编写程序,用 while 循环语句实现下列功能
编写程序,用 while 循环语句实现下列功能:有一篮鸡蛋,不止一个,有人两个两个数,多余一个,三个三个数,多余一个,再四个四个地数,也多余一个,请问这篮鸡蛋至少有多少个. 代码: using Sys ...
- 主线程中的Looper.loop()为什么不会造成ANR
引子: 正如我们所知,在android中如果主线程中进行耗时操作会引发ANR(Application Not Responding)异常. 造成ANR的原因一般有两种: 当前的事件没有机会得到处理(即 ...
- kali添加开机自启[亲测有效]
kali添加开机自启 采用systemd的方法,kali默认是没有rc.local的,需要自己创建.本方法也适用于ubuntu 18.04 64bit 改写rc-local.service 文件 先从 ...