Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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接続が確立された後、一定期間データが交換されない場合に、接続がまだ有効であるかを確認するために使用される機能です。これは、以下のような目的で利用されます。

  1. デッドピアの検出: 接続の相手側(ピア)がクラッシュしたり、ネットワークから切断されたりした場合に、アプリケーションがそれを検知できるようにします。キープアライブパケットへの応答がない場合、OSは接続が切断されたと判断し、アプリケーションにエラーを通知します。
  2. NAT/ファイアウォールのタイムアウト回避: 多くのネットワーク機器(NATルーターやファイアウォール)は、一定期間アイドル状態の接続を自動的に切断するタイムアウト設定を持っています。キープアライブパケットを定期的に送信することで、接続がアクティブであると認識させ、これらのタイムアウトによる意図しない切断を防ぐことができます。
  3. リソースの解放: デッドピアを早期に検出することで、サーバーやクライアントが不要なリソース(ソケット、メモリなど)を保持し続けることを防ぎ、リソースの効率的な利用を促進します。

TCPキープアライブの動作は、通常、以下の3つの主要なパラメータによって制御されます。

  • TCP_KEEPIDLE (または SO_KEEPALIVE_TIME): 接続がアイドル状態になってから、最初のキープアライブプローブを送信するまでの時間。
  • TCP_KEEPINTVL (または SO_KEEPALIVE_INTERVAL): 最初のプローブが送信された後、応答がない場合に、後続のプローブを送信する間隔。
  • TCP_KEEPCNT (または SO_KEEPALIVE_PROBES): 接続が切断されたと判断するまでに送信するプローブの最大回数。

Goのnet.TCPConn.SetKeepAlivePeriodメソッドは、これらのパラメータのうち、主にTCP_KEEPIDLETCP_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_KEEPIDLETCP_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設計において、特定のプラットフォームでの機能の有無をどのように扱うかという良い例です。

関連リンク

参考にした情報源リンク