我正在处理一个 http 端点,它将接收来自客户端的请求并阻塞,直到它从另一台服务器收到该请求的“确认”或直到它通过超时。我的代码和服务器之间的通信未包含在此示例中,但您可以假设对于每个请求,最终可能会收到一个 ack。
由于许多请求将在短时间内通过我的模块,我不能假设给定的 ack 与我阻止的请求相关。编辑:在这里澄清,因为它引起了一些混乱。控制器从外部来源接收请求和确认。这就是我异步处理它们的原因。/EDIT出于这个原因,如果它们不相关,我的代码会将 acks 放回通道。同样重要的是要注意 http.ListenAndServe 异步调用我的函数。
如果请求在超时内被确认,则没有问题。但是,如果 ack 在超时过后出现,它将被添加到通道中并且永远不会被删除。这将导致通道被填满。我害怕使用“取消”通道,因为也有可能不会收到给定请求的 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
}
注意:要对此进行测试,请在本地计算机上运行它。Curl/Wget127.0.0.1:8888/start/bob然后是 Curl/Wget 127.0.0.1:8888/ack/bob。您可以用任何字符串替换 bob 以查看行为。
我是 Go 的新手。请随时在评论中提供其他反馈。
ITMISS
桃花长相依
相关分类