Go on One VPS: Production Handbook

サーバー単体に置きっぱなしにできる Go サービスの書き方。シャットダウン、タイムアウト、メモリ、systemd を、掲載コードすべてに裏付けのあるリファレンスサービスとともに解説します。

Polar で購入: $39 買い切り · v0.1.0 · Polar からすぐにダウンロード

Go on One VPS: Production Handbook のカバー画像
モックアップではなく、実際のテスト実行の出力です。

想定している読者

Go を書いていて、サービスは Linux のサーバー単体で systemd の下に置いている方に向けた本です。バックグラウンドワーカーと SQLite を持つ API かもしれませんし、Webhook の受信サーバーや、社内の皆が頼っているツールかもしれません。動いてはいる。知りたいのは、その境界で何が起きるかです。リクエストが処理中のデプロイ、ヘッダーを送り終えないクライアント、メモリが足りないコンテナ、午前 3 時のクラッシュなどがあります。

Go のチュートリアルではありません。言語を理解していて、何かを出荷した経験があることを前提にしています。goroutine の入門をお探しなら、定評のある Go の入門書のほうが向いています。

収録内容

16 章、約 2,000 行の本文と、本中のすべての Go のコード掲載元になっている小さなリファレンスサービスです。60 個のコードブロックそれぞれが、テスト済みのソースと一致しているかをスクリプトで確認しているので、誰も実行していないスニペットが本文に紛れ込むことはありません。

#章
1小さなサービスのプロジェクト構成
2環境変数からの設定: すべて検証し、早く失敗させる
3log/slog による構造化ログ、シークレットを漏らさない
4HTTP サーバーのタイムアウト
5グレースフルシャットダウン
6ヘルスとレディネスの違い
7context、キャンセル、goroutine リークのチェック
8SQLite でのデータベースアクセス: WAL、書き込みは一本、マイグレーション
9エラーとパニック
10メトリクスと pprof を安全に使う
11テスト
12ビルド: 静的で再現可能なバイナリ
13systemd: ユニット、ハードニング、再起動、停止
14メモリ: 負荷がかかったときの Go プロセス
15リリースフォルダによるデプロイ
16よくある本番のバグと、それぞれを検出するチェック

ほかに、リファレンスサービス(標準ライブラリと SQLite ドライバー一つ)、負荷生成ツール、小さなメモリ実験、systemd ユニット、Dockerfile、チェックリスト、そしてクリーンなコンテナから全チェックを再実行する Docker ハーネスも付いています。直近の全実行の出力も含めているので、手元の結果と見比べられます。

テストで分かること

シャットダウンと systemd の章は、実際のバイナリを起動して本物のシグナルを送るテストで裏付けています。

試したこと結果
1.5 s のジョブが処理中に SIGTERM新規接続は 11 ms 後に拒否され、処理中のリクエストは 1.399 s で完了し、プロセスは 1.669 s 後にコード 0 で終了
アイドル状態のサービスに SIGTERM2 ms で終了
9 s のジョブがあり、シャットダウンの制限が 500 ms のときの SIGTERM515 ms 後にコード 1 で終了、ジョブはキューに戻された
ヘッダーをゆっくり送るクライアント、ヘッダータイムアウト 300 ms295 ms で接続を切断
3 s のリクエストが処理中の systemctl stopリクエストは 200 を返し、停止まで 3.19 s
systemd の下での kill -92.10 s 後に正常へ復帰
別々のディレクトリからの二回のビルドバイト単位で同一のバイナリ(対照として -trimpath を外すと異なる結果に)

systemd ユニットにはハードニングのオプションを入れています。ファイルの記述を信じるのではなく、稼働中のプロセスから結果を読み戻して確認しました。ケイパビリティなし、seccomp フィルター、読み取り専用の /usr と /etc、メモリ上限です。systemd-analyze security では、このユニットの露出スコアは 1.4 でした。

スループットとメモリ

条件は次のとおりです。Apple Silicon ノート PC 上の Docker Desktop、8 CPU、サービスと負荷生成ツールとデータベースを一つのコンテナに入れ、クライアント 16、モードごとに 8 秒の実行を三回。

モード毎秒のリクエスト数(3 回の実行)
書き込み9,190〜11,189(p99 8.4〜11.7 ms)
読み取り13,541〜18,421
ヘルスエンドポイント23,032〜26,757

常駐メモリは、アイドル時に 13 MiB、負荷テスト後に 23 MiB、ピークは 25 MiB でした。

GOMEMLIMIT を計測

14 章は「GOMEMLIMIT を設定しましょう」で終わりません。ライブヒープ 40 MiB の小さなプログラムを、80 MiB に制限したコンテナの中で動かします。制限なしでは、3 回中 3 回で OOM kill されました。GOMEMLIMIT=56MiB を付けると 3 回中 3 回とも生き延びましたが、代償としてガベージコレクションが約四倍に増えました。この制限がなぜソフトなのか、サイジングにどう響くのかも、本の中で説明しています。

動作要件と形式

Go 1.24 以降が必要です。Docker は、ハーネスを再実行したいときだけ使います。すべて Markdown、Go のソース、シェル、設定ファイルなので、PDF のロックもアカウント登録もなく、どこでも読めます。

よくある質問

初心者向けの本ですか?

いいえ。すでに Go を書いている方が対象です。扱うのは本番運用の側、つまり何かがおかしくなったときにプロセスがどう振る舞うかです。

Postgres も扱いますか?

リファレンスサービスとそのテストは SQLite を使っています。データベースの章では Postgres 向けの指針も載せています。

Go Webhook Receiver Starter とはどう違いますか?

スターターは、そのまま動かす小さな製品です。ハンドブックは、行儀のよい Go サービスの考え方と、その裏付けになるテストを扱います。使っているリファレンスサービスも別のものです。

コードを自分のプロジェクトで使えますか?

はい。ご自身のプロジェクトと、ご自身や勤務先のサーバーで使えます。本とキットの再販や再配布はしないでください。

変更履歴

  • 0.1.0: 初回リリース。

続きを読む

入手する

Polar で購入: $39

支払い、税、請求書は販売代行事業者の Polar が処理します。決済後にダウンロードリンクが届きます。