• 手写MQ框架(一)-准备启程


    一、背景

    很久以前写了DAO框架和MVC框架,前段时间又重写了DAO框架-GDAO(手写DAO框架(一)-从“1”开始,源码:https://github.com/shuimutong/gdao.git)和MVC框架-GMVC(手写MVC框架(一)-再出发,源码:https://gitee.com/simpleha/gmvc.git)。

    之前也尝试过写RPC框架(源码:https://github.com/shuimutong/grpc_beta.git),客户端、服务端的方法调用写完了,但是网络传输没有写。

    其实写框架也好,写博客也好,主要是为了学习。所以现在再开始的时候,我就在思考写什么好?

    我的想法很简单:把目前用到的框架,能自己实现的尽量都实现一遍。站在这个时间点,写哪个框架有两个选择:继续写RPC;写MQ。这两个框架个人认为有很多相似的地方:MQ虽然是异步的,其实也是有“长连接”在连着的。比如订阅方,会有长连接连着MQ的服务端。RPC框架不分订阅、发送,而是客户端、服务端,当客户端找到服务端之后,客户端会尽量和服务端保持连接。

    相比MQ,RPC框架不需要持久化的动作,而MQ不仅需要考虑持久化,还需要考虑如何进行高效的持久化。

    通过一番对比,我最终选择实现MQ框架,以学习序列化、网络传输、高效持久化方面的知识。选择的参照框架是kafka。

    二、如何下手

    既然选择了实现MQ,那从何下手呢?

    先了解一下kafka吧。

    1、mq框架大致流程

    生产方和服务端建立连接,将消息发送到服务端。

    订阅方和服务端建立连接,服务端将订阅方订阅的消息推送给订阅方,或者订阅方自己拉取指定的消息。

    2、了解一下kafka

    1)为什么kafka有如此高的qps

    kafka服务可以部署在机械硬盘上,接收到的每条消息都会存盘,但是qps可以轻松过万,甚至达到百万级别(数据来源于网上,本人暂未亲测)。怎么做到的?

    通过官网可以了解到,我记录的有3点。

    首先,采用磁盘顺序读写。其次,基于java,使用堆外内存,避免gc的干扰。再次,所有数据写两份,防止丢失。此外,还有零拷贝技术等。

    以上各个方面结合起来,最终成就了kafka的英名!

    2)是推消息还是拉消息

    推消息的话,如果消息骤增,可能导致订阅方崩掉,所以kafka采用的是拉的方式。以什么频率拉,由订阅方自己决定。

    其实采用拉消息的方式也有缺点,比如订阅方为了拉消息,就会一直在哪里循环请求。如果没有新消息,订阅方就会频繁的请求,白白浪费资源。

    针对这个循环空请求的问题,kafka增加了一个特性。当拉消息的时候,可以设置:如果没有消息,就先夯住请求,等到消息来了,再返回结果。这样,就能够避免这类问题了。

    3、写框架计划

    在稍微看了kafka之后,感觉这个技术含量还是很高的。虽然上面只列了几点,其实还有很多很重要的点没有提及。但是,我就是要学写。如果等我先把kafka看透之后再写,那可能得等很长时间。(其实我已经磨蹭了很长时间)

    所以我决定,先把架子搭起来。万丈高楼也得平地起!

    1)大致方案

    写服务端,网络传输使用http,序列化使用json(传输字符串,其实无所谓json),数据持久化使用DB。

    虽然使用http传输,但是需要封装成具体的工具,避免客户端自己写请求工具,方便后期升级。

    2)生产方发消息

    消息包括:主题、消息内容

    3)订阅方拉消息

    主题、消息内容、offset(拉多少条)

    4)服务端处理

    消息来了之后,将消息存在DB,编offset。

    拉消息动作,根据offset,返回取的多少条。

    offset的提交应在客户端里进行封装,可先实现为自动提交。

    5)框架组成

    a、服务端

    b、生产消息客户端(服务配置)

    c、消费消息客户端(服务配置)

    6)配置项

    a、服务地址

    b、主题号

    大致计划已定,那就开始实现吧

    三、服务端功能梳理

    1、注册主题号

    校验主题号是否存在,不存在则新增

    2、接收消息

    参数:主题号、消息体

    先校验主题号是否存在,存在则保存消息到DB,然后返回结果

    3、拉消息

    参数:主题号、offset、希望取的消息数量

    校验主题号是否存在,校验offset是否正常,正常则返回希望的消息数量(如果有消息)。

    4、更改offset

    参数:主题号、offset

    校验主题号是否存在,校验offset。

    重复消费功能后期做。

    四、结语

    关于手写MQ,暂时想的就这么多,后面想到其他的再加上。

    先实现一个简易的服务端,接下来就是代码实现了。

    写代码中……

    第一个版本在上周写完了,欢迎指教->手写MQ框架(二)-服务端实现

  • 相关阅读:
    STM32的DMA
    stm32f1的IO,推挽与开漏
    STM32_GPIO配置及库函数讲解——独立按键
    STM32-外部中断学习笔记
    关于STM32的NVIC问题
    梯度下降<1>
    QString toInt()函数慎用
    linux→查看当前系统时间和修改系统当前时间
    oracle函数→数值型函数
    oracle函数→字符型函数
  • 原文地址:https://www.cnblogs.com/shuimutong/p/11707187.html
Copyright © 2020-2023  润新知