技术价值与优势
- 避免惊群效应 (Thundering Herd Problem): 如果没有这种 Leader/Follower 机制,高并发下的多个 401 响应会导致所有线程同时发起 Token 刷新请求,瞬间压垮服务器或造成客户端资源浪费。
- 结果一致性 (Consistency): 所有在同一时间窗口内的 Follower 都会获得与 Leader 完全相同的结果(Token),保证了并发环境下状态的一致性。
- 高效的同步屏障: 利用
FutureTask 作为同步屏障,既实现了阻塞等待,又自带状态管理(Running/Completed/Cancelled),无需手动编写复杂的 wait/notify 逻辑。
class SignAuthenticator : Authenticator {
companion object {
private const val TAG = "SignAuthenticator"
private const val REFRESH_TIMEOUT_SECONDS = 30L
}
private val refreshingTask = AtomicReference<FutureTask<Boolean>?>(null)
override fun authenticate(route: Route?, response: Response): Request? {
val refreshSuccess = refreshToken()
logger.i(TAG, "authenticate :: refreshSuccess = $refreshSuccess")
if (SignManager.isResignRequest(response.request())) {
logger.i(TAG, "authenticate :: Ignoring resign request")
return null
}
return if (refreshSuccess) {
runCatching { response.close() }
val (signedRequest, signSuccess) = SignManager.generateNewRequest(response.request(), true)
if (signSuccess) {
signedRequest
} else {
null
}
} else {
null
}
}
private fun refreshToken(): Boolean {
val newTask = FutureTask { SignManager.refreshKeySync() }
if (refreshingTask.compareAndSet(null, newTask)) {
try {
newTask.run()
return newTask.get()
} catch (_: Exception) {
logger.e(TAG, "authenticate :: Refresh execution failed")
return false
} finally {
refreshingTask.compareAndSet(newTask, null)
}
} else {
val currentTask = refreshingTask.get() ?: return false
logger.i(TAG, "authenticate :: Waiting for existing refresh (Follower)")
return try {
currentTask.get(REFRESH_TIMEOUT_SECONDS, TimeUnit.SECONDS)
} catch (_: Exception) {
logger.w(TAG, "authenticate :: Wait failed")
false
}
}
}
}