首页 > 其他分享 >Go 语言生产服务故障案例精析

Go 语言生产服务故障案例精析

时间:2024-08-30 22:51:21浏览次数:10  
标签:网关 HTTP 精析 panic 故障 502 Go 异常

        大多数 Go 开发者都停留在简单的增删改查层面,对 Go 语言本身掌握程度不够,对常用依赖或者开源组件掌握不够,在开发项目过程中总会不经意间引入一些千奇百怪的问题,并且在遇到线上问题时往往束手无策。下面列举一些线上问题以及相应的解决思路,希望大家能从这些问题中吸取经验,总结出一套属于自己的解决问题的方法论。

1. 两种情况导致 502 状态码的情况

        服务端开发最常见的问题可能就是 HTTP 状态码异常了,其中 502 状态码最常见并且最复杂。

1.1.1 panic 异常

        我们可以将 Go 服务中的 panic 异常分为两种:一种是请求级别的 panic 异常,即 Go 服务在处理 HTTP 请求时发生了 panic 异常;与之相对的,我们称之为服务级别的 panic 异常。需要说明的是,两种类型的 panic 异常都会导致 502 状态码。

        1.1.1.1 panic 异常导致 502 状态码

        下面先来介绍服务级别的 panic 异常是如何导致 502 状态码的。服务级别的 panic 异常会导致 Go 服务异常退出,这时候网关侧必然会返回大量 502 状态码,同时网关侧会出现大量的错误日志,如下所示:

connect () failed (111: Connection refused) while connecting to upstream

        从上面的日志可知,网关发起 HTTP 请求需要先建立 TCP 连接,但是 Go 服务已经退出了,即没有进程在监听目标端口了,TCP 连接自然也就无法建立了,于是网关便向客户端返回了 502 状态码。这种情况还是比较容易处理的,只需要使用函数 recover 捕获异常就能避免 Go 服务的退出,参考下面的代码:

defer func(){
	if err := recover(); err != nil {
		buf = buf[:runtime.Stack(buf,false)]
		log.Fatalf("go panic err:%v \n stack:%s",err,buf)
	}
}()

        接下来讲解请求级别的 panic 异常是如何导致 502 状态码的。我们先写一个简单的程序验证一下,代码如下所示:

package main

func main() {
	server := &http.Server{
		Addr: "0.0.0.0:8080",
	}

	http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
		panic("panic test")
		w.Write([]byte(r.URL.Path + ">ping response"))
	})
	_ = server.ListenAndServe()
}

        在上面的代码中,我们在 HTTP 请求处理函数中抛出了 panic 异常。另外需要再次强调,本例中的访问链路是客户端--网关Nginx--Go 服务。编译上面的程序,并通过 curl 命令发起 HTTP 请求,结果如下所示:

[root@localhost ~]#curl --request POST 'http://127.0.0.1/ping' -v
<HTTP/1.1 502 Bad Gateway

        由上面的结果可知,客户端确实收到了 502 状态码,并且多次执行 crul 命令的结果都是一样的。另外,如果你这时候看控制台,你会发现 Go 服务并没有退出,但是控制台输出了以下日志:

2024/08/28 09:59:20 http: panic serving xxxx:56850: panic test
goroutine 6 [running]:
net/http.(*conn).serve.func1()

        参考上面的输出结果,Go 服务没有退出,说明一定有函数 recover 捕获了异常,并输出了协程调用栈,可是既然都捕获 panic 异常了,为什么网关返回的还是 502 状态码呢?我们可以查看网关的错误日志,如下所示:

[error] upstream prematurely closed connection while reading response header from upstream

         参考上面的错误日志,网关 Nginx 在等待上游 Go 服务返回 HTTP 响应时,上游 Go 服务过早地关闭了 TCP 连接。为什么呢? 估计是 Go 服务在处理 HTTP 请求时, 使用函数 recover 捕获了异常,并关闭了 TCP 连接。是这样吗?我们简单看一下 Go 语言底层处理 HTTP 请求的逻辑,如下所示:

func (c *conn) serve(ctx context.Context){
	defer func(){
		if err := recover();err != nil && ErrAbortHandler {
			......
			c.server.logf("http:panic serving %v:%v\n%s",c.remoteAddr,err,buf)
			c.close()
		}
	}()
}

        在上面的代码中,针对 TCP 连接,Go 语言都会创建新的协程来处理从该连接接收到的 HTTP 请求,并且使用了函数 recover 来捕获 panic 异常。可以看到,当发生了 panic 异常之后,Go 语言一方面输出了协程调用栈来帮助开发者排查问题,另一方面直接关闭了 TCP 连接,这也是网关 Nginx 返回 502 状态码的根本原因。

        最后总结下,请求级别的 panic 异常同样会导致 502 状态码。幸运的是,这种情况的 502 非常容易排查:一来我们可以在上游 Go 服务标准输出查看到错误日志;

标签:网关,HTTP,精析,panic,故障,502,Go,异常
From: https://blog.csdn.net/canglonghacker/article/details/141619903

相关文章

  • Study Plan For Algorithms - Part16
    1.下一个排列题目链接:https://leetcode.cn/problems/next-permutation/整数数组的一个排列就是将其所有成员以序列或线性顺序排列。整数数组的下一个排列是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组......
  • Goby 漏洞发布|Nacos Jraft 服务文件读取漏洞【已复现】
    漏洞名称:NacosJraft服务文件读取漏洞EnglishName:NacosJraftServicesFileReadVulnerabilityCVSScore:5.0漏洞描述:NACOS是阿里巴巴推出来的一个新开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nac......
  • 【Linux】开源的系统监控和故障排除工具Sysdig:用于系统监控、故障排除和安全审计,从下
    Sysdig是一个开源的系统监控和故障排除工具,可以捕获和分析系统调用,帮助你深入了解系统的运行状态。无论是开发人员、运维工程师还是安全专家,Sysdig都是进行系统监控、故障排除和安全审计的理想工具。本文将详细介绍Sysdig的安装、基本使用方法以及一些高级用法,并通过具......
  • golang使用http客户端 多个协程同时请求接口
    packagemainimport( "encoding/json" "fmt" "io" "net/http" "net/url" "sync")typeApiResponsestruct{ Codeint`json:"code"` Msgstring`json:"msg&qu......
  • Google Trends使用教程详解
    GoogleTrends是谷歌旗下一款基于搜索数据推出的一款分析工具。它通过分析谷歌搜索引擎每天数十亿的搜索数据,告诉用户某一关键词或者话题各个时期下在谷歌搜索引擎中展示的频率及其相关统计数据。01进入谷歌趋势打开网址:https://trends.google.com/,输入关键词,点击Enter即......
  • django中的数据库连接池实现
    1、第一步安装数据库连接池第三方模块pipinstalldjango-db-connection-pool2、在项目目录下的settings文件中添加下面配置DATABASES={"default":{'ENGINE':'dj_db_conn_pool.backends.mysql','NAME':'day04',#数据库名字......
  • go语言DB通用查询实现解析
    用例funcTest018_QueryShop(t*testing.T){   vardbRequest=Default()   dbRequest.TableName="contact_shop"   dbRequest.SetPageSize(2).OrderByAsc("id")   dbRequest.FieldsName="id_10,id,name"   varresult=dbRequ......
  • IndigoSCADA协助ARMxy实现智能工厂可视化解决方案
    一、IndigoSCADA简介IndigoSCADA基于先进的软件架构设计,确保了系统的稳定性和可扩展性。它支持多种通信协议,包括但不限于Modbus、OPCUA、MQTT等,使得与各种工业设备和系统的无缝对接成为可能。此外,IndigoSCADA还提供了丰富的图形库和脚本工具,允许用户根据实际需求快速构建个性化的......
  • Go,你也可以的!-【7.2 panic】
    7.2panicpanic就是Go语言中的崩溃,崩溃也就是程序不可用,这在实际的业务中基本是最严重的BUG。在大部分语言中,产生崩溃的原因基本是差不多的,大多都是访问了空指针、数组越界、内存溢出等。基本可以总结为,发生崩溃都是与系统进行了非法的内存或资源操作。本节代码存放目录......
  • LOTO示波器统计曲线和故障分析pass/fail测试
    LOTO示波器统计曲线和故障分析pass/fail测试虚拟示波器可以应用在工业自动化检测中,除了常规的检测波形和测量值参数以外,由多个行业客户定制和验证的统计曲线和故障分析(pass/fail)功能也为工业自动化检测带来极大的便利。     (一)故障分析(pass/fail)的基础:统计曲线功能在信号......