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

バッチ処理をパイプラインパターンで上手くやる

yusuke misawa
September 17, 2019

 バッチ処理をパイプラインパターンで上手くやる

yusuke misawa

September 17, 2019
Tweet

More Decks by yusuke misawa

Other Decks in Programming

Transcript

  1. 話の流れ • なにかとバッチ処理を作る機会があるという話 • バッチ処理作成時の課題がいろいろあるよねという話 • パイプラインパターンでうまくやろうという話 ◦ パイプラインとはステージと呼ばれるデータ操作の組み合わせのパターン ◦

    ステージをうまくやるためのパターン(ファンアウト・ファンイン・キャンセル) • パイプラインを使えばうまく作れそうだが残る課題として ◦ ゴルーチンがリークしないようにする話 ◦ チャネルのブロックと panicを防ぐ話 • まとめ
  2. 並行処理のパターンに関する情報源 • The Go Blog:Go Concurrency Patterns: Pipelines and cancellation

    ◦ https://blog.golang.org/pipelines • 書籍「Go言語による並行処理」 ◦ オライリージャパン ◦ Katherine Cox-Buday 著、山口 能迪 訳 ◦ 原書: Concurrency in Go ◦ https://www.oreilly.co.jp/books/9784873118468/ 
  3. パイプライン全体の擬似コード // ステージ1(ctx以下は入力) in := gen(ctx, 1,2,3,4,5) //genは受信専用チャネルinを返す // ステージ2

    (ファンアウト) c1 := sq(ctx,in) // 何らかの操作を並行実行 c2 := sq(ctx,in) // c1,c2は実行結果の受信専用チャネル // ステージ3(ファンイン) for n := range merge(ctx,c1, c2) { // mergeもc1,c2をまとめた受信専用チャネルを返す fmt.Println(n) }
  4. バッチ処理作成時の課題(再掲) • 処理量が多いので並行処理しようとするが複雑化 ◦ ◎パイプラインで見通し良さそう • 動きそうだがオレオレ実装で可読性が悪くレビューもし辛い ◦ ◎パイプラインの考え方が共有されていれば話が早そうだしコードの見通し良さそう。 •

    できれば再利用・拡張性あるものにしたい ◦ ◎パイプラインで拡張性良さそう • ゴルーチンがうまく扱えているか不安 ◦ パイプラインのステージ内の実装による • チャネルがうまく扱えているか不安 ◦ パイプラインのステージ内の実装による
  5. ゴルーチンのリークが起きないようにしたい • リーク(=漏れ) ◦ 情報のリーク:関係者がマスコミに秘密を漏らしちゃう • ゴルーチンのリーク ◦ 非メインのゴルーチンが終了せず残り続けること。 ◦

    ガベージコレクションで回収されずその分メモリを圧迫する。 ◦ バッチ処理の場合どこかでプロセスが終わるので永遠に増え続けることはな いが意図しないリークは避けたい。
  6. パイプラインでチャネルをうまく扱う • panicが起きる条件を知る ◦ closedチャネルへの送信(https://play.golang.org/p/puTTlBWgSTh) ◦ closedチャネルのclose ◦ nilチャネルのclose •

    意図せずブロックしないようにする ◦ nilチャネルの読み書きをしない(https://play.golang.org/p/jCnURn3qaiU ) ◦ 所有権(誰が初期化するか、送受信の制限)を決める
  7. バッチ処理作成時の課題(再々掲) • 処理量が多いので並行処理しようとするが複雑化 ◦ ◎パイプラインで見通し良さそう • 動きそうだがオレオレ実装で可読性が悪くレビューもし辛い ◦ ◎パイプラインの考え方が共有されていれば話が早そうだしコードの見通し良さそう。 •

    できれば再利用・拡張性あるものにしたい ◦ ◎パイプラインで拡張性良さそう • ゴルーチンがうまく扱えているか不安 ◦ ◎コンテキストで処理終了を伝えゴルーチンのリークを回避 • チャネルがうまく扱えているか不安 ◦ ◎チャネルの作成者と消費者で役割分担し不要なブロックや panicを回避
  8. パイプラインまとめ ステージ1 ステージ2 ステージ3 入力 出力 • パイプラインは入力を受け取りステージと呼ばれる独立したデータ操作の組み合わせるパターン • ステージの組み合わせで柔軟に処理の分割、並行実行が可能になる。

    ◦ ステージ同士はチャネルでデータを受け渡しする • ステージ(個々のデータ操作を上手くやる)のためのパターン ◦ ファンアウト・ファンイン(ステージ同士の連携のためのパターン) ◦ コンテキストキャンセル(ステージを安全に終了するためのパターン) ◦ ジェネレーターとコンシューマー(ステージを安全に終了するための役割分担のパターン)
  9. 最後に • バッチ処理作成時に課題と思ったいくつかのトピックは解決できた。 しかし並行処理の沼はまだまだ深い。 ◦ 競合状態 ◦ ロック ◦ エラー処理

    ◦ ゴルーチンのスケジューリング ◦ 並行処理の速度・律速問題 etc… • 今ここで話すために並行処理の勉強をしたけどまだ氷山の一角に過ぎないと感じ た。これからも備えていきたい。 • 懇親会では是非声をかけてください。