Caddy源码阅读(二)启动流程与 Event 事件通知


Caddy源码阅读(二)启动流程与 Event 事件通知

https://github.com/caddyserver/caddy

Caddy 整个软件可以说是由不同的 插件 堆砌起来的。自己本身仅提供 Plugin 的注册运行逻辑和 Server 的监听服务功能。

学习 caddy 的源码,实际上是学习 如何构建一个 松耦合的 抽象 Plugin 设计,即模块化插拔的做法。

所以我们的源码阅读,围绕 Caddy 为 Plugin 提供的基础设施,和 Plugin 自身逻辑。

caddy-overview (2).png
下面我们从第一步,启动流程开始阅读。
之后的路径应该是  Caddyfile 的解析,解析出的 配置文件如何消费,配置完成的服务器如何服务。

上一篇文章阅读完成

main.go 的代码

image.png

通过改变 run 变量的值来方便测试,可以学习一下。

Event 理解

// Executes Startup events
caddy.EmitEvent(caddy.StartupEvent, nil)

读取配置文件:参照我的接下来的文章 Caddy-解析Caddyfile

caddyfileinput, err := caddy.LoadCaddyfile(serverType)

启动:

instance, err := caddy.Start(caddyfileinput)

发送 InstanceStartupEvent

caddy.EmitEvent(caddy.InstanceStartupEvent, instance)

Caddy(三)中 Loader 下的 excuteDirective 理解。

Token :是 caddy 自己的 词法分析器 解析 caddyfile 配置文件出的选项的标记。

这一点请Caddy(三)中 Loader 中的 Parser 理解

caddy.Start.svg

我们来看顺序,第一遍从顶向下看。

第一个是 Input,这是 caddyfile 的变量结构,他可以通过 Start()方法新建实例 Instance

Instance 通过从 caddyfile 读取到信息的 Input 生成 Context

携带信息的 Context 承担 新建 Server 的任务

Context 读取 caddyfile 解析出的 ServerBlock 配置服务器

ServerBlock 包含 不同的 Tokens 他们会转换为 Directive

Directive 会被 Controller 消费,用于配置插件 安装到服务器上

值得注意的是 Controller  更改的是 Instance 
对于 http 服务器来说还会增加 http 服务的中间件

如果不理解,首先记住 caddy 是 **配置的 **模块化的服务器,

通过 caddyfile 配置 -> caddyfile
读取它 -> Loader
解析配置目标-> token & directives
进行配置 -> controller & setup
启动 -> instance & Start()

记住这个流程就能理解了。

caddy/plugin.go 包中

// eventHooks is a map of hook name to Hook. All hooks plugins
// must have a name.
eventHooks = &sync.Map{}

是一个保存所有 plugin hook 的 sync.Map{}

这个标准包的 Map 是并发安全的, 通常我们使用 Load() 或者 LoadOrStore() 方法存读信息,Range() 方法遍历,如果你需要,可以引入你的 Go 程序中。

Caddy源码阅读(一)Run详解
和之后的
Caddy源码阅读(三)Caddyfile 解析 by Loader & Parser
Caddy源码阅读(四)Plugin & Controller 安装插件
Caddy源码阅读(五) Instance & Server
caddy-plugins(一)自定义插件
caddy-plugins(二)caddy-grpc 一个插件实例