Golang清除了无法读取的频道

时间:2015-01-19 21:13:19

标签: http asynchronous go

我正在开发一个http端点,该端点将接收来自客户端的请求并阻塞,直到它收到" ack"来自另一台服务器的请求或直到它超时。我的代码和服务器之间的通信不包含在此示例中,但您可以假设对于每个请求,最终可能会收到确认。

由于许多请求会在短时间内通过我的模块,因此我无法假设给定的ack与我阻止的请求相关。 编辑:此处澄清,因为它引起了一些混乱。控制器从外部源接收请求和确认。这就是我异步处理它们的原因。 / EDIT 因此,如果相关信息不对,我的代码会将其放回频道。同样重要的是要注意http.ListenAndServe异步调用我的函数。

如果请求在超时内被激活,则没有问题。但是,ack在超时过后,它将被添加到一个通道并且永远不会删除。这将导致频道填满。我害怕使用"取消"通道,因为也可能不会收到给定请求的确认,导致取消通道也被填充。

问题:我怎样才能阻止他们填写我的频道?/我如何识别并删除迟到的内容?

以下代码。没有play.golang.org链接,因为http.ListenAndServe:/

package main

import (
    "fmt"
    "net/http"
    "time"
)

const timeout = 10

func startEndpoint(w http.ResponseWriter, r *http.Request) {
    var ack string
    timer := time.NewTimer(time.Second * timeout)
    defer timer.Stop()

    m := r.RequestURI[len("/start/"):]
    fmt.Print(m)
AckRecycle:
    for {
        select {
        case ack = <-acks:
            if ack == m {
                //What we found was our own ack
                fmt.Print("+")
                w.Write([]byte("Ack received for " + ack))
                break AckRecycle
            } else {
                //What we found on the channel wasn't for us
                fmt.Print(".")
                time.Sleep(time.Millisecond * 100)
                acks <- ack
            }
        case <-timer.C:
            //We ran out of time waiting for our ack
            w.Write([]byte("Timeout waiting for " + m))
            break AckRecycle
        default:
            //Channel was empty
            fmt.Print("-")
            time.Sleep(time.Millisecond * 100)
        }
    }
    return
}

func ackEndpoint(w http.ResponseWriter, r *http.Request) {
    ack := r.RequestURI[len("/ack/"):]
    acks <- ack
    fmt.Print("Ack for " + ack)
    w.Write([]byte("Thanks!"))
    return
}

var acks = make(chan string, 10)

func main() {
    http.HandleFunc("/ack/", ackEndpoint)
    http.HandleFunc("/start/", startEndpoint)

    http.ListenAndServe("127.0.0.1:8888", nil)
}

注意:要对此进行测试,请在本地计算机上运行它。 Curl / Wget 127.0.0.1:8888/start/bob然后是Curl / Wget 127.0.0.1:8888/ack/bob。您可以用任何字符串替换bob以查看行为。

我是Go的新手。您可以在评论中提供其他反馈。

2 个答案:

答案 0 :(得分:1)

保持map“uuids正在进行中”;当您收到/start/时将其添加到地图中,并在收到ack时(或请求超时)将其删除。如果您收到不在地图中的确认,请立即将其丢弃。

请注意,因为默认情况下地图不是线程安全的。

答案 1 :(得分:0)

好像你可能试图用Akka的异步风格编写Go。这是一个艰难的选择;惯用Go应该更容易。缺陷在这里:&#34; 我无法假设给定的ack与我阻止的请求相关&#34;。

相反,您需要使用简单的顺序步骤处理每个请求,并将ack直接发送回其客户端。为此,每个请求都需要自己的服务goroutine。