开源代码学习技巧-Nats源码原理分析

版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://blog.csdn.net/screscent/article/details/89140206

本文微信公众号文章链接: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

OP_PUB
OP_SUB
OP_UNSUB

为何说此版本为最简洁的版本。其中包含了最主要的功能,订阅,发布。

看到parse函数,让我想起的是Nginx的http协议解析函数。感兴趣的自己可以去找下。

一个字节一个字节的读取,根据不同字节进入不同的处理流程

pub 流程

pub中的处理流程为c.processPub。以及c.processMsg

剩余的分别为

c.processSub
c.processUnsub
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日

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

Golang 方法接收者为值与指针的区别

Golang 中同时有函数和方法。方法是一个包含了接收者(receiver)的函数,receiver可以是内置类型或者自定义类型struct的一个值或者是一个指...

23710
来自专栏黯羽轻扬

TypescriptServerPlugin_VSCode插件开发笔记3

VS Code能够正确支持JS/TS跳转到定义、补全提示等功能,但仅限于符合Node Module Resolution以及TypeScript Module ...

13330
来自专栏Java编程技术

beego-应用搭建

beego 是一个可以快速开发 Go 应用的 HTTP 框架,使用beego你可以可以快速开发 API、Web 及后端服务等各种应用,其是一个 RESTful ...

17220
来自专栏华章科技

我们对比了5款数据库,告诉你NewSQL的独到之处

对大多数开发人员而言,SQL 以及 MySQL、PostgreSQL 等关系数据库管理系统(即 RDBMS)并不陌生。RDBMS 的基本架构原则已历经了数十年的...

76620
来自专栏后端进阶

Golang 中函数作为值与类型

在 Go 语言中,我们可以把函数作为一种变量,用 type 去定义它,那么这个函数类型就可以作为值传递,甚至可以实现方法,这一特性是在太灵活了,有时候我们甚至可...

11020
来自专栏智慧协同

Chrome新标签无法打开网页的解决办法

37920
来自专栏C/C++基础

Golang map使用注意事项

map 是 Golang 中的方便而强大的内建数据结构,是一个同种类型元素的无序组,元素通过另一类型唯一的键进行索引。其键可以是任何相等性操作符支持的类型, 如...

20520
来自专栏C/C++基础

Golang json解析与生成

JSON(Javascript Object Notation)是一种轻量级的数据交换语言,以文字为基础,具有自我描述性且易于让人阅读。尽管JSON是JavaS...

22810
来自专栏C/C++基础

Golang sync.Mutex 与 sync.RWMutex

Golang中sync包实现了两种锁,Mutex(互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的。

14210
来自专栏智慧协同

Thumbnailator的简介和使用范例

Thumbnailator是一个用来生成图像缩略图的 Java类库,通过很简单的代码即可生成图片缩略图,也可直接对一整个目录的图片生成缩略图。 有了这玩意,就...

15310

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励