close イベントが来ないとき
自分のソケットの close イベントを待ってから後始末するクライアントは、そのイベントが届かないと、黙って止まることがあります。接続を終えると決めた時点で状態を確定させ、後始末を冪等にし、イベントは自分が始めていない切断のために残します。
自分のソケットの close イベントを待ってから後始末するクライアントは、そのイベントが届かないと、黙って止まることがあります。接続を終えると決めた時点で状態を確定させ、後始末を冪等にし、イベントは自分が始めていない切断のために残します。
複数言語が同居するコードベースで得た 5 つの手法をまとめます。既存の Go コードへの golangci-lint の段階導入、CI でのレースディテクタの常時実行、サブプロセスの寿命の制御、bootout の競合を避けた launchd サービスの再登録、そして外部キーを踏まえた PostgreSQL の行ロック強度の選び方です。
稼働中のデーモンをリクエストを落とさずに入れ替える手順書です。小さなTCPサーバーを本物のsystemdで動かして試しました。単純なrestartは毎回、接続の拒否かリセットを起こしました。SO_REUSEPORTで新旧を並べる方法は拒否ゼロでしたが、一部の回でリセットが出て、カーネルの設定でそれが消えました。ソケットアクティベーションはエラーなしでした。処理中リクエストのドレインとTimeoutStopSecの関係、新バージョンを確認して巻き戻すリリース切り替えも扱います。
自分自身を更新するデーモンが、更新用のヘルパーを起動してから自分のユニットを再起動すると、落とし穴があります。ヘルパーはサービスのcgroupの中で起動し、再起動時にsystemdがそのcgroupの中身を全部終了させるからです。使い捨てのsystemdで試すと、setsidしたヘルパーは最後のログ行を出す前に消え、KillMode=processでは生き残るものの次のインスタンスに紛れ込み、systemd-runなら独立したユニットとして最後まで動きました。証拠、直し方、試していないことを書きます。
Durable Object のアラームは1つだけで、少なくとも1回実行され、失敗するハンドラーはバックオフ付きで最大6回再試行されます。それが尽きると、オブジェクトを再び起こすものは何もありません。この3つに耐えるリース失効の台帳を、コードに注釈をつけて見ていきます。真実を持つ表、アラームを再設定するコンストラクター、2回実行されても困らない副作用です。ローカルの workerd で動かし、制限は Cloudflare の文書から引用しています。
端末がオフラインのとき、アプリが終了されたとき、送信が多すぎるときにプッシュがどうなるかを、AppleとGoogleは文書で説明しています。通知は置き換えられ、捨てられ、順序が入れ替わり、遅れます。文書に書かれた失敗モードの表と、ペイロードを適用するクライアントが収束せず、カーソルから取得するクライアントが収束することを示す小さなシミュレーションを紹介します。
AppleとAndroidの公式ドキュメントには、バックグラウンドのアプリは一時停止され、ネットワークが止められ、既存の接続が閉じられうると書かれています。つまり、フォアグラウンドに戻ったときの readyState === OPEN は、最後に処理したイベントの記憶にすぎません。この記事では、その記述から「確認する、作り直す、取りこぼしを取り戻す」という小さなルーチンを導き、Linux上の凍結プロセスという代役で動かします。実機では試していない点も、はっきり書きます。
たくさんのリクエストを同時に流している1本の接続で、1つのリクエストの期限が来たとき、接続ごと閉じるべきか、そのリクエストだけを閉じるべきか。小さなNodeの実験では、HTTP/2のセッションを閉じると無関係な2本が失敗し、ストリームだけをキャンセルすると同じTCP接続のまま2本とも完了しました。ただし、TCPの1パケットの遅れは接続上の全ストリームを止めます。その場合に接続の生死を確かめる方法として、PINGを使った確認も試します。
再接続したクライアントが、状態を取りこぼさず、重複せず、履歴を読み直さずに追いつく方法を、「全部読み直す」から「上限つきのログとスナップショットのフォールバック」まで、版0から版4まで段階的に組み立てます。ブラウザの EventSource が再接続時と non-200 応答のときに実際に何をするか、スナップショットの順序のバグ、決定木も扱います。
リクエストがタイムアウトしたとき、クライアントはリクエストが失われたのか、確認応答だけが失われたのかを区別できません。だから「ちょうど1回」の配送は作れず、実際にできるのは「少なくとも1回の配送」と「重複を除く受け手」の組み合わせです。不安定なネットワークでの実験、正しく見えて89件を重複させるバグ、原子的な重複排除ストア、ジッターのシミュレーションで確かめます。
TCP は、相手がいなくなったことを教えてくれません。読み取り側は永遠にブロックし、書き込み側は十数分も再送を続け、SO_KEEPALIVE は未確認のデータがあるあいだ何もしません。この記事では、root 不要の1ファイルの Linux 実験環境を作り、何もしない、keepalive、TCP_USER_TIMEOUT、アプリケーションのハートビートという順に仕組みを積み上げて、気づくまでの時間を測ります。NAT と RFC がどこに関わるかも整理します。
一定間隔の keepalive は、接続が忙しいときでも双方向に1メッセージずつ使います。受信したフレームをすべて生存の証拠として扱い、静かな接続だけを確認し、既存のハートビートで待機中のホストに切断してよいかを伝えれば、その大半を減らせます。代償は、上限のある復帰の遅延です。
自分のソケットの close イベントを待ってから後始末するクライアントは、そのイベントが届かないと、黙って止まることがあります。接続を終えると決めた時点で状態を確定させ、後始末を冪等にし、イベントは自分が始めていない切断のために残します。
複数言語が同居するコードベースで得た 5 つの手法をまとめます。既存の Go コードへの golangci-lint の段階導入、CI でのレースディテクタの常時実行、サブプロセスの寿命の制御、bootout の競合を避けた launchd サービスの再登録、そして外部キーを踏まえた PostgreSQL の行ロック強度の選び方です。