在 Go 中使用 TCP keepalive · Felix Geisendörfer

在 Go 中使用 TCP keepalive · Felix Geisendörfer


在 Go 中使用 TCP keepalive · Felix Geisendörfer

发表:

如果您曾经编写过一些 TCP 套接字代码,您可能会想:“如果拔掉网线或远程计算机崩溃,我的连接会发生什么情况?”。

简短的回答是:什么也没有。连接的远端将无法发送 FIN 数据包,本地操作系统也不会检测到连接丢失。因此,由您作为开发人员来解决这种情况。

在 Go 中,您可以使用多种方法来帮助解决此问题。也许第一个要考虑的是 SetReadDeadline net.Conn 接口的方法。假设您的连接预计会定期接收数据,您可以简单地将超时读取视为相当于 io.EOF 错误和 Close 连接。许多现有的 TCP 协议通过定义某种心跳机制来支持这种错误处理方式,该机制要求每个端点定期发送 PING/PONG 探测,以便检测网络问题以及服务运行状况1。此外,此类心跳还可以帮助处理寻找网络活动以确定连接健康状况的代理服务器。

因此,如果您的协议支持心跳,或者您有能力将心跳添加到自己的协议中,那么这应该是解决未插入网线场景的首选。

但是,如果您无法控制协议并且不支持心跳,会发生什么情况?

现在是时候了解 TCP keepalive 以及如何在 Go 中使用它了。 TCP keepalive 在 RFC 1122 中定义,并不是 TCP 规范本身的一部分。可以为单个连接启用它,但默认情况下必须关闭。启用它将导致网络堆栈在默认持续时间(必须不少于两个小时)后探测空闲连接的运行状况。探测数据包将不包含任何数据2,并且未能回复单个探测不能被解释为死连接,因为单个探测数据包没有可靠地传输。

Go 允许您使用以下命令启用 TCP keepalive net.TCPConn的 SetKeepAlive。在 OSX 和 Linux 上,这将导致在连接空闲 2 小时后以 75 秒的间隔发送最多 8 个 TCP keepalive 探测。或者换句话说, Read 将返回一个 io.EOF 2 小时 10 分钟后出现错误 (7200 + 8 * 75)。

根据您的应用程序,超时可能会太长。在这种情况下你可以打电话 SetKeepAlivePeriod。然而,目前此方法对于不同的操作系统表现不同。在 OSX 上,它将修改发送探测之前的空闲时间。然而,在 Linux 上,它将修改空闲时间以及发送探测的时间间隔。所以打电话
SetKeepAlivePeriod 使用 30 秒的参数将导致 OSX 上的总超时为 10 分 30 秒 (30 + 8 * 75),但在 Linux 上将导致 4 分 30 秒 (30 + 8 * 30)。

我发现这种情况相当令人不满意,因此我最终创建了一个名为 tcpkeepalive 的小包,它可以为您提供更多控制:

kaConn, _ := tcpkeepalive.EnableKeepAlive(conn)
kaConn.SetKeepAliveIdle(30*time.Second)
kaConn.SetKeepAliveCount(4)
kaConn.SetKeepAliveInterval(5*time.Second)

目前仅支持 Linux 和 OSX,但我很乐意合并其他平台的拉取请求。如果 Go 核心团队有兴趣,我也会尝试将这些新方法贡献给 Go 本身。

如果您认为本文有用、有任何疑问或发现任何错误,请告诉我,以便我纠正它们。

附录

  1. 调整心跳机制以尽早检测故障并降低误报率是一件棘手的事情。查看 phi 应计故障检测器以获得统计上合理的模型,以及 Damian Gryski 的 go-failure 实现。不幸的是,我无法想到将它与 TCP keepalive 一起使用。

  2. 根据 RFC 1122,保活探针可能包含单个垃圾八位组,以与损坏的实现兼容。但是,我不确定这是否被操作系统网络堆栈过滤掉,如果您知道,请发表评论。

——菲利克斯·盖森多夫


通过 RSS 或电子邮件订阅此博客,或者通过以下方式获取我的小更新 叽叽喳喳。





Source link

Postagens Similares

  • বোল্ডারিং

    বোল্ডারিংয়ের সাথে আমার প্রথম পরিচয় ছিল 2017 সালে, ব্রুকলিন ব্রিজ পার্কের ডাম্বো বোল্ডারে (এখন বন্ধ): আমি তখন এটাকে ঘৃণা করতাম কারণ এটা এত খোঁড়া মনে হয়েছিল। শুধু মানুষের উচ্চতা থেকে সবে উপরে উঠুন এবং আবার নিচে নেমে যান। আমি অবশ্যই এটা ভাল ছিল না. 6 বছর পরে, আমি এখন ~ দৈনিক বোল্ডারিংয়ের 2 মাস সম্পূর্ণ…

  • HazeOver — 用于突出显示最前面窗口的 Mac 实用程序

    2026 年 3 月 2 日星期一 早在 12 月,我就链接到了 Tyler Hall 的一个名为 Alan.app 的特技项目——一个简单的 Mac 实用程序,可以在当前活动窗口周围绘制一个粗体矩形。 Alan.app 允许您设置框架的厚度和颜色。我使用了一个小时左右,然后就退出了。它确实解决了在最新版本的 MacOS 中能够立即识别活动窗口的严重(且日益恶化)问题,但 Alan.app 的实现方式的粗糙性使其成为治本不如治病的情况之一。最终,我宁愿忍受几乎无法区分的活动窗口状态,也不愿每天看着 Alan.app 的原始活动窗口框架。 Alan.app 让我感兴趣的是它作为抗议应用程序的有效性。 Alan.app 的粗略解决方案的荒谬性凸显了根本问题的荒谬性——任何人甚至会 考虑 运行 Alan.app(或者 Hall 有意创建和发布它的事实)显示了最近的 MacOS 版本中的窗口 UI 有多么糟糕。 事实证明,有一个应用程序试图以一种您可能想要真正接受的优雅方式解决这个问题。它被称为 HazeOver,开发者 Maxim Ananov 在十年前首次发布了它。它在 Mac App Store 中的售价为 5 美元,包含在 SetApp 订阅服务中,并且可以从网站上免费试用。 HazeOver 的作用是通过调暗所有背景窗口来突出显示活动窗口。就是这样。但它能够沉着地完成这项简单的任务,并且对 MacOS 的日常可用性产生重大影响。不仅仅是 MacOS…

  • Фатальний щипок

    Грудень 2014 року Багато стартапів за кілька місяців до смерті проходять через такий момент, коли, хоча вони мають значну суму грошей у банку, вони також багато втрачають щомісяця, а зростання доходу або не існує, або є посереднім. Компанія має, скажімо, 6 місяців злітної смуги. Або, кажучи більш жорстоко, за 6 місяців до того, як вони…

  • Manton Reece – نیویارک ڈیٹا سینٹر توقف

    گورنر کیتھی ہوچل نے ڈیٹا سینٹر کی تعمیر کو روک دیا ہے۔ WXXI سے رپورٹنگ: گورنر کا حکم گزشتہ ماہ ریاستی مقننہ کے پاس کردہ ایک بل کے بعد ہے، جس میں ایک سال کی مہلت بھی شامل ہے۔ گورنر کی ٹیم کے ارکان کا کہنا ہے کہ بل پیچیدہ ہے اور اس پر کام…

  • E-Mail ist großartig, aber die Leute versuchen ihr Bestes, um sie zu ruinieren

    📅 13. November 2025 | ⏱️ ~1 Minute Lesezeit von Alex White Alex hat eine schöne Reflexion über die Wiederentdeckung der Freude an E-Mails als langsamere, bewusstere Art, mit Menschen zu kommunizieren, geschrieben. Es ist eine Lektüre wert, wenn Sie vermissen, dass sich der Posteingang wie ein Gespräch und nicht wie eine lästige Pflicht anfühlt….

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *