Message Queue的设计和实现(3)

2017-08-31 12:58 阅读 261 views 次 评论 0 条

Message Queue的设计和实现(3)

上周老王跟大家聊了Message Queue的整体逻辑和架构,本周咱就把整体的架构进行细化,看看每一个组件是怎么样来实现的,以及在实现中有哪些具体的问题。

现在百词斩线上跑的MQ,是老王大约两年前花了2-3周,用java写出来的。整体性能和稳定性都还不错,已经在线上稳定的运行了两年多了,每天数以亿计的提交也都还什么问题。

从老王实现Message Queue的经验来看,整个MQ实现完成后,在课堂上学过的网络、操作系统等原理的课程都会涉及到落地。所以,如果有机会的话,大家也可以去自己实现一个简单的MQ,找找感觉。

好了,言归正传,我们开始今天的话题吧。

上周我们把MQ的架构梳理成了三大模块:

细化他们得到如下的功能逻辑:

今天我们先聊聊Recv-Module。这个模块是MQ的入口,所以他需要实现:

· 功能

· 接收数据生产者提交的数据包

· 根据协议,解析数据包格式,提取数据

· 难点

· 大量的网络连接

· 协议的设计和解析

所以,今天我们就会围绕这这几个点来分析。

1、网络连接

对于网络连接,现在有很多成熟的网络模型:

· 朴素的线程模型

· select模型

· poll模型

· epoll模型

这些模型各有自己的优缺点,比如线程模型要依赖线程个数、select要做fd的拷贝和遍历等等。但是在不同的场景下,他们都有自己的适应空间。现在应用的最多的当然是epoll模型,用的事件驱动方式,来hold住大量连接。具体这几个模型,大家可以去查阅一下相关资料,都讲的非常详细。

而对于这些模型,很多开源软件都已经实现的比较好,比如用Java实现的minanetty等等。我曾经也读过他们部分的源代码。为了保持整个体系架构的统一,老王用的是fbthrift框架里面的ThreadedSelectorServer。他用的是java提供的nioselector,实际底层也就是epoll模型。大家实现的时候,也可以自己用最原始的epoll相关调用来实现。

2、数据协议

当我们调用read()或者recv()函数,获取下来二进制的data以后,我们就需要对这个data按照之前我们定义的格式进行解析了。那这个data可以是很多种格式:

· 字符串(base16或者base64编码)

· Json

· protobuf

· thrift-data

……

格式可以是任意多的。不过对于不同格式,我们有两个方面的东西需要去考虑:

· 数据包的大小

· 编解码的CPU消耗

对于网络传输,特别是大量的网络数据传输,数据包当然是越小越好。但是数据包越小,有可能带来内容编码(或者压缩)对于系统的消耗变大。大家可能有这样的经验,就是如果压缩文件被压的越小,解压消耗的时间会越多。这就要求我们在这两者之间达到一个平衡。

base16或者base64大家应该都已经非常熟悉了,就是对内容做16进制或者64进制编码;

JSON也是大家平时用的再多不过的数据协议了,特别是javascript和服务器交互,用的极多;

对于googleprotobuf,老王没实际用过,但是看过评测。他的压缩率和执行效率都非常高,非常适合做数据传输;

fbthrift则实现了很多个版本的数据协议,包括:JsonBinaryCompact等协议。这些协议老王都看过源代码,之前还跟大家做过zigzag算法的分享。现在我们用的就是compact协议。压缩率和效率都非常不错。

好了,有了上述两个技术框架,我们基本上就解决了Recv-Module的设计架构问题。那具体落地到实现上怎么弄呢?有以下的一些方法:

· 自己写一个原生的epoll + JSON

· 用高性能网络框架(如:minanetty + protobuf

· 直接使用thrift框架(已经集成了网络模型和数据协议)

老王是懒人,所以用的最后一种方式,挺好使的。大家如果想写demo,可以用thrift最简单的模型试试手,挺方便的。

好了,今天的内容大体就扯到这里。下期,我们就会讲述MQ最核心的那一部分:数据序列化模块,大家有兴趣的话,欢迎关注哦~


版权声明:本文版权由木秀林网所有,转载请保留链接:Message Queue的设计和实现(3)
分类:技术分享 标签:

发表评论


表情