首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Golang Pgx池动态配置

Golang Pgx池动态配置
EN

Stack Overflow用户
提问于 2021-03-12 08:27:38
回答 1查看 271关注 0票数 0

我有一个带有postgres的RDS实例,并且我通过IAM用户进行身份验证。密码是每15分钟刷新一次的令牌:

代码语言:javascript
复制
    authToken, err := rdsutils.BuildAuthToken(Endpoint, "mars-east-4", "iamuser", envCredentials)
    if err != nil {
        return "", err
    }

然而,我已经看到了连接池的问题,在令牌过期后抛出身份验证错误,并且我没有找到任何好的解决方法。

我的想法是创建一个函数池并将其注入到我的存储库中,该函数将返回一个GetPool对象pgxpool.Pool

代码语言:javascript
复制
func (p Pool) GetPool() (*pgxpool.Pool, error) {
    config, err := p.getConfig()
    if err != nil {
        return nil, err
    }

    pool, err := pgxpool.ConnectConfig(context.Background(), config)
    if err != nil {
        return nil, err
    }

    return pool, nil
}

getConfig将在内部调用BuildAuthToken,但仅每15分钟调用一次(伪代码):

代码语言:javascript
复制
if time > 15minutes {
  return BuildAuthToken()
}

因此,如果15分钟过去了,我将重新处理令牌,否则我将使用已有的令牌。这将是最终的解决方案

代码语言:javascript
复制
func (p Pool) GetPool() (*pgxpool.Pool, error) {
    // Pseudocode
    if p.time < 15minutes {
      return p.Pool, nil
    }

    config, err := p.getConfig()
    if err != nil {
        return nil, err
    }

    pool, err := pgxpool.ConnectConfig(context.Background(), config)
    if err != nil {
        return nil, err
    }

    p.Pool = pool
    p.time = time.Now()
    return pool, nil
}

那么这种方法是不是效率低下呢?有没有更好的方法?另外,由于我将在服务器中使用它,那么竞态条件如何?谢谢

EN

回答 1

Stack Overflow用户

发布于 2021-03-12 11:50:27

最近pgx为pgxpool.Pool引入了BeforeConnect钩子。

这是我目前的解决方案

代码语言:javascript
复制
func (p *Pool) getConfig() (*pgxpool.Config, error) {
    config, err := pgxpool.ParseConfig("")
    if err != nil {
        return nil, err
    }

    /**
    This will refresh the password if the connection is expired
    */
    config.BeforeConnect = func(ctx context.Context, config *pgx.ConnConfig) error {
        if p.isTokenExpired() {
            creds, err := p.getCredentials()
            if err != nil {
                return err
            }

            config.User = creds.user
            config.Password = creds.password
            config.Host = creds.host
            config.Database = creds.database
            config.Port = creds.port
            p.cachedCredentials = creds
            p.expire = time.Now()
        } else {
            config.User = p.cachedCredentials.user
            config.Password = p.cachedCredentials.password
            config.Host = p.cachedCredentials.host
            config.Database = p.cachedCredentials.database
            config.Port = p.cachedCredentials.port
        }

        return nil
    }

    return config, nil
}

如果轮询需要创建一个新的连接,它将调用第一个BeforeConnect钩子,getCredentials将从AWS IAM检索令牌,但只有在令牌接近到期时间(根据AWS为15分钟)时才会发生这种情况

PS:此功能尚未发布,但已合并到主版本中。要使用它,您必须获得最新的提交

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66592497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档