Go 如果RabbitMQConsumer没有收到响应,如何超时
我得到了使用RabbitMQ队列中消息的代码。如果它在一段时间内没有收到消息,它应该会失败Go 如果RabbitMQConsumer没有收到响应,如何超时,go,rabbitmq,timeout,channel,Go,Rabbitmq,Timeout,Channel,我得到了使用RabbitMQ队列中消息的代码。如果它在一段时间内没有收到消息,它应该会失败 msgs, err := ch.Consume( c.ResponseQueue, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-lo
msgs, err := ch.Consume(
c.ResponseQueue, // queue
"", // consumer
false, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
failOnError(err, "Failed to register a consumer")
...
loop:
for timeout := time.After(time.Second); ; {
select {
case <-timeout:
log.Printf("Failed to receive response for action %+v\n Payload: %+v\nError: %+v\n", action, body, err)
return errors.New("Failed to receive response for action")
default:
for d := range msgs {
if corrID == d.CorrelationId {
err = json.Unmarshal([]byte(uncompress(d.Body)), &v)
if err != nil {
return err
}
ch.Ack(d.DeliveryTag, false)
break loop
}
}
}
}
msgs,错误:=ch.Consume(
c、 ResponseQueue,//队列
“”,//消费者
false,//自动确认
false,//独占
false,//没有本地
false,//没有等待
nil,//args
)
FailOneError(错误,“未能注册消费者”)
...
循环:
对于超时:=time.After(time.Second);{
挑选{
案例您的循环有一个选择
,有两个案例:超时和默认
分支。进入循环后,超时不会触发,因此执行默认
分支
default
分支在msgs
通道上包含一个for range
,该通道一直从该通道接收数据,直到关闭为止(并且从该通道接收到所有值)。通常不应发生这种情况,因此不会重新查看超时情况(仅当发生错误且msgs
关闭时)
相反,在循环内部使用选择
,有两种情况,一种是超时,另一种是仅从msgs
接收一个值。如果收到消息,请重新启动超时。对于可重新启动的计时器,请使用
试一试这个
最后一点注意:如果在超时发生之前中断循环,后台计时器不会立即释放(仅在超时发生时)。如果您经常需要此操作,可以使用获取和取消函数,您可以在返回前立即调用该函数以释放计时器资源(最好延期)
这就是它的样子:
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
for {
select {
case <-ctx.Done():
fmt.Println("timeout, returning")
return
case msg := <-msgs:
fmt.Println("received message:", msg, time.Now())
}
}
ctx,cancel:=context.WithTimeout(context.Background(),time.Second)
推迟取消
为了{
挑选{
案例更改选择为:
c1 := make(chan error, 1)
go func() {
for d := range msgs {
if corrID == d.CorrelationId {
err = json.Unmarshal([]byte(uncompress(d.Body)), &v)
if err != nil {
c1 <- err
}
ch.Ack(d.DeliveryTag, false)
c1 <- nil
}
}
}()
select {
case <-time.After(defaultTimeout * time.Second):
log.Printf("Failed to receive response for action %+v\n Payload: %+v\nError: %+v\n", action, body, err)
return errors.New("Failed to receive response in time for action")
case err := <-c1:
failOnError(err, "Failed to process response")
}
return err
c1 := make(chan error, 1)
go func() {
for d := range msgs {
if corrID == d.CorrelationId {
err = json.Unmarshal([]byte(uncompress(d.Body)), &v)
if err != nil {
c1 <- err
}
ch.Ack(d.DeliveryTag, false)
c1 <- nil
}
}
}()
select {
case <-time.After(defaultTimeout * time.Second):
log.Printf("Failed to receive response for action %+v\n Payload: %+v\nError: %+v\n", action, body, err)
return errors.New("Failed to receive response in time for action")
case err := <-c1:
failOnError(err, "Failed to process response")
}
return err
c1:=make(chan错误,1)
go func(){
对于d:=范围msgs{
如果corrID==d.CorrelationId{
err=json.Unmarshal([]字节(解压缩(d.Body)),&v)
如果错误!=零{
c1在java中是ConnectionFactory上的属性?因此您不必在代码中处理该条件。谢谢,但我不需要超时刷新,以防收到消息。尝试将您的更改应用于我的现有代码,这很有帮助(更新的问题)。Thx!@Qworel如果您不需要重置,请注释掉重置代码:)但是,您可以使用time.After()
毕竟:)这对我来说显然是错误的。如果此代码的两个实例运行,MSG将不同步,一些工作进程将丢失其关联id。值仅从MSG中弹出一次。@mh cbon在我们的实现中,每个工作进程有一个队列,因此这不是问题
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
for {
select {
case <-ctx.Done():
fmt.Println("timeout, returning")
return
case msg := <-msgs:
fmt.Println("received message:", msg, time.Now())
}
}
c1 := make(chan error, 1)
go func() {
for d := range msgs {
if corrID == d.CorrelationId {
err = json.Unmarshal([]byte(uncompress(d.Body)), &v)
if err != nil {
c1 <- err
}
ch.Ack(d.DeliveryTag, false)
c1 <- nil
}
}
}()
select {
case <-time.After(defaultTimeout * time.Second):
log.Printf("Failed to receive response for action %+v\n Payload: %+v\nError: %+v\n", action, body, err)
return errors.New("Failed to receive response in time for action")
case err := <-c1:
failOnError(err, "Failed to process response")
}
return err