如何实现goroutine执行好请求

问题描述 投票:-2回答:1

我刚开始使用golang,出于性能考虑,我需要修改一些方法。

我有下一个方法

func (fs *ServiceImpl) GetContext(Item *models.Item, CallerID *int64, txn newrelic.Transaction) (models.Context, error) {
    var context models.Context

    //Resource1
    item := Item
    resource1, err := getResource1(fs, Item, txn)

    if err != nil {
        logger.Error("error", err)
    }

    context.Item = item
    context.Resource1 = resource1

    //Resource2
    resource2, err := getResource2(fs, Item, CallerID, txn)

    if err != nil {
        logger.Error("error", err)
    }

    context.Resource2 = resource2

    //Resource3
    resource3, err := getResource3(fs, Item, txn)

    if err != nil {
        logger.Error("error", err)
    }

    context.Resource3 = resource3

    return context, err
}

然后我有:

func getResource1(fs *ServiceImpl, Item *models.Item, txn Transaction) (*models.Resource1, error) {
    r1 := models.Resource1{}

    c1, err := fs.C1Provider.GetC1(Item.C1ID, txn)

    if err == nil {
        c1.C1s = &c1.PathFromRoot
    } else {
        logger.Errorf("error", err)
    }

    u1, err := fs.U1Provider.GetU1(Item.U1ID, txn)

    if err == nil {
        r1.StoreType = &u1.U1Type
        r1.ReputationLevel = &u1.Reputation.LevelID
    } else {
        logger.Errorf("error", err)
    }

    return &r1, err
}
func getResource2(fs *ServiceImpl, Item *models.Item, CallerID *int64, txn Transaction) ([]models.Resource2, error) {
    var r2 []models.Resource2

    ri2, err := getAux1R1(fs, Item, CallerID, txn)
    r2 = append(experiments, *ri2)

    return r2, err
}

func getAux1R2(fs *ServiceImpl, Item *models.Item, CallerID *int64, txn Transaction) (*models.Resource2, error) {
    if CallerID == nil {
        return &models.Resource2{Name: "XXX", Variant: "DEFAULT"}, nil
    }

    seed := strconv.FormatInt(*CallerID, 10)
    param := models.Resource2RequestParam{
        Resource2Name: "XXX",
        Seed:           seed
    }

    r2, err := getAux2R2(fs, param, txn)

    return r2, err
}

func getAux2R2(fs *ServiceImpl, param models.Resource2RequestParam, txn Transaction) (*models.Resource2, error) {
    exp, err := fs.Resource2Service.GetResource2Configuration(param.Resource2Name, param.Seed)

    r2 := &models.Resource2{
        Name:    exp.Resource2Name(),
        Variant: exp.VariantID(),
    }

    return r2, err
}

最后是:

func getResource3(fs *ServiceImpl, Item *models.Item, txn Transaction) (*models.Resource3, error) {
    var r3 *models.Resource3

    if !utils.Contains(text.ENABLE_XXX, Item.SiID) {
        return r3, nil
    }

    pay, err := getAux1R3(fs, Item, txn)

    if err == nil {
        switch Item.SiID {
        case text.P_X:
            r3 = pay.SetForX()
        case text.P_Y:
            r3 = pay.SetForY()
        case text.P_Z:
            r3 = pay.SetForZ()
        }
    }

    return r3, err
}

func getAux1R3(fs *ServiceImpl, Item *models.Item, txn Transaction) (*models.Resource3, error) {
    result, err := fs.P1Provider.GetP1Options(Item.ID, txn)

    if err != nil {
        logger.Errorf("error", err)

        return nil, err
    }

    return result, nil
}

这些方法都是api调用,需要大量的时间。

c1, err := fs.C1Provider.GetC1(Item.C1ID, txn)
exp, err := fs.Resource2Service.GetResource2Configuration(param.Resource2Name, param.Seed)
result, err := fs.P1Provider.GetP1Options(Item.ID, txn)

我不在乎调用的顺序,但GetContext方法必须在最后完成。

我必须如何实现goroutines与通道,以执行好这些调用?

先谢谢你

go goroutine channels
1个回答
0
投票

在不了解你的应用的情况下,不可能说并行是否会有效。如果你认为会有效,你可以做这样的事情。

var g errgroup.Group

g.Go(func() error {
    r, err := getResourceA(...)
    if err == nil {
        context.ResourceA = r
    }
    return err
})

... get more resources ...

g.Go(func() error {
    r, err := getResourceZ(...)
    if err == nil {
       context.ResourceZ = r
    }
    return err
})

return context, g.Wait()

这使用了 群体,它是一个方便的工具,用于等待返回错误的函数组。

如果这些资源获取器实现了一个通用的接口,并且能够支持 context.Context.

© www.soinside.com 2019 - 2024. All rights reserved.