auth: optimize lock scope for CheckPassword
to improve authentication performance in concurrent scenarios when enable auth and using authentication based password
@@ -319,11 +319,15 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) {
return 0, ErrAuthNotEnabled
}
+ var user *authpb.User
+ // CompareHashAndPassword is very expensive, so we use closures
+ // to avoid putting it in the critical section of the tx lock.
+ revision, err := func() (uint64, error) {
tx := as.be.BatchTx()
tx.Lock()
defer tx.Unlock()
- user := getUser(as.lg, tx, username)
+ user = getUser(as.lg, tx, username)
if user == nil {
return 0, ErrAuthFailed
}
@@ -332,11 +336,17 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) {
return 0, ErrAuthFailed
}
+ return getRevision(tx), nil
+ }()
+ if err != nil {
+ return 0, err
+ }
+
if bcrypt.CompareHashAndPassword(user.Password, []byte(password)) != nil {
as.lg.Info("invalid password", zap.String("user-name", username))
return 0, ErrAuthFailed
}
- return getRevision(tx), nil
+ return revision, nil
}
func (as *authStore) Recover(be backend.Backend) {
