我以为我找到了一种简单的方法来立即返回http响应,然后在后台进行一些工作而不会阻塞.但是,这不起作用.
func MyHandler(w http.ResponseWriter, r *http.Request) {
//handle form values
go doSomeBackgroundWork() // this will take 2 or 3 seconds
w.WriteHeader(http.StatusOK)
}
Run Code Online (Sandbox Code Playgroud)
它第一次工作 - 立即返回响应并开始后台工作.但是,任何进一步的请求都会挂起,直到后台goroutine完成.有没有更好的方法来执行此操作,这不涉及设置消息队列和单独的后台进程.
Jer*_*all 10
将多路复用goroutine复制到由GOMAXPROCS环境设置确定的可用线程上.因此,如果将此值设置为1,则单个goroutine可以占用单个线程Go可用,直到它将控制权返回到Go运行时.很可能doSomeBackgroundWork一直在单个线程上占用,这阻止了http处理程序的调度.
有很多方法可以解决这个问题.
首先,作为使用goroutine时的一般规则,您应该设置GOMAXPROCS系统具有的CPU数量或更大的CPU数量.
其次,您可以通过执行以下任一操作来控制goroutine:
runtime.Gosched()ch <- foofoo := <-chselect { ... }mutex.Lock()mutex.Unlock()所有这些都将回退到Go运行时调度程序,为其他goroutine提供工作机会.
Edd*_*dez 10
我知道这个问题是4年前发布的,但是我希望有人可以找到这个问题。
这是一种方法
有一种叫做工作池的东西https://gobyexample.com/worker-pools使用go例程和通道
但是在以下代码中,我将其调整为处理程序。(为简单起见,我忽略了错误,而是将作业用作全局变量)
package main
import (
"fmt"
"net/http"
"time"
)
var jobs chan int
func worker(jobs <-chan int) {
fmt.Println("Register the worker")
for i := range jobs {
fmt.Println("worker processing job", i)
time.Sleep(time.Second * 5)
}
}
func handler(w http.ResponseWriter, r *http.Request) {
jobs <- 1
fmt.Fprintln(w, "hello world")
}
func main() {
jobs = make(chan int, 100)
go worker(jobs)
http.HandleFunc("/request", handler)
http.ListenAndServe(":9090", nil)
}
Run Code Online (Sandbox Code Playgroud)
说明:
主要()
工人()
handler()
很酷的事情是,您可以发送任意数量的请求,因为此方案仅包含1个工作程序。下一个请求将一直等到前一个请求完成。
太棒了!
| 归档时间: |
|
| 查看次数: |
3842 次 |
| 最近记录: |