はじめに
地域のダウンロード窓口は、North Pier の実地ノートと庭園ボランティア向け資料を配布しています。窓口を閉じる前に、すでに受け付けたダウンロードを完了させたいところです。しかし最初の実装は接続を即座に閉じます。まず役に立つ完全な文書を取得し、その後で即時停止が何を中断するのかを正確に観察します。
Go の関数、ハンドラー、エラー値、および前の 2 プロジェクトで扱った goroutine/channel の責任分担、または同等の経験が必要です。プロセスの識別と SIGTERM はこの単元で説明します。名前の付いた 2 つのターミナルは、同じマシン上の別セッションです。準備済みの観測ツールは、このコースでビルドしたサーバーと curl 子プロセスだけを記録します。ネイティブトレースの形式を学ぶ必要はありません。読解や通常の入力ミスを含め、所要時間は約 45 分という著者の見積もりです。各単元は独立して開始します。
完全な文書を 1 つダウンロードする
このステップでは、完全で有用な文書を取得し、実際のバイトを確認します。
Downloads から始めます。両ターミナルの入口は既存の作業ディレクトリに移動するだけで、タブを開いても環境を作り直しません。通常のディレクトリ間違いが起きたら、次の明示的なコマンドで正しい場所に戻れます。
cd /home/labex/project/download-desk
元の 2 つのテキストファイルを読んでください。同じサンプルの別名ではなく、それぞれ異なる実用資料です。cat は内容を表示するだけで、ファイルを変更しません。
cat documents/north-pier.txt documents/garden-route.txt
この単元では、原本とすべての準備済みファイルを変更せずに保持します。desk のビルド、名前付きの観測試行の開始、ダウンロードの作成は可能です。Go ソースは変更しません。後の各単元には、それぞれ新しい独立したコピーがあります。
Server に切り替えます。Go 実行ファイルは絶対パスに用意されています。build はこのパッケージをコンパイルし、. は現在のパッケージ、-o desk は生成する実行ファイル名を指定します。go run のラッパーにシグナルを送る場合と異なり、ビルド済みバイナリなら対象プロセスを明確に識別できます。
cd /home/labex/project/download-desk
/usr/local/go/bin/go build -o desk .
名前付きの試行を開始します。付属の観測ツールはバイナリを起動し、実際のプロセス、HTTP リクエスト、シグナル、ネイティブ終了状態を記録します。グレースフルシャットダウンを実装するものではありません。first は試行名です。以前の証拠を黙って上書きしないよう、既存の名前は拒否されます。
python3 desk.py serve first
Ready. Use Downloads for client requests. を待ちます。このターミナルは元のプロセスが終了するまで使用中になります。表示される PID は観測ツールではなく、ビルドした Go 子プロセスのものです。Server は動かしたまま Downloads に切り替えます。
準備済みクライアントは実際の curl を実行し、そのネイティブなプロセス結果を記録して、実際の出力を保存します。4 つの引数は順に、試行、新しい出力ラベル、準備済み文書、32 バイトごとの遅延ミリ秒を指定します。遅延 0 は通常の高速サンプルです。ラベル normal では downloads/normal.txt が作られます。
python3 desk.py download first normal north-pier.txt 0
Original curl native exit: 0 が期待されます。0 は転送の完了を意味しますが、それだけでは内容を証明できません。cmp は実際のファイルをバイト単位で比較し、一致すれば何も表示しません。保存された有用な文書も読んでください。
cmp documents/north-pier.txt downloads/normal.txt
cat downloads/normal.txt
クライアントが接続拒否を報告したら、Server に戻って既存の出力を読みます。同じポートに別プロセスを繰り返し起動しないでください。Go がビルドエラーを報告したら、ディレクトリを直すか準備済みファイルと比較してから再ビルドします。新しいシェルは別のシェルの変数を引き継ぎませんが、ファイルと観測対象の試行は両セッションで共有されます。
受け付け済みのダウンロード中に元のサーバーを停止する
このステップでは、本当に受け付けられた転送を中断し、クライアントの失敗とサーバーの終了を区別します。
Server がまだ first を動かしている状態で、Downloads から始めます。プロセス ID(PID)は現在動いているプロセスを識別しますが、終了後に OS が同じ番号を再利用する場合があります。観測ツールは元のプロセスを見分けるため、実行ファイルのパス、現在のユーザー ID、/proc の Linux 起動 tick も確認します。シグナルは、このコースでビルドしたプロセスだけに送ってください。pkill の使用、観測ツールへの送信、プラットフォームのプロセスやシェル設定の変更は禁止です。
SIGTERM はプロセスに終了を求める通常の要求です。kill -TERM PID は特定の 1 つの PID にその要求を送ります。それ自体がダウンロードを待つわけではなく、プロセスが終わった証明にもなりません。準備済み Go プログラムはこのシグナルを受けると直ちに Close を呼び、main から戻ります。これから観察するのはその動作であり、ネットワーク障害ではありません。
低速転送を始める前に、予想される失敗と復旧を含め、このステップの残りを全部読んでください。 その後、操作ブロックを順番に実行します。この有限時間のリクエストが動いている間に、新しい概念の学習で手を止めないでください。この文書の操作時間は約 30 秒で、無制限ではありません。
有限時間の低速ダウンロードをバックグラウンドで開始します。& により、クライアントの実行中でも同じシェルに次のコマンドを入力できます。$! は直前のバックグラウンドジョブのプロセス ID で、代入によってその観測ジョブを保存し、後で wait がネイティブ結果を読み取れるようにします。公開されている 300ms の遅延は 32 バイトの書き込み間に入り、読む時間やタブ切り替えの余裕を作ります。制御された練習用転送であり、性能測定ではありません。
python3 desk.py download first interrupted north-pier.txt 300 & download_job=$!
何かを止める前に、すでに記録されたネイティブリクエストを観測ツールに読ませます。このコマンドは代わりのリクエストやシグナルを送りません。元のサーバーがこの実際のクライアントを受け付け、両者の識別情報がまだ存在すると報告する必要があります。標準の curl は小さなファイル書き込みをバッファーにためることがあるため、出力が一時的に空でもリクエストが始まっていないとは限りません。
python3 desk.py accepted first interrupted
元の識別情報を取得して調べます。$(...) はコマンドが表示した PID をシェル変数に保存し、後の引用符付き "$server_pid" はそれを 1 つの引数として渡します。補助ツールは古くなった PID/起動時刻/実行ファイル/UID の組み合わせを拒否します。
server_pid=$(python3 desk.py pid first)
python3 desk.py identity first
リクエストの受け付けを観測してから、正確なシグナルを送ります。
kill -TERM "$server_pid"
元のクライアント結果を読みます。wait はこのシェルのバックグラウンドジョブを待ちます。次のコマンドは 18 を返す想定です。 curl のバイト不足メッセージも出ます。これは失敗した転送を観測し終えた結果であり、成功マーカーで隠すべきコマンド失敗ではありません。
wait "$download_job"
echo $? は直前のネイティブ状態をすぐ表示し、期待値は 18 です。後から成功した cat はシェルの状態を置き換えるため、直ちに確認してください。
echo $?
cat downloads/interrupted.txt
原本と比較します。
cmp documents/north-pier.txt downloads/interrupted.txt
この比較は 1 を返し、部分ファイルが途中で終わったと報告する想定です。受信テキストは本物の North Pier の内容から始まりますが、不完全です。そのため、同じファイル名や空でないファイルだけでは、完全で使えるダウンロードの証拠にはなりません。Server に切り替え、Original server native exit: 0 を確認します。正常終了したサーバーでも、クライアントを中断させている場合があります。
Downloads に戻り、両方の結果を保持します。コースのチェックは既存の観測記録と実際のファイルを読むだけです。実行中のプロセスを止めたり、不足した中断操作を代行したりはしません。
シグナルを送る前に低速転送が完了するほど待ってしまった場合、それを中断と呼ばないでください。ネイティブ結果 0 を読み、完全なバイトを比較して保存します。first がまだ動いていれば、interrupted2 などの新ラベルで同じ低速コマンドを開始し、新しいバックグラウンドジョブを保存して、シグナル前に同じラベルで accepted を実行します。元のサーバーが終了済みなら Server に切り替え、古い試行を残して retry1 などの新試行を明示的に開始します。その後は download、accepted、pid、identity にその試行名と新しい出力ラベルを使います。チェックはこれらの新しい名前を受け付けます。部分ファイルのコピーではなく実際の観測を繰り返してください。終了済みまたは不明な転送は、再利用された PID に再びシグナルを送る許可ではありません。
以下は、まだ動いている同じ first 試行での完全な再試行です。古いクライアントが本当に終わってから使い、downloads/interrupted.txt は残します。開始前にすべてのブロックを読んでください。 新しいラベルが別の出力を作ります。
python3 desk.py download first interrupted2 north-pier.txt 300 & download_job=$!
python3 desk.py accepted first interrupted2
server_pid=$(python3 desk.py pid first)
python3 desk.py identity first
kill -TERM "$server_pid"
次の wait も 18 を返す想定です。すぐ確認し、新しい実際の部分ファイルを比較します(比較の期待値は 1)。
wait "$download_job"
echo $?
cmp documents/north-pier.txt downloads/interrupted2.txt
first がすでに終了していれば、代わりに Server で別の試行を開始します。
python3 desk.py serve retry1
準備完了メッセージの後、Downloads で 3 番目の新しい出力ラベルを使い、次の完全な手順を実行します。
python3 desk.py download retry1 interrupted3 north-pier.txt 300 & download_job=$!
python3 desk.py accepted retry1 interrupted3
server_pid=$(python3 desk.py pid retry1)
python3 desk.py identity retry1
kill -TERM "$server_pid"
wait "$download_job"
echo $?
wait は 18 を返すはずです。実際の出力を残し、不完全であることを確認します(比較の期待値は 1)。
cmp documents/north-pier.txt downloads/interrupted3.txt
元のダウンロード窓口を停止し、結果を保持した状態で終えます。通常のダウンロードはすでに完全で、引き続き読めます。チェック前に代替リスナーを動かしたままにしないでください。次の独立単元では活動中の転送を保全する方法を学びます。
まとめ
実際の完全なダウンロードを観察し、その後、転送の中断を元のサーバーへの正確な停止操作と結び付けました。接続拒否、部分的な転送、プロセスの正常終了は、それぞれ異なる事実を示します。



