通过选择去缓冲通道

时间:2017-05-17 09:28:05

标签: go channels

我有2个缓冲通道为入站请求提供服务:

rabbitQ = make(chan map[string]interface{}, 1000)
sqsQ = make (chan map[string]interface{}, 1000)

我的调度程序功能如下所示:

func dispatchMessage(params map[string]interface{}) {

    if !shouldFailoverToSQS {
        select {
        case rabbitQ <- params:
            sentToRabbitMQ++
        case sqsQ <- params:
            sentToSQS++
        default:
            log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
        }
    } else {
        sqsQ <- params
    }

}

我希望消息总能发送到rabbitQ,除非缓冲区有容量,但我发现呼叫正在通过并且大约一半时间向sqsQ发送消息。这不是我想要的 - 如果rabbitQ已满,我只想发送到sqsQ。

我该如何强制执行此操作?

3 个答案:

答案 0 :(得分:1)

Per Voker的评论,这就是我想出的:

func dispatchMessage(params map[string]interface{}) {

    //log.Debugf("Failover: %t, Len: %d", shouldFailoverToSQS, len(rabbitQ))

    if !shouldFailoverToSQS {
        select {
        case rabbitQ <- params:
            sentToRabbitMQ++
        default:
            select {
            case sqsQ <- params:
                sentToSQS++
            default:
                log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
            }
        }
    } else {
        select {
        case sqsQ <- params:
            sentToSQS++
        default:
            log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
        }
    }

}

答案 1 :(得分:0)

对于一个简洁的答案(看起来你已经从你的答案+线程评论中得到它),你的选择将随机选择。根据文档:

  

如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,&#34;选择&#34;语句阻塞,直到至少有一个通信可以继续。

此外,我想我会为你提供一个根本没有使用选择的答案。使用len,您可以确定在通道中排队的值的数量。当然,它与你现在所做的没什么不同,但我想我会提供不同的东西:

const MaxChan = 1000
func dispatchMessage(params map[string]interface{}) {
    if !shouldFailoverToSQS {
        if len(rabbitQ) < MaxChan {
            sentToRabbitMQ++
        } else if len(sqsQ) < MaxChan {
            sentToSQS++
        } else {
            log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
        }
    } else {
        if len(sqsQ) < MaxChan {
            sentToRabbitMQ++
        } else if len(rabbitQ) < MaxChan {
            sentToSQS++
        } else {
            log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
        }
    }
}

支持文档: https://golang.org/ref/spec#Select_statements

答案 2 :(得分:0)

func dispatchMessage(params map[string]interface{}) {

    if !shouldFailoverToSQS {
        select {
        case rabbitQ <- params:
            sentToRabbitMQ++
        case <-time.After(time.Millisecond * 10.0): // rabbit is blocked and 10 milli sec passed.
            select {
            case sqsQ <- params:
                sentToSQS++  
            default:
            log.Error("Failed to dispatch mesaage to either RabbitMQ or SQS")
            }
        }
    } else {
        sqsQ <- params
    }

}