局域网Gin服务需手动实现健康检查与故障自愈:每5秒探测/health接口,连续3次失败则os.Exit(1),且/health须验证etcd/Consul连通性、关键配置加载、下游gRPC健康状态;监听地址必须设为0.0.0.0:8080;多实例session共享须用Redis或Nginx ip_hash;DNS不稳定时应禁用缓存或改用固定IP;所有“理所当然”假设均需亲手验证。

局域网里Gin服务挂了没人知道
局域网环境天然缺乏云平台的健康检查和自动摘除机制,Gin进程一旦panic或卡死,上游(比如Nginx、前端、其他服务)会持续把请求打过去,直到超时——这不是“高可用”,是“静默故障”。
必须手动加两层探测:http.Get("http://localhost:8080/health")不能只在启动时跑一次;要起一个独立goroutine,每5秒调用一次/health接口,并在失败连续3次后主动os.Exit(1)。别依赖Kubernetes liveness probe,局域网没那个。
另一个常见错误是把/health写成只返回{"status":"ok"},结果数据库连不上、下游gRPC超时、配置文件被误删,它照样返回200。真正的健康检查得包含:
• 连得上本地etcd或Consul(如果用了服务发现)
• 能读取关键配置项(比如conf.Load()加载的configs/app.yaml里mysql.host不为空)
• 对下游至少一个核心服务发一次grpc_health_v1.HealthClient.Check()
Gin路由404但进程明明在跑
局域网部署常直接用gin.Default()起服务,结果所有接口都404。不是路由没写,是监听地址错了。r.Run(":8080")默认只监听127.0.0.1:8080,局域网其他机器根本连不上。
必须显式绑定0.0.0.0:r.Run("0.0.0.0:8080")。
还有人用gin.New()但忘了加recovery和logger中间件,panic发生时日志全丢,只能靠systemctl status看到“exited with code 2”——这种问题在局域网里最难排查。
正确做法:
• 用gin.New()自己拼中间件链,别图省事用Default()
• log.SetOutput(os.Stdout)确保日志输出到stdout,方便journalctl -u mygin.service查
• panic时记录完整堆栈:log.Printf("PANIC: %v\n%s", err, debug.Stack())
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
多实例Gin服务之间不共享session
局域网里用Nginx做负载均衡,用户第一次请求打到A实例登录成功,第二次打到B实例就变未登录——因为Gin默认session存在内存里,实例间不互通。
解决方案只有两个:
• 改用Redis存session:用github.com/go-session/redis,初始化时传入redis.Options{Addr: "192.168.1.100:6379"}(别用localhost,那是本机)
• 强制Nginx做IP hash:upstream backend { ip_hash; server 192.168.1.10:8080; server 192.168.1.11:8080; },但单点故障风险上升
注意:gin-contrib/sessions的cookie store在局域网里尤其危险——cookie没设Domain和Secure,浏览器可能把不同IP的session混在一起;redis store也得关掉SavePeriod,避免高频写Redis拖慢响应。
局域网DNS不稳定导致下游服务连不上
局域网DNS服务器(比如Windows AD DNS或dnsmasq)经常响应慢或返回缓存旧IP,Gin里用http.Client直连http://user-service:8080,第一次解析正常,之后就一直用过期IP,直到进程重启。
必须禁用DNS缓存:
• 创建http.Client时,Transport里设DialContext,每次请求都重新net.Dial
• 或更简单:不用域名,改用局域网固定IP+端口(如192.168.1.200:8080),并在配置中心里管理这个IP列表
如果非要用服务发现(比如Consul),别信consul.Agent.ServiceList()返回的ServiceNode.Address——它可能是容器内网IP,局域网机器根本访问不到。得提前在Consul注册时填Tags: []string{"lan-ip=192.168.1.200"},代码里从Tags里取真实可访问地址。

















