Go 如果RabbitMQConsumer没有收到响应,如何超时

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

我得到了使用RabbitMQ队列中消息的代码。如果它在一段时间内没有收到消息,它应该会失败

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