Http Golang将无法读取的项目清理出通道
我正在处理一个http端点,该端点将接收来自客户端的请求并阻塞,直到它从另一个服务器接收到该请求的“ack”或直到它通过超时。我的代码和服务器之间的通信不包括在这个示例中,但是您可以假设对于每个请求,最终可能会收到一个ack 由于许多请求将在短时间内通过我的模块,我不能假设给定的ack与我阻塞的请求相关编辑:此处有澄清,因为它引起了一些混乱。控制器从外部源接收请求和确认。这就是为什么我不同步地处理它们/EDIT因此,如果ACK不相关,我的代码会将它们放回频道。还需要注意的是,http.ListenAndServe异步调用我的函数 如果请求在超时时间内得到确认,则没有问题。但是,如果ack在超时后出现,它将被添加到通道中,并且永远不会被删除。这将导致通道填满。我害怕使用“取消”通道,因为对于给定的请求,也可能没有收到ack,从而导致取消通道也被填满 问题:如何防止延迟确认填满我的频道?/如何识别和删除延迟确认 代码如下。没有play.golang.org链接,因为http.listendserve:/Http Golang将无法读取的项目清理出通道,http,asynchronous,go,Http,Asynchronous,Go,我正在处理一个http端点,该端点将接收来自客户端的请求并阻塞,直到它从另一个服务器接收到该请求的“ack”或直到它通过超时。我的代码和服务器之间的通信不包括在这个示例中,但是您可以假设对于每个请求,最终可能会收到一个ack 由于许多请求将在短时间内通过我的模块,我不能假设给定的ack与我阻塞的请求相关编辑:此处有澄清,因为它引起了一些混乱。控制器从外部源接收请求和确认。这就是为什么我不同步地处理它们/EDIT因此,如果ACK不相关,我的代码会将它们放回频道。还需要注意的是,http.Liste
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)
}
主程序包
进口(
“fmt”
“net/http”
“时间”
)
常数超时=10
func startEndpoint(w http.ResponseWriter,r*http.Request){
var ack字符串
计时器:=time.NewTimer(time.Second*超时)
延迟计时器。停止()
m:=r.RequestURI[len(“/start/”):]
格式打印(m)
回收:
为了{
挑选{
case ack=保留一个“uuids in process”的map
;当您收到/start/
时,将其添加到map,当您收到ack
(或当请求超时)时,将其删除。如果您收到的ack不在map中,则立即放弃它
请小心,因为映射在默认情况下不是线程安全的。看起来您可能正在尝试使用Akka的异步样式编写Go。这是一个艰难的选择;惯用Go应该更容易。缺陷在于:“我不能假设给定的ack与我阻塞的请求相关”
相反,您需要通过简单的顺序步骤处理每个请求,并将ack直接发送回其客户端。为此,每个请求都需要自己的服务goroutine。如果您无法将ack与请求关联,则ack完全无用。否?在请求的同一通道上处理ack。使用令牌来标识e请求(生成一个uuid并将其传递)。ack将有一个与请求匹配的uuid(或者在本例中是一个名称字符串)。在“注意”中,我使用了“bob”作为将请求与ack匹配的名称字符串。问题是ack可能在请求超时后出现,或者根本不会出现。问题是我如何处理延迟/缺失的ack?这个答案解决了我思考中的根本问题:我在寻找一种跟踪哪些ack有效和无效的方法。更有效的方法是跟踪哪些请求是有效的,并使所有不相关的ACK无效。我感谢您的回答。我的问题的措辞似乎很糟糕。在这种情况下,有三个交互服务:发送请求的客户端、提供代码的控制器,以及一组向con发送ACK的外部服务器当工作完成时,troller。从控制器的角度来看,随机请求和ACK一直在到达,并且不一定按特定的顺序。因此,没有一种“顺序”方法来处理请求和ACK。我希望这能澄清这种情况。