Prospect Review

[mq] Implement mq-01-producer and consumer startup from scratch

[mq] To implement mq-02 from scratch - how to implement a producer calling a consumer?

[mq] Implementing mq-03-introduction of broker middlemen from scratch

[mq] Realize mq-04-start detection and optimization from scratch

In the previous section, we introduced the middleman broker to decouple message producers and consumers.

In this section, we optimize the initialization code to facilitate later expansion and maintenance.

启动检测

Producer startup optimization

Start the implementation

The overall implementation adjustment is as follows:

 @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);
    }
}

Does it look much cooler than before?

But complexity only shifts, not disappears .

The answer is to encapsulate it into initChannelFutureList.

initChannelFutureList

Because it is used by both producers and consumers.

So we put it in a unified tool class first, and the implementation itself is much the same as before.

 /**
 * 初始化列表
 * @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;
}

The check here is to avoid two situations:

(1) A certain broker is unavailable

(2) There is no broker information available.

Consumer Initiated Optimization

Consumers connect brokers and producers similarly.

Here is just to put the implementation, do not do more details.

 @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);
    }
}

summary

The content of this section is particularly simple, and the initialization part has been optimized to facilitate later maintenance and expansion.

I hope this article is helpful to you. If you like it, please like, collect and forward it.

I'm an old horse, and I look forward to seeing you again next time.

open source address

The message queue in java.(java simple version mq implementation) https://github.com/houbb/mq

Extended reading

rpc - Implementing rpc from scratch https://github.com/houbb/rpc


老马啸西风
191 声望34 粉丝