并行执行不同请求的正确方法

时间:2019-02-21 20:54:02

标签: go kubernetes

我知道有多种解决方案可以满足我的需求,但是我正在寻找一种/适当的方式来并行执行一些请求。我是Go的新手,但是我现在正在做的事情感觉很麻烦。

用例:

我需要并行查询4个不同的REST端点(kubernetes客户端请求)。一旦获得所有这4个结果,就需要进行一些处理。

我的问题:

我知道我需要为此使用go例程,但是收集结果的最佳方法是什么。我目前正在做的事情(请参见下面的代码示例)可能非常繁琐,但是我不确定我还能做些什么来改进代码。

代码:

此代码最容易理解,但我不想按顺序执行请求:

// Get node resource usage metrics
nodeMetricsList, err := c.kubernetesClient.NodeMetricses()
if err != nil {
    log.Warn("Failed to get node usage list from Kubernetes", err)
    return err
}

// Get pod resource usage metrics
podMetricsList, err := c.kubernetesClient.PodMetricses()
if err != nil {
    log.Warn("Failed to get pod usage list from Kubernetes", err)
    return err
}

这就是我并行运行请求的方式。这使得代码的可读性大大降低,实现起来也很麻烦:

var nodeMetricsList *v1beta1.NodeMetricsList
var nodeMetricsListError error
var podMetricsList *v1beta1.PodMetricsList
var podMetricsListError error

go func() {
    nodeMetricsList, nodeMetricsListError = c.kubernetesClient.NodeMetricses()
}()
if nodeMetricsListError != nil {
    log.Warn("Failed to get podList from Kubernetes", err)
    return err
}

// Get pod resource usage metrics
go func() {
    podMetricsList, podMetricsListError = c.kubernetesClient.PodMetricses()
}()
if podMetricsListError != nil {
    log.Warn("Failed to get pod usage list from Kubernetes", err)
    return err
}

在给定示例中并行执行请求的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

您的代码有2个竞争条件,可能永远不会正确报告错误。

您需要先等待goroutine完成,然后才能读取它们所操作的值,这可以通过sync.WaitGroup轻松完成,如下所示:

var nodeMetricsList *v1beta1.NodeMetricsList
var podMetricsList *v1beta1.PodMetricsList
var nodeMetricsListError, podMetricsListError error
var wg sync.WaitGroup

// Get node resource usage metrics
wg.Add(1)
go func() {
    defer wg.Done()
    nodeMetricsList, nodeMetricsListError = c.kubernetesClient.NodeMetricses()
}()

// Get pod resource usage metrics
wg.Add(1)
go func() {
    defer wg.Done()
    podMetricsList, podMetricsListError = c.kubernetesClient.PodMetricses()
}()

wg.Wait()
if nodeMetricsListError != nil {
    log.Warn("Failed to get podList from Kubernetes", err)
    return err
}
if podMetricsListError != nil {
    log.Warn("Failed to get pod usage list from Kubernetes", err)
    return err
}

fmt.Println("Hello, playground")