時間制限後のゴルーチンのキャンセル
負荷テストのシナリオでは、ゴルーチンの実行時間を制御することが重要です。これを達成するための効果的なアプローチを次に示します。
Goroutines で HTTP リクエストを管理する次のコード スニペットを考えてみましょう:
func attack(cfg AttackConfig) { // some code ... var ar attackResponse ch := make(chan uint8, 8) go func() { time.Sleep(cfg.Duration * time.Second) ch <- CALL_TIME_RAN_OUT }() for { if atomic.LoadInt32(&currConnections) < atomic.LoadInt32(&maxConnections) - 1 { go httpPost(cfg, &ar, ch) } switch <-ch { // some other cases ... case CALL_TIME_RAN_OUT: fmt.Printf("%d seconds have elapsed. Shutting down!", cfg.Duration) return } } }
ただし、httpPost() の Goroutines は、指定された cfg.Duration の後も実行され続けます。
この問題に対処するには、Go のコンテキスト パッケージを利用できます。 context.Context オブジェクトをゴルーチンに渡すことで、指定したタイムアウトに達したときにそれらのゴルーチンをキャンセルできます。
コンテキスト パッケージを使用したコードの改訂版は次のとおりです。
import ( "context" "fmt" "golang.org/x/net/context" "time" ) func attack(cfg AttackConfig) { // some code ... var ar attackResponse // Define a timeout context ctx, cancel := context.WithTimeout(context.Background(), cfg.Duration*time.Second) defer cancel() go func() { time.Sleep(cfg.Duration * time.Second) cancel() }() for { if atomic.LoadInt32(&currConnections) < atomic.LoadInt32(&maxConnections) - 1 { go httpPost(ctx, cfg, &ar) } select { // some other cases ... case <-ctx.Done(): fmt.Printf("%d seconds have elapsed. Shutting down!", cfg.Duration) return } } } func httpPost(ctx context.Context, cfg AttackConfig, a *attackResponse) { // some code here to create HTTP client ... for { // some code to make HTTP call ... select { case <-ctx.Done(): return default: } } }
この変更により、指定された cfg.Duration の有効期限が切れると、ctx.Done() チャネルが閉じられ、httpPost() のキャンセルが通知されます。その後返されるゴルーチン。
以上がGo で指定された時間制限の後にゴルーチンを正常にキャンセルするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。