版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://cloud.tencent.com/developer/article/1454560
本文微信公众号文章链接:https://mp.weixin.qq.com/s/LsGEr_RJYfAbGBBlRxJH-Q
NATS是由CloudFoundry的架构师Derek开发的一个开源的、轻量级、高性能的,支持发布、订阅机制的分布式消息队列系统。
NATS的性能非常好,下面是官网的性能对比图:
从图中可以看出Nats的性能远超其他。
对于一个出名的开源组件,可以在网上找到很多对nats的简介,比如
高性能消息中间件——NATS http://dockone.io/article/8312
还有很多类似的文章,这些简介的文章,好处就是,能够快速的了解nats的基本功能。
那接下来看源码
github:https://github.com/nats-io/gnatsd
用工具把代码下载下来
下载了当前的v1.4.1版本
代码量太庞大,若要完整看的话,工作量巨大。
那么有没有一种快速了解其原理的方法呢?
有的,研究一下代码上传历史
从最开始的上传历史开始查看,最终找到了一个最初的原始server
看下代码量
代码量极少,但整个功能流程是一个最小集的功能版本。
此版本,里面就有着nats的精髓原理。只需要分析这个版本,就可以知道其背后的主要原理。
下面就是具体源码的分析。
github.com/nats-io/gnatsd/gnatsd.go
main函数入口,最重要的入口就是s.AcceptLoop()
github.com/nats-io/gnatsd/server/server.go
info为一些基本的参数,不做解释
Server,最重要的结构体。其中info为整个server的参数
sl,sublist,是存储管理subscriptions的模块。稍后介绍。
server的初始化,代码简单
这里才是真正的程序入口。
建立了一个tcp的监听,然后在for循环中进行accept,来一个conn,则处理一个,处理入口s.createClient(conn)
77-82,一些简单的初始化设置
90:c.readLoop() 是链接的具体处理入口
github.com/nats-io/gnatsd/server/client.go
结构体很简单,不做解释
继续跟踪流程,在for循环中,从tcp链接中不停的读取数据,解析处理的地方为c.parse
github.com/nats-io/gnatsd/server/parser.go
此文件为协议解析处理模块
此版本里面,包含的协议为
OP_CONNECT
代码语言:javascript复制OP_PUB
代码语言:javascript复制OP_SUB
代码语言:javascript复制OP_UNSUB
为何说此版本为最简洁的版本。其中包含了最主要的功能,订阅,发布。
看到parse函数,让我想起的是Nginx的http协议解析函数。感兴趣的自己可以去找下。
一个字节一个字节的读取,根据不同字节进入不同的处理流程
pub 流程
pub中的处理流程为c.processPub。以及c.processMsg
剩余的分别为
代码语言:javascript复制c.processSub
代码语言:javascript复制c.processUnsub
代码语言:javascript复制c.processPing
c.processConnect
下面进入pub流程
解析pub的内容
此函数为处理即将发布的消息。
261:查找匹配订阅的用户
266-270:构建msg 头部
278:继续构建
279:sub.deliverMsg(mh, msg) 发送消息
红框中,就是发送写过程。
上面流程是pub流程。
下面看看sub流程
153-167:解析
176:将此subject的订阅者,放入到sublist中管理。
在pub流程中,则是从其中查找订阅者,然后将内容发送到订阅者的。
github.com/nats-io/gnatsd/sublist/sublist.go
A Sublist stores and efficiently retrieves subscriptions.
It uses atree structure and an efficient RR cache
to achieve quick lookups.
这部分不做解释。
那么nats的发布,订阅的基本原理,从上面的简单介绍中,应该已经很明了。
对于对发布,订阅功能需求不是那么多的,完全可以通过此版本进行一些简单的二次开发,来得到自身的消息中间件。
在分析完之后,也大致看了下v1.0.0版本,其中增加了很多功能,但主要流程还是如本文所分析的。
对于大型的开源代码,若是一下看最新版本,可能会由于功能太多,逻辑太复杂,不容易入手。那么从最简单的版本入手,分析其原理,能够节约很多时间。
龚浩华
月牙寂道长
qq:29185807
2019年04月08日