Envoy作为Sidecar通过127.0.0.1:8080与Go服务通信,需显式配置上游集群、启用健康检查、透传x-envoy-*头供业务识别调用方,并通过/healthcheck/fail通知下线,Go服务应优先使用X-Envoy-External-Address获取真实客户端IP。

Envoy 作为 Sidecar 怎么和 Go 服务进程通信?
Envoy 默认不自动感知你的 Go 服务监听在哪,必须显式配置上游集群指向 127.0.0.1:8080(或你 Go 程序实际监听的地址)。常见错误是让 Envoy 去连 localhost:8080,结果在容器里解析成自身环回,而非宿主侧的 Go 进程——务必统一用 127.0.0.1,避免 DNS 解析歧义。
Go 服务启动时建议加健康检查端点,比如 /healthz 返回 200,然后在 Envoy 的 cluster 配置里启用主动健康检查:health_checks + http_health_check。否则流量可能打到还没 ready 的 Go 实例上。
- Go 服务不要绑定
0.0.0.0:8080后直接暴露公网;Sidecar 模式下它只该监听127.0.0.1:8080 - Envoy 的
listener接收外部请求(如0.0.0.0:8000),再通过route转发到本地 Go 服务 - 若 Go 服务启用了 TLS,Envoy 可以终止 TLS(即做 HTTPS 入口),后端用 HTTP 连 Go,减少 Go 代码里的证书逻辑
Go 服务怎么知道当前请求被 Envoy 注入了哪些头?
Envoy 默认会透传原始请求头,并添加 x-envoy-* 类头,比如 x-envoy-expected-rq-timeout-ms、x-envoy-downstream-service-cluster。这些不是装饰用的——Go 服务可以直接读 r.Header.Get("X-Envoy-Downstream-Service-Cluster") 来识别调用方身份,用于灰度路由或限流策略。
但注意:Envoy 默认不传递 forwarded 或 x-real-ip,如果需要真实客户端 IP,得在 Envoy 的 http_connection_manager 里显式开启 set_current_client_address,并配置 use_remote_address: true 和可信代理网段。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- Go 中别依赖
r.RemoteAddr获取用户 IP,它返回的是 Envoy 的连接地址(通常是127.0.0.1:xxxx) - 若 Envoy 启用了 JWT 认证,验证通过后会注入
x-envoy-auth-user,Go 服务可直接取值做鉴权,不用重复解析 token - 所有
x-envoy-*头都由 Envoy 控制,Go 不应伪造或覆盖,否则可能干扰熔断、追踪等治理行为
如何让 Go 服务优雅退出,同时通知 Envoy 下线?
Envoy 提供了 /server_info 和 /healthcheck/fail 等管理接口,但 Go 服务本身无法直接调用它们。正确做法是:Go 在收到 SIGTERM 后,先关闭 HTTP server,再向 Envoy 的管理端口(默认 127.0.0.1:9901)发送 POST /healthcheck/fail,触发 Envoy 主动摘除该实例。
如果没这一步,Envoy 仍会按健康检查周期(默认 30s)才发现下游不可达,期间新请求可能失败。更稳妥的方式是在 Go 里启动一个轻量 HTTP client,shutdown 逻辑中调用一次这个 endpoint。
- 确保 Envoy 的管理接口已启用:
admin: { address: 127.0.0.1:9901 } - Go 的
http.Server.Shutdown()必须带 context,超时时间建议略短于 Kubernetes 的terminationGracePeriodSeconds - 调用
/healthcheck/fail后无需等待响应;失败也不影响主流程,属于尽力而为
为什么 Go 服务日志里看不到真实客户端 IP?
根本原因是 Envoy 默认不改写 X-Forwarded-For,且 Go 的 net/http 不自动解析该头。即使 Envoy 已配置 xff_num_trusted_hops: 1,Go 仍需手动从 r.Header.Get("X-Forwarded-For") 提取第一个非私有地址。
更麻烦的是:如果流量经过多层代理(比如云 LB → Envoy → Go),X-Forwarded-For 可能含多个 IP,而 Go 默认只取最左——这容易被伪造。安全做法是结合 X-Envoy-External-Address(Envoy 设置的可信客户端地址)或启用 use_remote_address 并限定信任 CIDR。
- 别用第三方中间件自动处理 XFF,除非你能控制其信任链逻辑
- 在 Go 里打印日志时,优先用
r.Header.Get("X-Envoy-External-Address"),它比 XFF 更可靠 - 如果 Envoy 没开
external_address_headers,这个头就不存在——检查http_connection_manager的add_user_agent和set_forwarded_for配置项

















