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

Caddy-用Go写的新一代可扩展WebServer 前几天用 Netmaker 的时候发现它用 Caddy 替换掉了 Nginx,用了后发现确实简单好用,就安利一下。 Caddy 是一个强大的、可扩展的平台,用 Go 编写,可以为你的站点、服务和应用程序提供服务。如果你是 Caddy 的新手,你服务网络的方式将会改变。 引言 大多数人使用 Caddy 作为网络服务器或代理,但在其核心,Caddy 是一个服务器的服务器(a server of servers)。通过必要的模块,它可以承担任何长时间运行的进程的角色! 配置是动态的和可通过 Caddy 的 API 阅读详情

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

Preface

Caddy 是 Go 语言构建的轻量配置化服务器。https://github.com/caddyserver/caddy

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

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

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

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

Overview

Package

这是 caddy 包的结构
image.pngimage.png

main.go

一切的开始 —
我们查看 在 caddy 文件夹下的 main.go 函数。

这是 上图 caddy 文件夹下的目录结构。

其中 run.go 我们在上一篇文章阅读完成

main.go 的 Trick

在 caddy 文件夹中的 main 函数启动 caddy 服务器。实际运行的是 run.go 中的文件,这是方便测试使用
看 main.go 的代码

image.png

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

启动流程

启动 caddy 的流程
在这里插入图片描述
caddyfileLoader 加载 caddyfile 配置 =》生成 Input 信息
Context =》 生成 Server

caddyfile 示例

caddyfile 简单示例:
image.png

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

Server 两种监听模式 TCP UDP

我们首先关心的是 Start() 启动服务器。

启动服务器

发送 StartupEvent, 参照下文中 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)

Start()

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

阅读完代码,画一张图帮助理解
![屏幕快照 2019-08-04 下午6.35.03.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAxOS9wbmcvMTc2MjgwLzE1NjQ5MjUxMTQ0MjctMmE2N2ExNmEtNGZhYS00MDY0LWJiZmEtNGZkYzAzMWFhZWExLnBuZw?x-oss-process=image/format,png#align=left&display=inline&height=858&name=屏幕快照 2019-08-04 下午6.35.03.png&originHeight=858&originWidth=652&size=127542&status=done&width=652)

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

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

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

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

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

在这里插入图片描述
我们来看顺序,第一遍从顶向下看。

第一个是 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()

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

Event 事件通知启动插件

在这里插入图片描述

引入

我们看到,在 caddy 的 run.go 中有一行代码是

caddy.EmitEvent(caddy.StartupEvent, nil)

这就是 caddy 中的 事件通知系统,通知的是所有的 plugin。

变量

在 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 程序中。

Logic

看内在实现

// EmitEvent executes the different hooks passing the EventType as an
// argument. This is a blocking function. Hook developers should
// use 'go' keyword if they don't want to block Caddy.
func EmitEvent(event EventName, info interface{}) {
	eventHooks.Range(func(k, v interface{}) bool {
		err := v.(EventHook)(event, info)
		if err != nil {
			log.Printf("error on '%s' hook: %v", k.(string), err)
		}
		return true
	})
}

很简单,上文提过,eventHooks.Range 是遍历信息,会遍历所有保存的 EventHook 函数并运行。

那么 Plugin 想使用接收某一个事件通知做相应操作的时候,只需把自己的 EventHook 函数注册到这个 map 中

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

使用 RegisterEventHook 注册
type EventHook func(eventType EventName, eventInfo interface{}) error

// RegisterEventHook plugs in hook. All the hooks should register themselves
// and they must have a name.
func RegisterEventHook(name string, hook EventHook) {
	if name == "" {
		panic("event hook must have a name")
	}
	_, dup := eventHooks.LoadOrStore(name, hook)
	if dup {
		panic("hook named " + name + " already registered")
	}
}

那么可以监听哪些事件呢?在 Plugin 中有定义常量

// Define names for the various events
const (
	StartupEvent         EventName = "startup"
	ShutdownEvent                  = "shutdown"
	CertRenewEvent                 = "certrenew"
	InstanceStartupEvent           = "instancestartup"
	InstanceRestartEvent           = "instancerestart"
)

启动,关闭,刷新证书,这里提到的 Instance 是 caddy 中的 Server 实例

结语

我们概览了 caddy 的 run 和 Start 启动流程,接下来我们会继续深入了解 Caddy 每个部分流程。
可以看之前的文章
Caddy源码阅读(一)Run详解
和之后的
Caddy源码阅读(三)Caddyfile 解析 by Loader & Parser
Caddy源码阅读(四)Plugin & Controller 安装插件
Caddy源码阅读(五) Instance & Server
caddy-plugins(一)自定义插件
caddy-plugins(二)caddy-grpc 一个插件实例

从Tinyhttpd源码剖析HTTP服务器核心原理与C语言网络编程实践 HTTP服务器是Web技术的基石,它遵循客户端-服务器模型,通过HTTP协议在网络上传输超文本数据。其核心原理在于监听端口、解析请求、处理业务逻辑并返回响应,这一过程涉及网络套接字、多进程/线程并发及协议解析等底层技术。理解服务器工作原理对于进行Web性能优化、安全加固及协议设计具有重要价值,广泛应用于网站托管、API服务及微服务架构等场景。本文以经典教学项目Tinyhttpd为切入点,通过分析其约500行C语言实现的**多进程模型**和**HTTP/1.0协议**精简实现,深入拆解从请求接受到响应返回的完 阅读详情

相关推荐

智能家居灯光中枢lighthamhead:多协议统一控制与本地自动化实战

智能家居的核心在于设备间的协同与自动化,而灯光控制是其中体验最直观的环节。其技术原理在于通过统一的抽象层,将不同通信协议(如Wi-Fi、蓝牙Mesh、Zigbee)的设备接入同一个控制平台,实现集中管理。这种架构的技术价值在于打破了品牌壁垒,实现了跨生态的联动,并依托本地优先原则,确保了控制的低延迟与数据隐私。典型的应用场景包括基于人体感应的自动照明、多设备联动的场景模式以及模拟自然光节律的自适应调光。本文以开源项目lighthamhead为例,深入探讨了如何构建一个专注于**智能照明**的本地控制中枢,通

cuanwei9356的博客 533

一个比 Nginx 还简单的 Web 服务器

企业级的 Web 服务器非常多,Nginx、Tomcat、Apache、IIS、FastAPI、Flask 等。今天松哥再给大家介绍一个开源的 Web 服务器,这款服务器具备自动 HTTPS 功能和高度可配置性,它的名字是:Caddy。Caddy 是一个 Go 编写的 Web 服务器,类似于 Nginx,Caddy 提供了更加强大的功能,随着 v2 版本发布,Caddy 已经可以作为中小型站点 Web 服务器的另一个选择。Caddy 轻量简单,对新手也比较友好,我们一起来看下 Caddy 的用法吧。

江南一点雨的专栏 1万+

Caddy实践 | Docker环境下使用Caddy快速部署web服务器

Caddy实践 | Docker环境下使用Caddy快速部署web服务器

jks212454的博客 3304

为什么个人项目我更推荐使用Caddy?

最近我把自己一些项目里面的nginx换成了caddy,运转相当良好,比较开心,所以写了这篇文章,也推荐给大家使用。Caddy。

ice breaker's blog 2987

简单使用Caddy

环境:CentOS 7系统。

janthinasnail的博客 3306

RGB接口电容触摸屏驱动(一)模块介绍

RGB接口电容触摸屏驱动(一)模块介绍

杰克拉力船长个人博客 7879

【Caddy】:现代化、自动 HTTPS 的 Web 服务器新星

Caddy是一个由 Go 语言开发的开源 Web 服务器,它以“自动化、安全、现代✅自动 HTTPS(内置 Let’s Encrypt 证书签发)✅简单配置语法(Caddyfile)✅跨平台支持✅内置反向代理、静态文件托管、重定向、负载均衡等功能Caddy 作为现代 Web 服务生态的一股新势力,凭借自动 HTTPS、配置简单、功能全面、模块化架构,成为很多开发者和运维的首选。无论你是独立开发者、前端工程师,还是 DevOps 从业者,Caddy 都值得一试!

Huazzi的博客 2497

达梦DCA2023年10月培训及考试总结

本次培训共分三天,培训内容不单单是DCA的单机安装、实例创建、库表操作等,培训内容是把关系型数据库的理论及DM8的产品结合起来讲,很实用。具体的考试则是需要个人大量的线下练习,考试总体而言都是培训讲过的内容,只要用心听,好好练习,哪怕是没有计算机基础的童鞋也能考过。提示:以下是本篇文章正文内容,下面案例可供参考总体而言,本次考试不是很难,用心准备,考前认真听讲,考后多次练习,基本都能通过。

qinjuao的博客 2321

[运维] caddy 介绍

自动化 HTTPS:Caddy 默认集成了自动化的 HTTPS 功能,使你可以轻松地为你的网站启用和管理 SSL/TLS 加密。HTTP/2 和 HTTP/3 支持:Caddy 支持最新的 HTTP/2 和 HTTP/3 协议,以提供更快的网站加载速度和更高的性能。Caddy 是一个开源的跨平台服务器软件,旨在提供简单易用的配置和自动化的 HTTPS 功能。日志和监控:Caddy 提供了灵活的日志记录功能,允许你将访问日志输出到不同的目标,并支持集成监控工具进行性能分析和故障排除。

梦醒贰零壹柒 962

Unity FPS射击控制系统:数据驱动的武器行为解耦方案

在Unity第一人称射击(FPS)开发中,射击系统常因输入、状态、行为耦合导致连发异常、换弹冲突与网络同步失准。其本质是缺乏对‘武器行为’(如后坐力曲线、弹药逻辑)与‘射击控制’(如输入合法性校验、冷却调度)的正交分离。本方案基于ScriptableObject实现WeaponData数据资产化,配合ShootingController状态机服务,达成输入解耦、运行时参数可调、协程受控、网络预测友好等工程目标。适用于中大型FPS项目架构升级与数据驱动转型,尤其解决Unity InputSystem与物理反馈

weixin_30536861的博客 613

数字IC后端手把手实战教程 | Innovus verify_drc VIA1 DRC Violation解析及脚本自动化修复方案

数字IC后端实战项目案例之Innovus verify_drc DRC Violation脚本自动化修复方案

weixin_37584728的博客 4053

启动go服务_Caddy源码阅读(二)启动流程与 Event 事件通知

PrefaceCaddy 是 Go 语言构建的轻量配置化服务器。https://github.com/caddyserver/caddyCaddy 整个软件可以说是由不同的 插件 堆砌起来的。自己本身仅提供 Plugin 的注册运行逻辑和 Server 的监听服务功能。学习 caddy 的源码,实际上是学习 如何构建一个 松耦合的 抽象 Plugin 设计,即模块化插拔的做法。所以我们的源码阅读,...

weixin_28675661的博客 379

Bellhop海底地形仿真入门:从MATLAB数据导入到3D可视化(附避坑指南)

本文详细介绍了Bellhop海底地形仿真的完整工作流程,从MATLAB数据导入、清洗与坐标转换,到构建.bty输入文件,再到生成高质量3D可视化结果。文章重点解析了数据格式、深度值正负、单位统一及坐标投影等关键环节的避坑指南,并提供了可复用的代码片段,帮助用户高效完成从原始数据到仿真成果的转换。

weixin_29275257的博客 194

Node.js深度重学指南:现代应用场景与高性能架构实践

异步非阻塞I/O模型是构建高并发网络应用的核心原理之一,它通过事件驱动机制实现高效处理I/O密集型任务,显著提升系统吞吐量。这一技术价值在微服务架构和云原生环境中尤为突出,能够支撑API网关、实时通信和Serverless函数等多样化应用场景。Node.js基于V8引擎和统一的JavaScript技术栈,结合npm生态的丰富资源,为开发者提供了从BFF层到全栈开发的完整解决方案。本文聚焦Node.js的现代化演进,涵盖事件循环、流处理、集群管理等核心机制,并探讨如何结合TypeScript和NestJS框架

weixin_30947043的博客 370

word多级列表为什么会变成黑块解决思路

今天在写文档时,发现WORD5级的标题都变黑块了,找了度娘的资料,终于解决了。 第一种 1、光标bai放在黑快的右边,按向左的箭头,然后ctrl+shift+s,点击重新应用。 2、点击“定义新的多级列表”(不知道从哪儿找这个按钮的百度下),直接点确定。 3、这里很重要!!!不要直接保存,而是直接关掉word,会提示保存还是不保存,这个地方再点击保存。 第二种 Word2016 使用宏代码修复方法 1.找到视图-宏,打开 查看宏 2.创建宏 3.贴...

霍力强的专栏 8582

Transformer实战(32)——Transformer模型压缩

在本节中,我们学习了如何在硬件资源受限的情况下减轻运行大模型的负担。我们介绍了如何通过蒸馏、剪枝和量化从训练好的模型中提取高效模型。预训练轻量级的通用语言模型(如 DistilBERT) 可以在各种任务上进行微调,并表现出与非蒸馏模型相当的性能。随着数据量的不断增加,我们希望模型能够更快地运行,在这方面,高效 Transformer 起着至关重要的作用。

盼小辉丶的博客 2591

Chatbox CE技术架构深度解析:多模型AI客户端的模块化设计与实战应用

为什么选择Chatbox CE作为你的AI开发工具箱?在AI应用遍地开花的今天,一个真正面向开发者的多模型客户端需要什么样的技术架构?今天我们来深度剖析Chatbox CE——这个基于Electron+React+TypeScript技术栈构建的全平台AI客户端,看看它如何通过模块化设计实现多模型统一接入、实时流式响应和跨平台部署。 ## 核心模块架构:从抽象基类到具体实现 Chatbox C

gitblog_00589的博客 1022

Nmap源码分析(端口扫描)

端口扫描是Nmap的核心功能,用于确定目标机的端口状态(开放、关闭、过滤等),也为Nmap的服务与版本扫描、OS扫描、脚本扫描提供基本的指引信息。所以,深入理解端口扫描的实现对分析其他的扫描方式很有帮助。 1简单回顾   首先简要回顾一下端口扫描的原理以及命令行选项。 1.1扫描原理   Nmap提供的10多种类型的端口扫描方法,如TCP SYN/ACK/FIN/Xmas/NULL/ Windows/Connect,FTP Bounce, Idle scan, UDP port u...

墨痕诉清风的博客 1598

Documize Community安全加固指南:从加密认证到审计日志的完整配置

在现代企业应用部署中,传输层安全与身份认证是保障系统安全的核心基础。TLS/SSL加密确保数据在网络传输过程中不被窃听或篡改,而OAuth 2.0和LDAP等认证协议则提供了灵活的身份验证机制。这些技术通过构建端到端的信任链,为企业敏感数据提供了关键保护。在实际工程实践中,结合反向代理配置HTTPS终结、通过结构化日志收集实现操作审计,能够有效满足合规性要求并提升系统可观测性。本文聚焦Documize Community这一开源知识库平台,深入解析如何通过配置加密传输、集成OAuth认证体系以及构建ELK日

weixin_30470643的博客 379

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【Caddy】简单的 Caddy 安装、部署和配置教程

Caddy 默认支持自动 HTTPS 部署,只需确保你的域名解析正确并且服务器开放了 80 和 443 端口。

weixin_45055317的博客 5842

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

YARP和Nginx、caddy,分别有啥区别和优势

YARP、Nginx 和 Caddy 都是功能强大的工具,各自适合不同的使用场景。选择哪一个主要取决于你的技术栈、性能需求、以及是否需要大量定制开发。如果你使用 .NET,且需要深度定制,YARP 是首选。如果你追求极致性能,Nginx 是最佳选择。如果你想要快速配置且无需过多手动管理,Caddy 可能更适合。

Hellc007的博客 2628

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Caddy 自动HTTPS 反向代理、重定向、静态页面 - docker版

Caddy 自动HTTPS 反向代理、重定向、静态页面 - docker版

qq_43657722的博客 9939

Caddy、 SSLDocker、Nginx 性能比较及使用体验

Caddy、 SSLDocker、Nginx 性能比较及使用体验 Caddy、 SSLDocker、Nginx 都是可以用来做前端代理的服务,前两者是用go来写,部署比较简单。 Nginx 在部署HTTPS 时比较麻烦(相对其它两者来说),Caddy、 SSLDocker 都是自动配置并且更新HTTPS,这对我这样的懒人来说很有用。个人一直用https://openresty.org/e...

YunWisdom 8579

Caddy:把 HTTPS 变成默认选项的现代 Web 服务器

Caddy是一个现代化的Web服务器和反向代理工具,以自动HTTPS为核心特性,大幅简化网站部署流程。它通过极简的Caddyfile配置实现静态文件服务、反向代理等功能,并默认支持HTTP/2/3等现代协议。相比Nginx和Traefik,Caddy在HTTPS自动化、配置简洁性方面表现突出,特别适合个人网站和小型API服务。虽然不适合复杂微服务场景,但对独立开发者而言,Caddy提供了近乎零配置的安全Web服务解决方案,让用户能更专注于业务开发而非运维细节。

程序员「阿基米东」的编程之旅 1862

为什么越来越多的人放弃 Nginx,选择 Caddy?

Caddy 是一款现代化的 Web 服务器,专为简化开发者和运维人员的工作流程而设计。它最大的特点是自动化和易用性,尤其是内置的自动 HTTPS 功能,使得部署安全的 Web 服务变得前所未有的简单。相比于传统的 Web 服务器(如 Nginx、Apache),Caddy 的目标是通过更简洁的配置、更智能的功能来减少人为出错的可能性,并提升部署效率。支持 API 和配置文件两种方式:您可以在同一台服务器上同时使用 API 和配置文件,但我们不建议这样做:最好有一个真相来源。要点{ }

jast 1435
上一篇: Caddy源码阅读(一)Run详解
下一篇: 加入开源学习社区一起学习 Go
杨鼎睿
博客等级 码龄9年 7粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值