0Pricing
Go Academy · Lekcja

Wzorzec puli workerów

Ograniczaj współbieżność

Wzorzec puli workerów to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.

Czym jest pula workerów

Pula workerów uruchamia stałą liczbę goroutines, które pobierają zadania ze wspólnego kanału. Zamiast uruchamiać jedną goroutine dla każdego zadania, uruchamiasz N workerów i dostarczasz im pracę.

  • Ogranicza liczbę operacji wykonywanych współbieżnie
  • Ponownie wykorzystuje goroutines zamiast tworzyć ich tysiące
  • Chroni współdzielone zasoby, takie jak bazy danych lub interfejsy API

Dlaczego warto ograniczać współbieżność

Nieograniczona liczba goroutines może wyczerpać pamięć lub deskryptory plików albo przeciążyć usługę, z którą się komunikujesz. Pula daje możliwość kontrolowania, ile pracy jest wykonywane jednocześnie.

Jeśli masz do pobrania 10000 adresów URL, nie chcesz wysyłać 10000 jednoczesnych żądań HTTP. Pula 20 workerów utrzymuje sytuację pod kontrolą.

Kanał jobs

Zadania trafiają do kanału jobs. Każdy worker odczytuje je w pętli for range. Gdy kanał zostanie zamknięty, pętla się kończy, a worker zostaje zamknięty.

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

Pojedynczy worker

Worker to po prostu funkcja, która iteruje po kanale jobs. Przetwarza każde zadanie i zapisuje wynik w kanale results.

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

Uruchamianie wielu workerów

Uruchom pulę za pomocą prostej pętli. Każda iteracja uruchamia jedną goroutine wykonującą tę samą funkcję workera. Wszystkie współdzielą kanały jobs i results.

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

Kierunkowe typy kanałów

Zwróć uwagę na <-chan int (tylko do odbioru) oraz chan<- int (tylko do wysyłania) w sygnaturze workera. Te kierunkowe typy pozwalają kompilatorowi powstrzymać workera przed przypadkowym wysyłaniem do jobs lub odczytywaniem z results.

Zbieranie wyników

Po dostarczeniu wszystkich zadań i zamknięciu kanału główna goroutine odczytuje dokładnie tyle wyników, ile było zadań. Synchronizuje to program, dzięki czemu nie kończy się on zbyt wcześnie.

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

Kompletna, uruchamialna pula

Oto cały wzorzec w jednym programie: trzy workery podwajają pięć liczb. Uruchom program i sprawdź sumę.

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)
}

Buforowany a niebuforowany

Buforowany kanał jobs pozwala producentowi kolejkować pracę bez blokowania, dopóki bufor się nie zapełni. Kanał niebuforowany wymusza przekazanie: wysyłanie blokuje się, dopóki worker nie będzie gotowy. Buforowanie łagodzi nagłe skoki liczby zadań od producenta.

Dobór rozmiaru puli

W przypadku pracy ograniczonej przez CPU ustaw rozmiar puli w pobliżu wartości runtime.NumCPU(). W przypadku pracy ograniczonej przez operacje wejścia-wyjścia (sieć, dysk) możesz użyć znacznie większej puli, ponieważ workery spędzają czas na oczekiwaniu, a nie na obliczeniach.

package main

import (
    "fmt"
    "runtime"
)

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

Unikanie wycieków goroutines

Jeśli zapomnisz o close(jobs), workery będą bez końca blokować się na pustym kanale, powodując wyciek. Zawsze zamykaj kanał jobs po przesłaniu całej pracy, aby pętle for range mogły się zakończyć.

Szybki test

Proszę sprawdzić zrozumienie pul workerów.

Podsumowanie

Poznali Państwo wzorzec puli workerów:

  • Uruchamianie stałej liczby workerów odczytujących dane ze współdzielonego kanału zadań
  • Używanie kierunkowych typów kanałów dla większego bezpieczeństwa
  • Zamykanie kanału zadań w celu zakończenia pracy workerów
  • Gromadzenie wyników w celu synchronizacji zakończenia pracy
  • Dopasowanie rozmiaru puli do rodzaju obciążenia (CPU lub IO)

Często zadawane pytania

Czy lekcja „Wzorzec puli workerów” jest bezpłatna?

Tak — pełny tekst „Wzorzec puli workerów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorzec puli workerów”?

Ograniczaj współbieżność Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Go Academy?

Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Wzorzec puli workerów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?

Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wzorzec puli workerów
  2. Fan-Out i Fan-In
  3. Etapy potoku
  4. Kontrolowane zamykanie
← Powrót do Go Academy