为初学者而来~手工最简MQ(二)Broker

本文是为初学者准备的手工构建最简消息队列(MQ)Broker的教程,主要涵盖服务端设计,包括消息文件存储(模仿Kafka但简化逻辑)和网络编程(使用Netty)。服务端分为消息文件存储和网络编程两部分,消息存储在topicname.index和topicname.data文件中,网络编程使用Netty处理生产者和消费者的请求。
摘要由CSDN通过智能技术生成

本文仅展示核心代码,全部代码,请移步:git-soomq

为初学者而来~手工最简MQ(一)设计篇
为初学者而来~手工最简MQ(二)Broker
为初学者而来~手工最简MQ(三)Client

1,服务端

服务端的设计就非常简单了,最核心的就是消息的存取,以及响应生产者和消费者的网络请求
分为2部分:

1.1 消息文件

消息的存储我们参考kafka,并简化其逻辑,因为是最简单的mq,我们只考虑单机的情况的就行,每个topic存储2个文件

topicname.index
topicname.data

.index 文件存储格式为:
消息顺序号:消息截止位置
.data 文件按照顺序存储具体的消息

文件操作:

package com.esoo.mq.server.message;

import com.alibaba.fastjson.JSON;
import com.esoo.mq.common.ProcessorCommand;

import java.io.RandomAccessFile;

/**
 * 为每个topic创建一个对象进行管理
 */
public class MessageFile {
   
    private String topic;
    private Long offset;
    //索引文件
    private RandomAccessFile indexFile = null ;
    //数据文件
    private RandomAccessFile dataFile = null ;

    //追加消息(生产者进行调用)
    public ProcessorCommand appendMsg(ProcessorCommand in){
   

        try {
   
            //加锁,避免竞争,文件乱码
            synchronized (in.getResult().getTopic()) {
   

                //读取index文件最后一行
                String lastLine = readLastLine(indexFile, null);
                int lastOffset = 1;
                //消息体追加到data文件中,并返回文件末尾位置,作为本条消息的offset
                long lastindex =  writeEndLine(dataFile, in.getResult().getBody());
                if (lastLine != null && !lastLine.equals("")) {
   
                    String index[] = lastLine.split(":");
                    lastOffset = Integer.valueOf(index[0]);
                    lastOffset = lastOffset + 1;
                }
                //组装本条消息index 序列号:消息体末尾位置
                String insertMsgIndex = lastOffset + ":" + lastindex + "\t\n";
                writeEndLine(indexFile, insertMsgIndex.getBytes());
                in.setSuccess(true);
            }
        }catch (Exception e){
   
            e.printStackTrace();

            in.setSuccess(false);
            in.setExmsg(e.getMessage());
        }
        return in;

    }

    //读取消息,消费者进行调用
    public ProcessorCommand readMsg(ProcessorCommand in){
   


        try {
   
            synchronized (in.getResult().getTopic()) {
   
                // 消息定位位置
                int seekIn = 0;
                // 消息体大小
                int bodySize = 0;
                //先定位到开始
                indexFile.seek(0);
                String indesMap=null;
                //遍历index文件,找到上一个消息 offset 与本消息offset 进行相减就是消息体大小
                while ((indesMap = indexFile.readLine())!=null){
   
                    String index[] = indesMap.split(":");
                    int inNum = Integer.valueOf(String.valueOf(index[0]).
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值