我有一个带有postgres的RDS实例,并且我通过IAM用户进行身份验证。密码是每15分钟刷新一次的令牌:
authToken, err := rdsutils.BuildAuthToken(Endpoint, "mars-east-4", "iamuser", envCredentials)
if err != nil {
return "", err
}然而,我已经看到了连接池的问题,在令牌过期后抛出身份验证错误,并且我没有找到任何好的解决方法。
我的想法是创建一个函数池并将其注入到我的存储库中,该函数将返回一个GetPool对象pgxpool.Pool
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分钟调用一次(伪代码):
if time > 15minutes {
return BuildAuthToken()
}因此,如果15分钟过去了,我将重新处理令牌,否则我将使用已有的令牌。这将是最终的解决方案
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
}那么这种方法是不是效率低下呢?有没有更好的方法?另外,由于我将在服务器中使用它,那么竞态条件如何?谢谢
发布于 2021-03-12 11:50:27
最近pgx为pgxpool.Pool引入了BeforeConnect钩子。
这是我目前的解决方案
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:此功能尚未发布,但已合并到主版本中。要使用它,您必须获得最新的提交
https://stackoverflow.com/questions/66592497
复制相似问题