人生需要总结

手写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框架(二)-服务端实现

posted @ 2019-10-20 16:52  水木桶  阅读(1979)  评论(0编辑  收藏  举报