一尘不染

使用Golang通道处理HTTP请求

go

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

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

是否可以将Go的缓冲通道用作线程安全队列?

但是,我无法让我简单的hello world示例起作用。似乎在’goprocess(w,cr)’行上失败了;我从服务器收到200响应,但没有竞争。如果我在此行中消除了“ go”,则效果很好,但是我猜我没有正确调用该通道。

有人指出我要去哪里了吗?

谢谢!

// 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)
}

阅读 457

收藏
2020-07-02

共1个答案

一尘不染

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

要停止此操作,您可以使用等待组(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)
}
2020-07-02