Upgrade to Pro — share decks privately, control downloads, hide ads and more …

gobpfでPostgreSQLを動的トレーシングする

 gobpfでPostgreSQLを動的トレーシングする

gobpfは、eBPFをGoのコードから扱えるようにしたフレームワークである。eBPFを使えば、カーネルレベルのさまざまな処理にフックして任意の処理を動作させることが可能となる。gobpfの使い方の例として、PostgreSQLの動的トレーシングを取り上げ、Goによる低レイヤな分析ツールが容易に作成可能であるかを紹介する。たとえば、実行した個別のクエリが消費したワーキングメモリのサイズであったり、共有バッファに読み込んだブロックサイズをGoのプログラムで取得できるので、パフォーマンスチューニングやトラブルシュートに役立てることができるようになるかもしれない。

Jun Uchino

May 18, 2019
Tweet

Other Decks in Technology

Transcript

  1. 自己紹介 • Twitter: @u3jun, Github: @ujun • インフラエンジニア @Sansan株式会社 •

    法人向け名刺管理サービス Sansan • 普段はPython(2多め 好きなモジュールはclickやconcurrent.futures) • Goは書いてない • PostgreSQL9.6 on AWS EC2 の運用 • さまざまな理由からマネージドDBに移行できない • 業務外だと最近は複雑ネットワーク推し
  2. BPFとは • Linux 4.* から 導入された (RHELはで8から) • 特定のカーネル内のイベントにフックして任意の処理を簡単に書けます •

    各種MW等で定義されたトレーシング用のエントリポイント(USDT)にフックしていろいろ できる(Dtrace SystemTapと同じ様) • Nginx • Python • MySQL • PythonやLuaやGoなど各種言語でBPFを容易に扱えるフレームワークが開発されてお りそれを使う
  3. PostgtrSQLが動的トレース用に定義したエントリポイントにフッ クしてGoのコードを実行することができる BPF Map BPF Program PostgreSQL Events BPF Hook

    smgr-md-read-done transaction-start query-plan-start userland kernel Go Frontend ① ② ③ ④ ① 動的トレースポイントにアタッチしてイベン トを捕捉したいBPFプログラムを書く(大抵C) ② 捕捉したい対象のエントリポイント(プロー ブ)に①をアタッチする ③ BPFプログラムが受け取りたいメトリクスを ユーザランドに持ってくる ④ 採取したデータを用いて任意の処理をす る
  4. 現時点でのgobpfでPostgreSQLのUSDTを触る(面倒) BPF Map BPF Program Go Frontend query_blk_read.go --- //

    cgoでごりごり書く必要がある /* #cgo CFLAGS: -I/usr/include/bcc/compat #cgo LDFLAGS: -lbcc #include <bcc/bcc_usdt.h> #include <bcc/bcc_common.h> */ import "C" // インラインでCのBPF Program(query_blk_read)を書く int query_blk_read(struct pt_regs *ctx) {…} ・・・ // BPF Programの結果を受け取る structを書く type readlineEvent struct {…} ・・・ // プローブ(smgr__md__read__done)にたいしてフックする関数(query_blk_read)をアタッチする context := C.bcc_usdt_new_frompid(C.int(2228), nil) C.bcc_usdt_enable_probe(context, C.CString("smgr__md__read__done"), C.CString("query_blk_read")) usdt_text := C.bcc_usdt_genargs(&context, 1) m := C.bpf_module_create_c_from_string(usdt_text, C.uint(0), nil, C.int(0), C.bool(false) ① ② ③