Go、Rust 这俩语言火起来后,又爆发了一波造轮子的热潮。Go 有大名鼎鼎的 Kubernetes,Rust 也即将出现在 linux 内核的 6.1 版本中,除了这些杀手级使用场景,还有一些较小的轮子,基本都是杀手级场景的衍生场景,Go 专注云场景、后端场景,Rust 专注 linux 环境——最近好像不少人在用 Rust 狂写命令行工具。今天要体验的 Caddy 就是用 Go 写的 Web 服务器,Github 43k star 的项目。
主要用途:Web 服务器、反向代理。看起来和 Nginx 属于同类产品。先看看丫是怎么客观地吹自己的🤔。
浏览一遍我们直接上路,在 Fedora 36 上的安装体验比较丝滑。
cq@fedora ~> sudo dnf install 'dnf-command(copr)' cq@fedora ~> sudo dnf copr enable @caddy/caddy cq@fedora ~> sudo dnf install caddy
三条命令执行过后,就算安装成功了,可以在 /lib/systemd/system/ 下找到 caddy.service、caddy-api.service 两个服务。命令行也可以直接执行 caddy,指向 /usr/bin/caddy。
使用 caddy run 就可以按默认配置把应用起起来。
Caddy 主要支持三种配置方式:Caddyfile、caddy.json、API。前两种都是静态配置文件,最后一种是动态配置。除了主流的三种,也有若干 config-adapter 支持从其他配置格式转译过来,如 nginx、yaml、toml。配置加载进 caddy 后,都转换为 json 格式。
可以写一个 Caddyfile,内容如下,在启动的时候加载。
:2015 respond "你好,法外狂徒张三"
管理端口是 2019,服务端口是我们指定的 2015。
也可以将配置写为 json 格式文件,在启动时加载。
{
"apps": {
"http": {
"servers": {
"example": {
"listen": [":2015"],
"routes": [
{
"handle": [{
"handler": "static_response",
"body": "Hello, world!"
}]
}
]
}
}
}
}
}
caddy 也支持吐 metrics 给 Prometheus。更详细完整的配置规则见 directives,本篇就不赘述了。
使用 文件服务功能时,切换到文件服务的根路径,启动 caddy,如果没有 index.html,可以带上 --browse 参数,在浏览器里就能浏览文件了。也可以通过 --root 来指定文件服务的根路径。
再看看第二个核心功能——反向代理,反向代理的配置模型都差不多。
upstream 支持写 ip:port、域名、unix socket 等。
提供两种对 upstream 的健康检查方式:active、passive。active 是基于定时器主动进行健康检查,passive 是有实际流量发生时才顺带进行健康检查。
一份粗略的反向代理配置
reverse_proxy [] [ ] { # backends to dynamic ... # load balancing lb_policy [ ] lb_try_duration lb_try_interval # active health checking health_uri health_port health_interval health_timeout health_status health_body health_headers { [ ] } # passive health checking fail_duration max_fails unhealthy_status unhealthy_latency unhealthy_request_count # streaming flush_interval buffer_requests buffer_responses max_buffer_size # request manipulation trusted_proxies [private_ranges] header_up [+|-] [ [ ]] header_down [+|-] [ [ ]] method rewrite # round trip transport { ... } # optionally intercept responses from upstream @name { status header [ ] } replace_status [ ] handle_response [ ] { # special directives only available in handle_response copy_response [ ] [ ] { status } copy_response_headers [ ] { include exclude } } }
一个简单的例子
下一次再来扒一下它的架构🤔