日記マン

動画広告プロダクトしてます。Go, Kubernetesが好きです。

12月振り返り

まさかの一年ではなく今月に限定して振り返ってみる。。

  • 実務と関係あること
    • Go言語のランタイムの動作理解(netpoller周り)
    • Kubernetesの拡張性 AdapterパターンとOperatorパターン
    • システムパフォーマンス
    • 継続的プロファイリング
    • プロダクトを継続させるための考え方
  • ただの興味
    • Rustの async-std
続きを読む

GoはネットワークI/Oをどう実現しているか

goroutine自体はOSスレッドに多重化してスケジュールされる。
ランタイムでは goroutine関数をG、OSスレッドをM、GをMに割り当てるスケジューラをP、と名称し実装されている。

qiita.com

ではG全てがI/O実行を行いブロック状態になった場合、Gに紐づかれたMがそのままブロック状態になるのだろうか。
100個のgoroutineが同時にI/O待ちのときに、100個のOSスレッドがI/O待ちの状態になっているのか。

結論からいうとならない。なぜならラインタイム以下で非同期I/Oを実現している。
ネットワークI/Oの場合はGoの標準ライブラリではあたかもブロッキングI/Oのようなインターフェイスを提供しているが、
Goランタイム(で動くsysmonという特別なワーカー)が待ち状態のgoroutineのI/Oを非同期I/Oに変換している。
(Linux環境ではepoll(7)を使う)
そのためOSスレッド自体はネットワークI/O待ちのブロック状態にならずに別のgoroutineの実行を受け入れることができる。

続きを読む

Goのサーバサイドアプリケーションのパフォーマンス可視化に向けたメトリクス設計

最近はGoで書いたアプリケーションをKubernetesで運用し始めたが、
アプリケーションの内部状態を計測できるようにObservabilityの確保にトライしている。

「Observabilityがなぜ必要だと考えるか」について山口さんのエントリはとても学びになった。

ymotongpoo.hatenablog.com

顧客に対し、不便や不満のないようにサービスを提供できているか。
リソースの状態のみならずサービスの健康状態を表すアプリケーションレベルのメトリクスは、可観測性の確保において重要になる。
例えばHTTP応答レイテンシやエラー率などである。
Goならばメモリ管理がGCなのでランタイムレベルのメトリクスも重要になる。
例えばGCの発生頻度や実行レイテンシ。
これらをアプリケーションプロセス側がメトリクスを収集可能に実装することをInstrumentationと呼ぶ。

続きを読む

GoにおけるDBクライアントの設計とObservabilityの確保

Goで sql.DB を扱ってMySQLを扱うとき、
インターフェイスの実装、チューニングできる設定値への理解、Observabilityをどのように確保すればよいか。
ある程度知識がまとまってきたのでアウトプットする。
(実際は sql.DB にない構造体バインディングが欲しかったので sqlx.DB を使っている。)

DBクライアント

func main() {
    stop := utils.SignalHandler(logger)
    cleanup, err := adapter.SetupMySQL(cfg, logger)
    defer func() {
        <-stop
        cleanup()
    }()
     
    db := adapter.GetMySQL()
    // ...
}

DBクライアントのセットアップ関数を実行しクリーンアップ用のコールバックを受け取るインターフェイス

続きを読む