golang 中如何通过一个 http 请求触发一个长时间运行的函数?

2019-08-30 10:58:54 +08:00
 blackcurrant

这里的 doSomething 可能会因为 http 超时或者各种原因中断,如何让 longTimeTask() 持续运行下去呢?

func doSomething(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, "start!\n")
    longTimeTask()
}

func longTimeTask() {
    ...
}

func main() {
    http.HandleFunc("/do", doSomething)
    err := http.ListenAndServe(":12345", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
3370 次点击
所在节点    Go 编程语言
12 条回复
Trim21
2019-08-30 11:01:39 +08:00
新开一个 goroutine ?
blackcurrant
2019-08-30 11:05:30 +08:00
@Trim21 你是说这样?
func doSomething(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "start!\n")
go longTimeTask()
}

当 doSomething 退出,函数里面的 goroutine 也退出了。
lbp0200
2019-08-30 11:39:20 +08:00
func longTimeTask() {
go func() {
tick := time.Tick(time.Second)
for range tick {
log.Println("fucker")
}
}()
}

结果:
curl 127.0.0.1:12345/do [11:37:17]
start!

2019/08/30 11:37:21 fucker
2019/08/30 11:37:22 fucker
2019/08/30 11:37:23 fucker
2019/08/30 11:37:24 fucker
2019/08/30 11:37:25 fucker
2019/08/30 11:37:26 fucker
2019/08/30 11:37:27 fucker
2019/08/30 11:37:28 fucker
2019/08/30 11:37:29 fucker
2019/08/30 11:37:30 fucker
2019/08/30 11:37:31 fucker
2019/08/30 11:37:32 fucker
……
fuxiaohei
2019-08-30 11:57:55 +08:00
@blackcurrant 你最好试一下再说
wkzq
2019-08-30 12:30:19 +08:00
建议用 channel 触发 goroutine, 这样子可以通过调节 sigChan 的 size 来控制 goroutine 的数量

func doSomething(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "start!\n")
sigChan <- 1
}

func goroutine() {
for {
select {
case _ = <- sigChan:
go longTimeTask()
}
}
}

func longTimeTask() {
...
}
blackcurrant
2019-08-30 12:31:08 +08:00
@lbp0200
@fuxiaohei
真的可以!看来自己对 goroutine 理解不够。
zzlettle
2019-08-30 13:21:58 +08:00
意思是函数退出了
协程依然在运行
看来我也对 GO 协程理解不到位
buried
2019-08-30 13:28:53 +08:00
三楼的回答有声音怎么回事
zzlettle
2019-08-30 13:31:06 +08:00
这个也解开了我以前的一个提问
当时用时时间定时器
很奇怪,函数推出
然后还显示了协程里面的内容
现在知道了,原来是时间定时器那个协程还能在运行的原因
labulaka521
2019-08-30 13:37:00 +08:00
@blackcurrant 不会的 建议看下 go 的调度
fishofcat
2019-08-30 13:37:46 +08:00
@blackcurrant 你最好试试再说
vtz668
2019-10-14 20:26:37 +08:00
我之前写了一个求素数的,当值特别大时,运行时间要好久,10 几秒把,后来我用 grpc 调用,无论这个值多大,运行一二十秒,结果也会顺利得到,后来我用 http 调用,刚开始我以为我是用微服务 micro 做得,api 负责处理 http 请求,然后再调用 grpc 调用方法求素数,这时候如果超时 5 秒,就会报错,但是 grpc 调用的代码依旧在运行,后来我就搜索英文和中文,因为我不知道是 micro 框架限定超时时间还是注册服务 consul,但是没收到,后来我无意中在那里看到有人回复说,是 http 里面 ctx 会默认 timeout 时间为 5 秒,所以应该是这个问题,因为就算开启一个协程,http 在 5 秒内没有得到结果,也会返回

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/596460

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX