From 3f419f93a827251a0639acd6b6636093ba135123 Mon Sep 17 00:00:00 2001 From: shawwang Date: Mon, 30 Mar 2020 17:21:40 +0800 Subject: [PATCH] auth: optimize lock scope for CheckPassword to improve authentication performance in concurrent scenarios when enable auth and using authentication based password --- auth/store.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/auth/store.go b/auth/store.go index 6ddeb86e8fb9..eb91514e0036 100644 --- a/auth/store.go +++ b/auth/store.go @@ -319,24 +319,34 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { return 0, ErrAuthNotEnabled } - tx := as.be.BatchTx() - tx.Lock() - defer tx.Unlock() + var user *authpb.User + // CompareHashAndPassword is very expensive, so we use closures + // to avoid putting it in the critical area of the tx lock. + revision, err := func() (uint64, error) { + tx := as.be.BatchTx() + tx.Lock() + defer tx.Unlock() + + user = getUser(as.lg, tx, username) + if user == nil { + return 0, ErrAuthFailed + } - user := getUser(as.lg, tx, username) - if user == nil { - return 0, ErrAuthFailed - } + if user.Options != nil && user.Options.NoPassword { + return 0, ErrAuthFailed + } - if user.Options != nil && user.Options.NoPassword { - 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) {