0Pricing
Go Academy · レッスン

ワーカープールパターン

並行実行数を制限します

「ワーカープールパターン」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

ワーカープールとは

ワーカープールは、共有チャネルからジョブを取り出す一定数のゴルーチンを起動します。タスクごとにゴルーチンを1つ起動するのではなく、N個のワーカーを起動して作業を供給します。

  • 同時に実行する処理数を制限する
  • 何千ものゴルーチンを作成せずに再利用する
  • データベースやAPIなどの共有リソースを保護する

並行性を制限する理由

ゴルーチンを無制限に起動すると、メモリやファイルディスクリプターを使い果たしたり、下流のサービスに過剰な負荷をかけたりする可能性があります。プールを使えば、一度に実行する作業量を制御できます。

取得するURLが10000個あるとしても、HTTPリクエストを10000個同時に送信したいわけではありません。20個のワーカーからなるプールなら、適切な範囲に保てます。

jobsチャネル

ジョブはjobsチャネルに流し込みます。各ワーカーはfor rangeループでそこから読み取ります。チャネルが閉じられるとループが終了し、ワーカーも終了します。

jobs := make(chan int, 100)
for j := 1; j <= 5; j++ {
    jobs <- j
}
close(jobs)

単一のワーカー

ワーカーは、jobsチャネルをrangeする関数にすぎません。各ジョブを処理し、結果をresultsチャネルに書き込みます。

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        results <- j * 2
    }
}

複数のワーカーを起動する

単純なループでプールを起動します。各反復で、同じワーカー関数を実行するゴルーチンを1つ起動します。すべてのワーカーが同じjobsチャネルとresultsチャネルを共有します。

for w := 1; w <= 3; w++ {
    go worker(w, jobs, results)
}

方向付きチャネル型

ワーカーのシグネチャにある<-chan int(受信専用)とchan<- int(送信専用)に注目してください。これらの方向付き型により、ワーカーが誤ってjobsに送信したり、resultsから読み取ったりするのをコンパイラーが防げます。

結果を収集する

すべてのジョブを送り、チャネルを閉じた後、メインのゴルーチンはジョブ数と同じ数の結果を読み取ります。これによりプログラムが早期終了しないよう同期できます。

sum := 0
for a := 1; a <= 5; a++ {
    sum += <-results
}
fmt.Println("total:", sum)

完全に実行できるプール

1つのプログラムにまとめた完全なパターンを見てみましょう。3つのワーカーが5つの数値を2倍にします。実行して合計を確認してください。

package main

import "fmt"

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        results <- j * 2
    }
}

func main() {
    jobs := make(chan int, 5)
    results := make(chan int, 5)
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)
    total := 0
    for a := 1; a <= 5; a++ {
        total += <-results
    }
    fmt.Println("total:", total)
}

バッファ付きとバッファなし

バッファ付きのjobsチャネルでは、バッファが満杯になるまで、プロデューサーはブロックせずに作業をキューに入れられます。バッファなしのチャネルでは受け渡しが必要になり、ワーカーの準備が整うまで送信がブロックされます。バッファリングにより、作業が急増するプロデューサーの負荷を平滑化できます。

プールサイズを選ぶ

CPUバウンドの処理では、プールサイズをruntime.NumCPU()に近づけます。I/Oバウンドの処理(ネットワークやディスク)では、ワーカーは計算ではなく待機に時間を使うため、もっと大きくできます。

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("CPUs:", runtime.NumCPU())
}

ゴルーチンリークを避ける

close(jobs)を忘れると、ワーカーは空のチャネルで永遠にブロックし、リークします。すべての作業を送信し終えたら必ずjobsチャネルを閉じ、for rangeループを終了させてください。

クイックチェック

ワーカープールについての理解度を確認しましょう。

まとめ

ワーカープールパターンについて学びました。

  • 共有の jobs チャネルから読み取るワーカーを固定数起動します
  • 安全性のために方向付きチャネル型を使用します
  • ワーカーを終了するには jobs チャネルを閉じます
  • 結果を収集して処理の完了を同期します
  • ワークロードの種類(CPU と IO)に応じてプールのサイズを決めます

よくある質問

「ワーカープールパターン」レッスンは無料ですか?

はい。「ワーカープールパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「ワーカープールパターン」で何を学びますか?

並行実行数を制限します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「ワーカープールパターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ワーカープールパターン
  2. Fan-OutとFan-In
  3. パイプラインのステージ
  4. グレースフルシャットダウン
← Go Academyに戻る