使用 Golang 通道处理 HTTP 请求

2024-05-06

我正在尝试构建一个简单的 Golang/Appengine 应用程序,它使用通道来处理每个 http 请求。原因是我希望每个请求执行合理的大型内存计算,并且每个请求都以线程安全的方式执行(即来自并发请求的计算不会混合),这一点很重要。

本质上,我需要一个同步队列,它一次只能处理一个请求,并且通道看起来很自然。

是否可以使用Go的缓冲通道作为线程安全队列? https://stackoverflow.com/questions/10424144/is-it-possible-to-use-gos-buffered-channel-as-a-thread-safe-queue

但是我无法让我的简单的 hello world 示例正常工作。它似乎在“go process(w, cr)”行失败;我从服务器收到 200 响应,但没有内容。如果我从这一行中删除“go”,效果很好,但我猜我没有正确调用通道。

有人指出我哪里出错了吗?

Thanks!

// curl -X POST "http://localhost:8080/add" -d "{\"A\":1, \"B\":2}"

package hello

import (
    "encoding/json"
    "net/http"  
)

type MyStruct struct {
    A, B, Total int64
}

func (s *MyStruct) add() {
    s.Total = s.A + s.B
}

func process(w http.ResponseWriter, cr chan *http.Request) {
    r := <- cr
    var s MyStruct
    json.NewDecoder(r.Body).Decode(&s)
    s.add()
    json.NewEncoder(w).Encode(s)
}

func handler(w http.ResponseWriter, r *http.Request) {  
    cr := make(chan *http.Request, 1)
    cr <- r
    go process(w, cr) // doesn't work; no response :-(
    // process(w, cr) // works, but blank response :-(
}

func init() {
    http.HandleFunc("/add", handler)
}

不确定这是正确的设计,但我怀疑问题在于,在您启动第二个 go 例程的地方,第一个 go 例程将继续并完成写入连接等。

要停止这种情况,您可以使用 waitgroup 让第一个例程等待(http://golang.org/pkg/sync/#WaitGroup http://golang.org/pkg/sync/#WaitGroup).

这停止了​​您尝试将其放入线程中的整个推理(因此我认为您遇到了设计问题)。

这是一些未经测试的代码,应该可以工作或至少在正确的方向上有所帮助。

package main

import (
    "encoding/json"
    "net/http"
    "sync"  
)

type MyStruct struct {
    A, B, Total int64
}

func (s *MyStruct) add() {
    s.Total = s.A + s.B
}

func process(w http.ResponseWriter, cr chan *http.Request) {
    r := <- cr
    var s MyStruct
    json.NewDecoder(r.Body).Decode(&s)
    s.add()
    json.NewEncoder(w).Encode(s)
}

func handler(w http.ResponseWriter, r *http.Request) {  
    cr := make(chan *http.Request, 1)
    cr <- r
    var pleasewait sync.WaitGroup
    pleasewait.Add(1)

    go func() {
        defer pleasewait.Done()
        process(w, cr) // doesn't work; no response :-(
    }()
    // process(w, cr) // works, but blank response :-(

    pleasewait.Wait()
}

func main() {
    http.HandleFunc("/add", handler)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Golang 通道处理 HTTP 请求 的相关文章

随机推荐