英文:
How to cancel goroutines after certain amount of time
问题
我正在制作一个负载测试工具,它在goroutine中进行多个HTTP调用,目前它可以正常工作,但现在我想让它只运行指定的持续时间。
当sleep完成后,我该如何取消goroutine?
我目前尝试的方法是创建一个goroutine,在指定的持续时间内执行time.Sleep()
,当时间到达后,它会向通道发送一条消息。
在我的无限循环中,我使用switch语句监听该消息,当消息到达时,我返回。这正是我想要的效果。
问题是,来自go httpPost()
行的goroutine将继续进行HTTP调用。我甚至尝试将通道传递给该函数,并在那里监听相同的CALL_TIME_RAN_OUT
消息,但由于某种原因,当我这样做时,goroutine只运行一次,然后立即返回,而不是等待Sleep
结束时广播的消息。
有人知道我可以采取更好的方法吗?这种方法似乎不起作用。
以下是代码(已删除不相关的部分):
func attack(cfg AttackConfig) {
// 一些代码...
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 {
// 其他一些case...
case CALL_TIME_RAN_OUT:
fmt.Printf("%d seconds have elapsed. Shutting down!", cfg.Duration)
return
}
}
}
func httpPost(cfg AttackConfig, a *attackResponse, ch chan uint8) {
// 一些创建HTTP客户端的代码...
for {
// 一些进行HTTP调用的代码...
switch <-ch {
case CALL_TIME_RAN_OUT:
return
}
}
}
希望对你有所帮助!
英文:
I am making a load testing tool that makes multiple HTTP calls in goroutines, and it works, but now I am trying to allow it to run for only a specified duration.
How can I cancel the goroutines when the sleep has finished?
What I am currently attempting to do is to make a goroutine that does time.Sleep()
for the specified duration, and when that is finished it will broadcast a message to the channel.
In my infinite loop, I listen for the message in the switch statement, and when it is there I return. This works just as I want it to.
The problem is, the goroutines from the go httpPost()
line will continue making HTTP calls. I even attempt to pass the channel into that function and listen for the same CALL_TIME_RAN_OUT
message there as well, but for whatever reason when I do that the goroutines only run once and then immediately return, as opposed to waiting for the message to be broadcasted by the end of the Sleep
.
Does anyone know a better approach I can take? This doesn't seem to be working.
Here's the code (removed irrelevant parts):
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
}
}
}
func httpPost(cfg AttackConfig, a *attackResponse, ch chan uint8) {
// some code here to create HTTP client ...
for {
// some code to make HTTP call ...
switch <-ch {
case CALL_TIME_RAN_OUT:
return
}
}
}
答案1
得分: 2
使用golang.org/x/net/context
包。Go 1.7将golang.org/x/net/context
包移入标准库,命名为context
。
所以如果你使用1.7+版本,只需导入context
。
使用方法很简单:
package main
import (
"context"
"fmt"
"time"
)
func test(ctx context.Context) {
t := time.Now()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
}
fmt.Println("used:", time.Since(t))
}
func main() {
ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
test(ctx)
}
英文:
use package golang.org/x/net/context
. Go 1.7 moves the golang.org/x/net/context
package into the standard library as context
.
So just import context
if you use version 1.7+.
the usage is straightforward:
package main
import (
"context"
"fmt"
"time"
)
func test(ctx context.Context) {
t := time.Now()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
}
fmt.Println("used:", time.Since(t))
}
func main() {
ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
test(ctx)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论