spring cloud oauth2 中的併發問題

堅持是一種態度,優秀是一種習慣!


最近一直在倒騰oauth2,oauth2是一種開放授權的協議。具體的原理不在本篇文章敘述,如同學們有興趣,可以下次詳細介紹。本篇主要講述這兩天遇到的獲取token的併發問題。

出現的問題

廢話少說,上乾貨。oauth2的一個主要作用是獲取token(有四種方式),併發出現的現象是當有同一個client_id,secret併發訪問/oauth/token時報

Incorrect result size: expected 1, actual 2 using jdbctokenstore錯誤。通過debug發現是oauth中的DefaultTokenService中的createAccessToken方法拋出來的異常


spring cloud oauth2 中的併發問題


上圖中的函數跟進去,發現在獲取token之前首先會根據client_id去數據庫中查詢是否token,當數據庫中有>1條記錄的時候,拋異常。

此時,數據庫中卻出現了2條記錄,why???

原因

createAccessToken方法的大概的邏輯是先刪除後插入,數據庫中有2條記錄,有時候會更多,懷疑是createAccessToken沒有做併發控制,當多個線程同時進入createAccessToken方法時會出現多條記錄的現象。於是寫了個腳本驗證自己的推斷:


spring cloud oauth2 中的併發問題


結果發現,如果同時啟動10個線程,同一個client_id會出現10天記錄(有時候低於10,純屬看運氣),驗證了我的推斷。

解決方案:

問題根源找到了,就得想辦法解決。在spring-security-oauth git的issue上發現有好幾個人也遇到同樣的問題,具體產生多條記錄的,有個老外總結如下:


spring cloud oauth2 中的併發問題


看不懂英文的,可以去Google翻譯,但是作為一個程序猿,還是要有閱讀技術類文檔的能力。

按照老外的說法是,oauth2目前只支持單線程,認為現實的應用場景也只有單線程用戶,wtf!!!殊不知還有腳本這玩意。

目前總體的解決方案有如下2種:

1、繼承DefaultTokenService 在createAccessToken方法加上sychronized關鍵字。但是這種方案有個弊端在於,oauth服務器如果是分佈式部署還是會出現併發問題

2、繼承DefaultTokenService 將createAccessToken事務級別調SERIALIZABLE。這種方案的弊端在於使用的底層數據庫得支持事務


spring cloud oauth2 中的併發問題

歡迎關注我的公眾號Porce2018哈。之後繼續分享工作中遇到的各種技術問題。






分享到:


相關文章: