Throttling v Go

Publikováno 09-19-2017 06:07:45

Throttling je způsob, jak omezit počet běžících vláken. Pokud chceme, abychom nezahltili druhý systém (subsystém) nekontrolovaným množství paralelních volání, potřebujeme způsob, jak omezit počet běžících go rutin.

Určitě je mnoho způsobů, jak toho docílit, nabízím zde jeden, který se mi osvědčil.

V zásadě vycházím z toho, že zápis do kanálu blokuje, pokud je překrečena kapacita bufferu kanálu.

Tedy

ch := make(chan int, 1)
ch <- 1 // OK
ch <- 2 // blokuje, dokuď někdo kanál nepřečte

Tento konkrétní příklad vám neprojde, samotné Go detekuje deadlock (zápis bez čtení v jediné go rutině) a radši program zabije.

Jak se to dá využít pro throttling programu? Tak, že si uděláte kanál s bufferem o velikosti maximálního počtu paralelních zpracování a při vstupu do kritické části do kanálu zapíšete. Naopak při výstupu z kanálu přečtete (nejlépe přes defer). Ukázka:

func throttler() {
	ch := make(chan int, 2) // nastavíme kapacitu na 2
	defer close(ch)         // good practice - zavřeme kanál před opuštění funkce

	for i := 1; i <= 10; i++ {
		ch <- 0 // zápis blokuje, pokud překračuje kapacitu kanálu
		go func(i int) {
			defer func() { <-ch }() // na závěr přečteme data z kanálu, tím ho odblokujeme
			fmt.Printf("provádím %d\n", i)
		}(i)
	}
}
comments powered by Disqus