upstream必须定义在http块顶层,不能嵌套在server或location中,否则Nginx启动报错或静默失效;正确结构为http{upstream name{server...;}server{location{proxy_pass http://name;}}}。

upstream 必须定义在 http 块顶层,不能塞进 server 或 location
这是 Nginx 启动失败最常见原因。报错通常是 invalid number of arguments in "upstream" directive 或配置静默失效。Nginx 的 upstream 是 http 级指令,和 server 并列,不是 location 的子配置。
正确结构示例:
http {
upstream service_a {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://service_a;
}
}
}
- 所有 Go 实例必须监听
127.0.0.1(或内网 IP),绝不能用0.0.0.0或省略地址——否则会暴露到公网 - 容器或跨机部署时,
localhost指的是 Nginx 所在机器,得换为真实内网 IP 或 DNS 名(如go-auth-svc.default.svc.cluster.local) - 别把多个
upstream块写成嵌套结构;每个服务一个独立块,名字见名知义(如service_auth、service_order)
proxy_pass 尾部斜杠决定路径是否重写
90% 的 404 来自这里。Go 服务注册的路由是 /api/users,但 Nginx 转发后路径错了,后端根本收不到请求。
-
location /auth/ { proxy_pass http://service_auth; }→ 请求/auth/login被转发为http://service_auth/auth/login(错误,多了一层/auth) -
location /auth/ { proxy_pass http://service_auth/; }→ 请求/auth/login被转发为http://service_auth/login(正确,前缀被剥离) -
location / { proxy_pass http://service_api; }→ 请求/v1/users被转发为http://service_api(错误,路径丢失) -
location / { proxy_pass http://service_api/; }→ 请求/v1/users被转发为http://service_api/v1/users(正确)
漏配 proxy_next_upstream 导致单点卡死就全挂
Go 实例可能因 GC STW、慢 SQL、panic 临时不可用。Nginx 默认只做 TCP 连通性探测,不重试——用户直接看到超时或 502。
- 必须显式加:
proxy_next_upstream error timeout http_500 http_502 http_503 http_504; - 搭配合理的健康检查参数:
max_fails=3 fail_timeout=30s,太激进(如max_fails=1)会让一次 panic 就剔除节点 - Go 服务需暴露
/healthz接口(返回 200),Nginx 可配合health_check指令做主动探活(需 stream 模块或商业版) - 用了
ip_hash但没透传真实 IP?补上:proxy_set_header X-Real-IP $remote_addr;,否则r.RemoteAddr拿到的是 Nginx 本机地址
Go 多实例端口不能硬编码,得按环境解耦
开发、Docker、K8s 场景下,端口来源完全不同。写死 :8080 在代码里等于埋雷。
- 本地调试:用
http.ListenAndServe(":0", nil)让系统自动分配空闲端口,启动后打印l.Addr().Port,再填进 Nginxupstream - Docker 部署:Dockerfile 不写
EXPOSE固定端口,运行时用-p 8080随机映射,查实际端口用docker port - Kubernetes:直接用 Service DNS 名(如
service-a.default.svc.cluster.local:8080),Nginx Ingress Controller 自动同步 endpoints,不用手维护 IP 列表
真正难的不是写配置,而是让 Nginx 的健康感知节奏和 Go 的崩溃恢复机制对齐——比如 panic 后进程退出速度、systemd 的 Restart=always 间隔、Nginx 的 fail_timeout,三者差几秒都可能导致流量抖动。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











