如何在Go编程语言中处理并行的HTTP请求?

10

我正在使用 Go HTTP 包进行编程,希望像 Java 一样并发处理请求。但是我无法实现。

我创建了一个简单的 Web 服务器,在其中加入了一个 sleep(暂停)的函数。结果我意识到 Go 只能逐个处理请求。也就是说,如果在浏览器中刷新页面,第一个请求必须完成处理后,才能开始处理第二个请求。以下是代码:

func main(){

    //Process the http commands
    fmt.Printf("Starting http Server ... ")
    http.Handle("/", http.HandlerFunc(sayHello))
    err := http.ListenAndServe("0.0.0.0:8080", nil)
    if err != nil {
        fmt.Printf("ListenAndServe Error",err)
    }
}

func sayHello(c http.ResponseWriter, req *http.Request) {
    fmt.Printf("New Request\n")
    processRequest(c, req)
}

func processRequest(w http.ResponseWriter, req *http.Request){
    time.Sleep(time.Second*3)
    w.Write([]byte("Go Say’s Hello(Via http)"))
    fmt.Println("End")
}

我想同时处理两个请求,所以在 "sayHello" 函数中的 "processRequest(c, req)" 前添加了 "go" 命令,以便在不同的 goroutine 中处理每个请求。但是……它没有起作用……我不知道为什么。我知道两个请求都已被处理,因为我在控制台上看到了打印的行,但浏览器仍在等待信息……而且没有显示我的响应。

所以……我的问题是:

每个请求是否会创建一个新的 http.ResponseWriter?还是使用相同的? 您知道如何指示 web 服务器使用不同线程处理每个请求吗?

欢迎任何帮助……

Fersca

3个回答

22

所有连接都会自动并发处理。每个 TCP 连接(不是请求)都有其自己的 goroutine。

在使用 HTTP 管道和重用连接的浏览器中,这种方式可能并不总是有效。很可能您的浏览器正在重用连接,而该连接会一直阻塞,直到当前被 goroutine 处理的请求完成。


谢谢。今天因为浏览器过于智能的行为浪费了太多时间 :) - OZ_

0

我认为你的浏览器一直在等待,因为你没有向它发送响应。 你的浏览器发出了一个请求来调用sayHello函数,而sayHello函数又发出了一个请求来处理processRequest函数。 从你的代码中,processRequest函数已经向sayHello函数发送了一个响应,但是sayHello函数没有向浏览器发送响应。

你可以使用http.Get或http.Post来调用processRequest函数。


0

如果你希望运行时支持能够利用多个操作系统线程,你可以通过以下方式设置该数量:

 runtime.GOMAXPROCS(n)

或者设置GOMAXPROCS环境变量。

要获取可用核心的数量,请使用

 runtime.NumCPU()

所以你经常会得到

 runtime.GOMAXPROCS(runtime.NumCPU())

这并没有帮助。Go语言默认是并发的,只不过不是多线程的(两者之间有很大的区别)。在阻塞调用(如time.Sleep().Write())时,它会切换到另一个goroutine。 - ayke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接