了解Golang中的“连接重置”:故障排除指南
#go #网络 #http #networking

介绍

在应用程序中使用网络连接时,您可能会遇到错误消息“ by peer Reset”。此错误消息可能会令人困惑和令人沮丧,特别是如果您不熟悉其含义。在本故障排除指南中,我们将探讨“ peer重置”的含义,是什么原因以及如何在应用程序中进行修复。

什么是“同行连接重置”?

“连接重置peer”是一个错误消息,在使用网络连接时可能会发生。它表明远程服务器或客户端意外关闭了连接,从而导致连接的终止。

此错误消息可能是由多种因素引起的,例如网络连接问题,错误配置的防火墙或代码中网络错误的处理不当。 “通过对等重置”错误消息的一些常见原因包括:

  1. 网络问题:客户端和服务器可能在不同的网络上,与网络相关的问题(例如防火墙,代理或路由器)可能会干扰连接。
  2. 服务器过载:服务器可能会被请求淹没,从而终止连接以保持稳定性。
  3. 不正确的协议处理:如果客户端和服务器使用不同的协议或版本,则可能导致意外行为和连接重置。
  4. 防火墙或安全配置:错误配置的防火墙或安全设置可能会拒绝或终止连接,从而触发错误。

故障排除“连接重置由对等”:

  1. 验证连接:确保客户端和服务器都具有稳定且可靠的网络连接。检查可能导致错误的任何与网络有关的问题或限制。
  2. 查看服务器日志:检查服务器日志以确定任何潜在问题,例如服务器过载或资源耗尽。这些日志可以为连接重置的根本原因提供宝贵的见解。
  3. 检查协议兼容性:确认客户端和服务器都使用相同的协议和兼容版本。不兼容的协议可能导致意外行为和连接重置。
  4. 修改防火墙或安全设置:暂时禁用防火墙或安全措施,以确定它们是否导致连接重置。如果是这样,请相应地调整设置以允许连接。
  5. 实施连接重试机制:要处理瞬态网络问题或服务器过载情况,请考虑在代码中实现连接重试机制。这允许客户端自动重新连接并从连接重置中恢复。
  6. 优化代码和资源用法:查看您的代码,以确保其高效且不不必要地消耗过多的资源。优化代码和资源使用情况以减少遇到连接重置错误的可能性。

例子

我获得了一个代码简单的HTTP服务器和客户端

func client() {
    for i := 0; i < 100; i++ {
        res, err := http.Post("http://localhost:9000/test", "text/json", bytes.NewReader(nil))
        if err != nil {
            log.Printf("error sending: %s", err)
            continue
        }

        body, err := ioutil.ReadAll(res.Body)
        defer res.Body.Close()
        if err != nil {
            log.Printf("error reading: %s", err)
            continue
        }
        fmt.Printf("iteration #%0d read: %s", i, string(body))
        time.Sleep(time.Millisecond * 200)
    }
}

func srv() {
    mux := http.NewServeMux()
    mux.HandleFunc("/test", func(w http.ResponseWriter, req *http.Request) {
        fmt.Println(w, "test\n")
    })

    srv := &http.Server{
        Addr:        ":9000",
        Handler:     mux,
        IdleTimeout: time.Millisecond * 300,
    }
    srv.ListenAndServe()
}

func main() {
    go srv()
    time.Sleep(3 * time.Second)
    client()
}

辩解此代码时,我会遇到一些错误:

2023/06/02 09:44:20 error sending: Post "http://localhost:9000/test": http: server closed idle connection
iteration #16 read: test
2023/06/02 09:44:20 error sending: Post "http://localhost:9000/test": EOF
iteration #18 read: test
2023/06/02 09:44:20 error sending: Post "http://localhost:9000/test": EOF
iteration #20 read: test
2023/06/02 09:44:20 error sending: Post "http://localhost:9000/test": read tcp 127.0.0.1:43258->127.0.0.1:9000: read: connection reset by peer

原因* *

http 1.1引入了持续连接的概念,使客户能够重用相同的连接,以便多个请求到服务器。该连接没有在收到响应后立即关闭连接,而是保持打开状态,从而使随后的请求从延迟和改善的性能中受益。这种持久性是通过保持TCP连接的活力来实现的。

连接封闭和非数字请求:
在某些情况下,服务器可能会意外关闭持久连接,从而导致客户端错误。重要的是要理解,在连接关闭时,不应重复非数字请求,例如邮政和补丁。

愿意的请求是那些产生相同结果的请求,无论其重复多少次。另一方面,非数字请求有可能在每次执行时对服务器造成副作用。例如,帖子通常用于创建新记录,多个执行将导致创建多个记录。

处理连接关闭:
关闭连接时,客户端无法确定请求是否由服务器成功执行。因此,根据定义HTTP 1.1协议的RFC 7230,客户端自动重试的非快速请求(例如POST)被认为是不安全的。客户应该将连接封闭视为服务器的确定响应,并进行相应的操作。

如果使用该方法对多个相同请求的服务器的预期效果与单个请求RFC 7230 4.2.2

的效果相同,则将请求方法视为“ disempotent”

自动重试非掌位请求可能会导致意想不到的后果,例如在服务器上创建的重复记录。由于客户端无法确定在连接关闭之前服务器是否处理了原始请求,因此重试该请求会违反操作的性质。

我的解决方案:

  • 禁用客户端上的持续连接
  • 将客户端的连接超时缩短为小于服务器
  // Set Transport
    t := http.DefaultTransport.(*http.Transport).Clone()
    t.DisableKeepAlives = true
  // option 2
    // t.IdleConnTimeout = time.Millisecond * 100
    c := &http.Client{
        Transport: t,
    }
res, err := c.Post("http://localhost:9000/test", "text/json", bytes.NewReader(nil))

结果:

iteration #0 read: test
iteration #1 read: test
....
iteration #98 read: test
iteration #99 read: test

https://go.dev/play/p/Aw1PXsmm9lm

结论

“通过对等”错误是使用网络编程的开发人员面临的常见挑战。通过了解原因,实施适当的故障排除技术以及遵循预防措施,您可以有效克服此错误并构建可靠可靠的网络应用程序。请记住要利用Golang的错误处理机制的功能,并定期监视和优化服务器的性能以最大程度地减少连接重置错误的发生。

给我买咖啡:
Buy Me A Coffee