google-app-engine - 使用 Golang channel 处理 HTTP 请求

标签 google-app-engine concurrency go

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

本质上,我需要一个同步队列,一次只处理一个请求, channel 看起来很自然。

Is it possible to use Go's buffered channel as a thread-safe queue?

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

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

谢谢!

// 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) 让第一个例程等待。

这停止了为什么你试图将它放入一个线程背后的整个推理(因此我认为你遇到了设计问题)。

这里有一些未经测试的代码应该可以工作或者至少有助于正确的方向。

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

关于google-app-engine - 使用 Golang channel 处理 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25721084/

相关文章:

go - sqlx - 具有 >1 列的非结构 dest 类型结构 (2)

go - Beego POST方法始终寻找模板文件

当 url 包含尾部斜杠时 CSS 不加载

google-app-engine - 如何解决 "no matching index found."错误

android - 使用游标从 android 中的谷歌应用引擎查询

generics - 在 Go 中实现通用映射器的惯用方法

python - 当我的用户使用 gae-simpleauth 登录时,如何从 Google 帐户检索电子邮件地址并将其存储在我的应用程序的用户个人资料中?

objective-c - performSelectorOnMainThread 的 block 版本 :withObject:waitUntilDone:

java - 用 Java 实现 Peterson 锁

java - 在池中的 Akka actor 实例之间共享可变数据