夏溪辰的博客

xiaxichen's blog

Caddy 源码分析 启动流程与Event事件通知

2023-12-03

Caddy 源码分析 启动流程与Event事件通知

介绍

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

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

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

80F5F012-F4D9-4B2E-B4B7-31C10A30E86A.png

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

main.go

├── caddy # caddy主目录
│   ├── caddymain
│   │   ├── run.go # 运行文件
│   │   └── run_test.go
│   ├── main.go # 主文件
│   └── main_test.go

其中run.go 上篇笔记中已经分析 Caddy 源码分析 run.go

main.go

var run = caddymain.Run // replaced for tests

func main() {
	run()
}

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

启动流程

启动 caddy 的流程

0FCE8CBE-53ED-4D45-90AB-E84C657D1C82.jpg

caddyfileLoader 加载 caddyfile 配置 --> 生成 Input 信息 Context --> 生成 Server

caddyfile 示例

4F9367D6-0B3B-4C9D-B671-94ACC6535F74.png

Instans 是运行操作的 Server 实例,可以看到几个主要的操作都是在他身上

Server 两种监听模式 TCP UDP

启动服务器

发送 StartupEvent

// Executes Startup events 注册开始事件钩子(即插件相关启动都在此处注册 很多魔改框架都是改动的这里)
caddy.EmitEvent(caddy.StartupEvent, nil)

读取配置文件

caddyfileinput, err := caddy.LoadCaddyfile(serverType)

启动

instance, err := caddy.Start(caddyfileinput)

发送 InstanceStartupEvent

caddy.EmitEvent(caddy.InstanceStartupEvent, instance)

Start()

// Start your engines 
instance, err := caddy.Start(caddyfileinput) 
if err != nil { 
    mustLogFatalf("%v", err) 
}

C3A9BC8B-2FC4-4F53-9291-12AFA862F3B1.jpg

这里除了 Instance 之外还有两个新名词

Controller(控制器):它是用来帮助 Directives(指令) 设置它自身的,通过读取 Token,这里的 Directives 实际上对应的就是上文所说的 caddyfile 中的配置文件选项。

这一点请参照 Caddy(三)中 Loader 下的 excuteDirective 理解。

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

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