[インデックス 16922] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージにおいて、Plan 9オペレーティングシステム向けのTCPソケット実装にSetKeepAlivePeriod
メソッドを追加するものです。これにより、Plan 9環境でもTCPキープアライブの期間を設定できるようになります。
コミット
commit 8f32df5455c08d8bffd17e0bd69aab9386a97b29
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Tue Jul 30 16:29:51 2013 +0900
net: add missing SetKeepAlivePeriod for Plan 9
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/12082045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8f32df5455c08d8bffd17e0bd69aab9386a97b29
元コミット内容
net: add missing SetKeepAlivePeriod for Plan 9
このコミットは、Goのnet
パッケージにおいて、Plan 9オペレーティングシステム向けにSetKeepAlivePeriod
メソッドが欠落していたため、それを追加するものです。
変更の背景
TCPキープアライブは、アイドル状態のTCP接続がまだ有効であるかを確認するために定期的にパケットを送信するメカニズムです。これにより、ネットワークの途中で接続が切断された場合でも、アプリケーションがそれを検知し、リソースを解放することができます。SetKeepAlive
メソッドはキープアライブを有効/無効にするものですが、SetKeepAlivePeriod
はキープアライブプローブを送信する間隔を設定するために使用されます。
Goのnet
パッケージは、様々なオペレーティングシステムに対応するために、OS固有の実装を持っています。このコミット以前は、Plan 9向けのtcpsock_plan9.go
ファイルにはSetKeepAlive
メソッドは存在していましたが、キープアライブの期間を設定するためのSetKeepAlivePeriod
メソッドが実装されていませんでした。
この欠落は、Plan 9上で動作するGoアプリケーションが、TCPキープアライブの動作を細かく制御できないことを意味していました。特に、長期間アイドル状態になる可能性のある接続(例: データベース接続、チャットアプリケーションの接続など)では、キープアライブ期間の適切な設定が重要になります。このコミットは、この機能のギャップを埋め、Plan 9環境におけるネットワークプログラミングの柔軟性を向上させることを目的としています。
前提知識の解説
TCPキープアライブ (TCP Keep-Alive)
TCPキープアライブは、TCP接続が確立された後、一定期間データが交換されない場合に、接続がまだ有効であるかを確認するために使用される機能です。これは、以下のような目的で利用されます。
- デッドピアの検出: 接続の相手側(ピア)がクラッシュしたり、ネットワークから切断されたりした場合に、アプリケーションがそれを検知できるようにします。キープアライブパケットへの応答がない場合、OSは接続が切断されたと判断し、アプリケーションにエラーを通知します。
- NAT/ファイアウォールのタイムアウト回避: 多くのネットワーク機器(NATルーターやファイアウォール)は、一定期間アイドル状態の接続を自動的に切断するタイムアウト設定を持っています。キープアライブパケットを定期的に送信することで、接続がアクティブであると認識させ、これらのタイムアウトによる意図しない切断を防ぐことができます。
- リソースの解放: デッドピアを早期に検出することで、サーバーやクライアントが不要なリソース(ソケット、メモリなど)を保持し続けることを防ぎ、リソースの効率的な利用を促進します。
TCPキープアライブの動作は、通常、以下の3つの主要なパラメータによって制御されます。
- TCP_KEEPIDLE (または SO_KEEPALIVE_TIME): 接続がアイドル状態になってから、最初のキープアライブプローブを送信するまでの時間。
- TCP_KEEPINTVL (または SO_KEEPALIVE_INTERVAL): 最初のプローブが送信された後、応答がない場合に、後続のプローブを送信する間隔。
- TCP_KEEPCNT (または SO_KEEPALIVE_PROBES): 接続が切断されたと判断するまでに送信するプローブの最大回数。
Goのnet.TCPConn.SetKeepAlivePeriod
メソッドは、これらのパラメータのうち、主にTCP_KEEPIDLE
とTCP_KEEPINTVL
に影響を与えます。
Plan 9
Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現するという特徴を持っています。これにより、シンプルなファイル操作のインターフェースを通じて、様々なリソースにアクセスできる統一的な環境を提供します。
Go言語は、その設計思想の一部にPlan 9の影響を受けており、特に初期のGoコンパイラやツールチェインはPlan 9のツールチェインから派生しています。そのため、Goの標準ライブラリには、Plan 9固有のシステムコールやインターフェースに対応するためのコードが含まれていることがあります。
syscall.EPLAN9
syscall.EPLAN9
は、Goのsyscall
パッケージで定義されているエラーコードの一つで、特定の操作がPlan 9オペレーティングシステムではサポートされていないことを示すために使用されます。このコミット以前のSetKeepAlive
メソッドの実装では、Plan 9でキープアライブがサポートされていないことを示すためにこのエラーを返していました。しかし、このコミットでSetKeepAlivePeriod
が追加されることで、Plan 9でもキープアライブ期間の設定が可能になります。
技術的詳細
このコミットの技術的なポイントは、Goのnet
パッケージがOS固有のネットワーク操作をどのように抽象化しているか、そしてPlan 9のような非UNIX系OSへの対応をどのように行っているかという点にあります。
Goのnet
パッケージは、クロスプラットフォームなネットワークプログラミングインターフェースを提供しますが、その内部では各OSのシステムコールを呼び出すための抽象化レイヤーが存在します。src/pkg/net/tcpsock_plan9.go
は、Plan 9オペレーティングシステムに特化したTCPソケットの動作を定義するファイルです。
SetKeepAlivePeriod
メソッドは、time.Duration
型の引数d
を受け取り、この期間をTCPキープアライブのアイドル時間またはプローブ間隔として設定します。しかし、Plan 9のネットワークスタックが直接的にTCP_KEEPIDLE
やTCP_KEEPINTVL
のようなソケットオプションをサポートしているわけではないため、このコミットでは、SetKeepAlivePeriod
の実装もSetKeepAlive
と同様にsyscall.EPLAN9
を返すようにしています。これは、Plan 9のネットワークスタックがキープアライブ期間の細かな制御をサポートしていない、あるいはGoのnet
パッケージがその機能をPlan 9上で完全にエミュレートできないことを示唆しています。
つまり、このコミットは、APIの整合性を保つためにSetKeepAlivePeriod
メソッドを追加したものの、Plan 9のシステム的な制約により、その機能はまだ完全に利用できない状態であることを示しています。これは、Goの標準ライブラリが、特定のOSの機能的な制約に直面した場合に、どのようにAPIの互換性を維持しつつ、その制約を表現するかの一例と言えます。
コアとなるコードの変更箇所
変更はsrc/pkg/net/tcpsock_plan9.go
ファイルにのみ行われています。
--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/pkg/net/tcpsock_plan9.go
@@ -65,6 +65,11 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
return syscall.EPLAN9
}
+// SetKeepAlivePeriod sets period between keep alives.
+func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
+ return syscall.EPLAN9
+}
+
// SetNoDelay controls whether the operating system should delay
// packet transmission in hopes of sending fewer packets (Nagle\'s
// algorithm). The default is true (no delay), meaning that data is
コアとなるコードの解説
追加されたコードは以下の5行です。
// SetKeepAlivePeriod sets period between keep alives.
func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
return syscall.EPLAN9
}
-
// SetKeepAlivePeriod sets period between keep alives.
これは、追加されたメソッドの目的を説明するコメントです。SetKeepAlivePeriod
がキープアライブ間の期間を設定するものであることを示しています。 -
func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error { ... }
これは、TCPConn
型に新しいメソッドSetKeepAlivePeriod
を追加するGoの関数シグネチャです。c *TCPConn
:TCPConn
型のレシーバc
を持つメソッドであることを示します。これにより、TCPConn
のインスタンスに対してこのメソッドを呼び出すことができます。d time.Duration
: キープアライブ期間として設定する時間を表すtime.Duration
型の引数d
を受け取ります。error
: メソッドがエラーを返す可能性があることを示します。
-
return syscall.EPLAN9
この行が、このコミットの最も重要な部分です。SetKeepAlivePeriod
メソッドが呼び出された際に、常にsyscall.EPLAN9
エラーを返します。これは、前述の通り、Plan 9オペレーティングシステムではこの機能が直接サポートされていないため、Goのnet
パッケージがその制約をAPIレベルで表現していることを意味します。
この変更により、Goのnet
パッケージのAPIは、他のOS向けの実装と整合性が取れるようになりました。つまり、TCPConn
オブジェクトは、どのOS上でもSetKeepAlivePeriod
メソッドを持つことになりますが、Plan 9上ではその呼び出しが常にエラーを返すことで、機能が利用できないことを明示します。これは、クロスプラットフォームなAPI設計において、特定のプラットフォームでの機能の有無をどのように扱うかという良い例です。
関連リンク
- Go言語の
net
パッケージドキュメント: https://pkg.go.dev/net - Go言語の
syscall
パッケージドキュメント: https://pkg.go.dev/syscall - Plan 9 from Bell Labs: https://9p.io/plan9/
参考にした情報源リンク
- コミットのGitHubページ: https://github.com/golang/go/commit/8f32df5455c08d8bffd17e0bd69aab9386a97b29
- Go CL 12082045: https://golang.org/cl/12082045 (コミットメッセージに記載されているChange ListのURL)
- TCP Keep-Aliveに関する一般的な情報源 (例: Wikipedia, RFCなど)
- Wikipedia (TCP keepalive): https://en.wikipedia.org/wiki/TCP_keepalive
- Goの
net.TCPConn.SetKeepAlivePeriod
に関する情報 (Web検索結果より)- bencane.com (Go TCP Keep-Alive): https://www.bencane.com/2020/07/27/go-tcp-keep-alive/
- felixge.de (Go TCP Keep-Alive on Linux and macOS): https://felixge.de/2017/07/27/go-tcp-keep-alive-on-linux-and-macos.html