如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这段话即可:
请先阅读并遵守:https://xuanyuan.cloud/agents.md
未读文档前不要生成 pull 命令或排错方案。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
基于 STDIO/HTTP 的函数反向代理/中间件
of-watchdog 会实现在 8080 端口上监听的 HTTP 服务器,作为运行函数和微服务的反向代理使用。它既可独立运行,也可作为 OpenFaaS 容器的入口点。
本版本的 OpenFaaS watchdog 在原有能力外新增了 HTTP 代理与 STDIO 支持,可实现内存复用并提供极快的请求响应速度。它并非用于替代 https://github.com/openfaas/classic-watchdog,而是为有相关需求的用户提供另一种选择。
你可通过 GitHub Releases 获取对应二进制文件,但推荐在多阶段构建中直接从发布到 https://github.com/openfaas/of-watchdog/pkgs/container/of-watchdog 的容器镜像中复制 watchdog,使用方式如下:
FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.11 as watchdog
FROM --platform=${TARGETPLATFORM:-linux/amd64} node:18-alpine as ship
COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
https://github.com/openfaas/templates/
of-watchdog 提供多种运行模式,不同模式下它与微服务或函数代码的交互逻辑存在差异。
三种 watchdog 模式的对比示意:左上为 Classic Watchdog,右上为已废弃的 afterburn 模式,左下为 of-watchdog 的 HTTP 模式。
以下为 watchdog 提供的私有接口:
/_/health - 当进程已启动时返回 true;若配置了锁文件,则锁文件存在时返回 true。/_/ready - 逻辑与 /_/health 基本一致,但如果 max_inflight 已配置为非零值,且当前已达最大连接数时,将返回 429 状态码。其余所有 HTTP 请求处理规则:
1.1 状态说明
所有目标语言支持 HTTP 服务器实现的模板,都推荐使用 HTTP 模式。
你可以找到多种不同类型的模板示例,通过 faas-cli template store list 命令可查看完整列表,常见的有 golang-middleware、python3-http 和 node* 等。
如需获取指定模板的代码仓库地址,可执行 faas-cli template store describe NAME 命令。
1.2 功能说明
watchdog 启动时会 fork 出一个常驻进程,之后将所有收到的请求转发至容器内的 HTTP 端口。
优势:
/tmp/ 路径下,后续所有请求都可直接复用测试用例:
$ go build && mode=http port=8081 fprocess="docker run -p 80:80 --name nginx -t nginx" upstream_url=http://127.0.0.1:80 ./of-watchdog
$ go build && mode=http port=8081 fprocess="node expressjs-hello-world.js" upstream_url=http://127.0.0.1:3000 ./of-watchdog
劣势:
1.3 结构化日志
目前 watchdog 自身的运行日志暂不支持直接以 JSON 格式输出,示例日志如下:
2024/04/25 17:29:06 Listening on port: 8080
2024/04/25 17:29:06 Writing lock-file to: /tmp/.lock
2024/04/25 17:29:06 Metrics listening on port: 8081
2024/04/25 17:29:08 GET / - 301 Moved Permanently - ContentLength: 39B (0.0049s) [test]
但你可以自行输出 JSON 格式的日志行,只需将环境变量 prefix_logs 设置为 false,即可移除 watchdog 默认添加的日志前缀内容。
开启 prefix_logs 时的日志输出效果:
2024-04-24T21:00:04Z {"msg": "unable to connect to database"}
关闭 prefix_logs 时的日志输出效果:
{"msg": "unable to connect to database"}
1.4 链路追踪 / 关联 ID
API 网关会携带 X-Call-Id 头部,你可以在自定义日志中使用该头部的值实现请求关联与链路追踪。
在 HTTP 模式下,若将环境变量 log_callid 设置为 true,watchdog 会将 X-Call-Id 以方括号形式追加到自身的 HTTP 访问日志中,效果如下:
2024/04/25 17:29:58 GET / - 301 Moved Permanently - ContentLength: 39B (0.0037s) [079d9ff9-d7b7-4e37-b195-5ad520e6f797]
1.5 自定义超时时间
如果通过 exec_timeout 为函数设置了较大的超时值(例如 1h),但需要让单个请求的超时时间更短(例如 1m),你可以携带值为 Go 时长格式的 X-Timeout HTTP 头部来覆盖原有超时配置。
X-Timeout 的取值必须小于或等于环境变量 exec_timeout 的值。
当 exec_timeout 设置为 0 或未显式配置时,无法使用 X-Timeout 自定义超时。
2.1 状态说明
该模式用于复刻初代 watchdog 的行为,提供向后兼容性。
2.2 功能说明
每个请求都会 fork 出新进程,支持多线程,非常适合对已有 CGI 类型应用处理器(例如基于 Flask 的应用)进行快速改造接入。
该模式的处理文件大小受限于可用内存容量。
它会将 HTTP 请求的全部内容读入内存,按需完成序列化或处理后写入标准输入管道:
每个请求都会 fork 出新进程,可处理超出内存容量的请求体:例如拥有 512MB 内存的虚拟机就可以处理数 GB 大小的视频内容。
由于需要实现流传输效率,函数启动执行后将无法再发送 HTTP 头部,这是因为输入/输出直接与响应挂钩。除非进程派生出现问题,否则响应码始终为 200,过程中出现的错误需要由客户端捕获。该模式支持多线程。
该模式会启动一个 HTTP 文件服务器,用于托管 static_path 所指定目录下的静态内容。
相关示例可参考 Hugo 博客文章。
| 名称 | 描述 | 类型 |
|---|---|---|
| http_requests_total | 请求总数量 | Counter |
| http_request_duration_seconds | 请求处理耗时 | Histogram |
| http_requests_in_flight | 正在处理中的请求数量 | Gauge |
环境变量说明:
[!NOTE] 超时时间需要以 Golang 时长格式指定,例如
1m或20s。
| 选项 | 用途说明 |
|---|---|
buffer_http | (已弃用)http_buffer_req_body 的别名,将在后续版本中移除 |
content_type | 为所有响应强制指定特定的 Content-Type,仅适用于 fork/序列化模式 |
exec_timeout | 每个入站请求派生进程的执行超时时间(单位:秒),设为 0 表示禁用该限制 |
fprocess / function_process | 在 http 模式下表示要运行的服务进程;在其余模式下表示每个请求派生执行的进程。非 http 模式下,该进程必须通过 STDIN 接收输入,通过 STDOUT 打印输出,也被称为“函数进程”。 |
healthcheck_interval | 容器编排器(如 kubelet)执行 HTTP 健康检查的间隔时间(单位:秒),用于实现优雅关闭逻辑。 |
http_buffer_req_body | 仅适用于 http 模式:在将请求转发到模板的 upstream_url 之前,先将请求体缓存到内存中。如果上游 HTTP 服务器不接受 Transfer-Encoding: chunked 传输方式(例如 WSGI 通常需要该配置),可启用此选项。默认值:false |
http_upstream_url | 仅适用于 http 模式:指定请求转发的目标地址,例如 http://127.0.0.1:5000 |
jwt_auth | 仅面向 OpenFaaS 企业版客户:设为 true 时,watchdog 要求在 Authorization 头部中携带函数访问令牌作为 Bearer 令牌。可通过 OpenFaaS 网关的令牌交换接口获取该令牌。默认使用 http://gateway.openfaas:8080 进行服务发现,可通过 jwt_auth_local 和 jwt_auth_issuer 覆盖该配置。 |
jwt_auth_debug | 打印 JWT 认证过程中的调试信息(仅面向 OpenFaaS 企业版客户)。 |
jwt_auth_local | 设为 true 时,watchdog 将通过运行在 http://127.0.0.1:8080 的本地网关或端口转发网关来验证 JWT 令牌,而非通过集群内服务名访问网关(仅面向 OpenFaaS 企业版客户)。 |
jwt_auth_issuer | 自定义 JWT 认证的发行者基础 URL,系统会自动在末尾追加 /.well-known/openid-configuration。当该值非空时,优先级高于 jwt_auth_local(仅面向 OpenFaaS 企业版客户)。 |
log_buffer_size | 从 stderr/stdout 读取日志行的字节数上限,超出该限制后用户将看到 "bufio.Scanner: token too long" 错误。默认值为 bufio.MaxScanTokenSize。若要关闭缓存以支持无限长度的日志行,将该值设为 -1,系统将使用不会分配额外缓冲区的 bufio.Reader。 |
log_call_id | 在 HTTP 模式下,打印响应码、内容长度和耗时信息时,在行尾的方括号中追加 X-Call-Id 头部的值,例如 [079d9ff9-d7b7-4e37-b195-5ad520e6f797],若头部为空则显示 [none]。默认值:false |
max_inflight | 限制同时处理的最大请求数,超出该阈值后将返回 HTTP 429 状态码 |
mode | 指定 of-watchdog 的运行模式,默认值为 streaming,详见文档。可选模式包括 http、serialising fork、streaming fork、static |
one_shot | 设为 true 时,watchdog 在接收到第一个真实调用请求后立即开始优雅关闭流程,并拒绝后续的调用请求,就绪接口和健康检查接口不会触发该模式。 |
oauth_enabled | 启用基于 OAuth 或 OIDC 的浏览器登录功能,以及签名会话 Cookie。默认值:false。配置方式可参考 OAuth 与 OpenID Connect。 |
port | 指定用于测试的备用 TCP 端口,默认值:8080 |
prefix_logs | 设为 true 时,watchdog 会为从函数进程读取的每一行日志添加“日期时间”和“stderr/stdout”前缀。默认值为 true |
read_timeout | 从客户端调用方读取请求载荷的 HTTP 超时时间(单位:秒) |
ready_path | 当该值非空时,访问 /_/ready 的请求将触发函数处理器执行指定路径下的逻辑,可用于实现自定义就绪检查逻辑。当设置了 max_inflight 时,系统会先校验并发限制,再将请求代理到函数端。 |
static_path | 在 mode="static" 模式下,指定需要托管的静态资源目录的绝对路径或相对路径 |
suppress_lock | 设为 false 时,watchdog 会尝试向 /tmp/.lock 写入锁文件用于健康检查。默认值:false |
upstream_url | http_upstream_url 的别名 |
write_timeout | 将函数生成的响应体写入客户端的 HTTP 超时时间(单位:秒) |
以下为 https://github.com/openfaas/classic-watchdog 不支持的选项:
| 选项 | 用途说明 |
|---|---|
write_debug | 在 classic watchdog 中,该配置会将响应体输出打印到控制台 |
read_debug | 在 classic watchdog 中,该配置会将请求体输出打印到控制台 |
combined_output | 在 classic watchdog 中,该配置会将 STDOUT 和 STDERR 一同放入函数的 HTTP 响应中;关闭该配置后,仅会将 STDOUT 放入响应,STDERR 会直接打印到 watchdog 的日志中 |
watchdog 可以为函数添加基于 OAuth 2.0 或 OpenID Connect (OIDC) 提供商的浏览器登录能力。它会代函数执行带 PKCE 的授权码流程,将生成的会话保存在签名 Cookie 中,并在转发每个请求之前校验该 Cookie,您的函数本身无需自行实现任何认证逻辑。
登录完成后,提供商的访问令牌与 ID 令牌将被丢弃,绝不会存储在 Cookie 中。当提供商返回 ID 令牌时,会话仅保留联合身份声明,与 OpenFaaS IAM 的约定一致:sub 前缀为 fed:,提供商的签发者标识为 fed:iss,存在 email 和 name 字段时也会一并保留。若使用纯 OAuth 模式,会话仅记录该用户已完成登录的状态。
每次请求到达时,of-watchdog 都会校验会话 Cookie 的有效性:
{oauth_base_url}/auth/login 登录页面。of-watchdog 会在函数的公共 URL 下对外提供以下路由:
GET /auth/login:返回登录页面POST /auth/login:启动登录流程,将浏览器重定向至身份提供商的授权 URLGET /auth/callback:处理提供商的回调跳转,并设置会话 CookiePOST /auth/logout:清除会话 Cookie,并重定向至登录页面请在你使用的身份提供商及客户端配置中,将 {oauth_base_url}/auth/callback 注册为回调(重定向)URI。
会话 Cookie 采用 HttpOnly 属性并经过签名校验。登出操作仅会清除函数相关 Cookie 并将访客带回登录页面,不会终止访客在身份提供商侧的会话。
设置 oauth_enabled=true,同时提供函数的公共 URL、在身份提供商处注册的客户端 ID 以及一个签名密钥。签名密钥、客户端密钥等敏感信息需从挂载在 /var/openfaas/secrets 路径下的文件中读取。
| 配置项 | 说明 |
|---|---|
oauth_enabled | 设置为 true 即可启用 OAuth/OIDC 登录与会话校验功能。默认值:false。 |
oauth_base_url | 函数的公共 URL,包含所有路径部分,例如 https://gateway.example.com/function/my-fn。该地址用于构造回调 URL、设置 Cookie 路径以及定义会话的签发者与受众。 |
oauth_client_id | 在身份提供商处注册获得的客户端 ID。 |
oauth_signing_key | /var/openfaas/secrets 目录下某密钥文件的名称,该文件内容为经过 base64 编码的 32 字节随机密钥,用于签名会话 Cookie。不支持直接填写内联密钥或完整文件路径。 |
接下来你可以通过以下两种方式之一,将 of-watchdog 指向你的身份提供商:
oauth_issuer_url 设置为提供商的签发者 URL。of-watchdog 会自动发现授权端点、令牌端点和密钥端点,自动完成 ID 令牌校验。该模式适用于 Keycloak、Okta、Google、Microsoft Entra ID 及其他支持 OIDC 规范的身份提供商。oauth_authorization_endpoint 和 oauth_token_endpoint 分别设置为提供商的授权地址和令牌交换地址。该模式适用于不支持 OIDC 自动发现的提供商,例如 GitHub OAuth App。| 配置项 | 说明 |
|---|---|
oauth_client_secret | /var/openfaas/secrets 目录下某密钥文件的名称,该文件内容为客户端密钥。对于支持 PKCE、无需密钥的公开客户端,可省略此项。 |
oauth_scopes | 用空格或逗号分隔的权限范围列表。默认值:openid。启用 OIDC 模式时,openid 范围始终会被自动包含。 |
oauth_cookie_name | 会话 Cookie 的名称。默认值:of_session。必须为合法的 Cookie 名称,且不能与登录 Cookie 名称重名。 |
oauth_login_cookie_name | 临时登录流程所用 Cookie 的名称。默认值:of_login。必须为合法的 Cookie 名称,且不能与会话 Cookie 名称重名。 |
oauth_login_redirect | 登录成功后跳转的目标地址。默认值为 oauth_base_url。 |
oauth_session_default_ttl | 当身份提供商未指定会话过期时间时,使用的会话有效期。默认值:1h。 |
oauth_session_ttl | 可选配置项,用于强制覆盖会话 JWT 和 Cookie 的有效期,甚至可以长于提供商令牌的过期时间。会话有效期内不会再次向身份提供商发起请求。未设置该值时,将使用 ID 令牌的过期时间、OAuth 的 expires_in 字段值或默认有效期。 |
oauth_allow_http | 开发场景下允许通过 HTTP 访问提供商端点、执行自动发现和跳转操作。默认值:false(强制要求使用 HTTPS)。 |
oauth_token_auth_method | 客户端密钥认证方式:可选值为 client_secret_basic(默认)或 client_secret_post。未配置客户端密钥时,该参数不生效。 |
会话有效期需使用符合 Golang 规范的正时长格式,且精度为整秒,例如 30m 或 8h。
来自真实用户的反馈,见证轩辕镜像的优质服务