Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Messaging] Stop Unnecessary Refresh of JWT Tokens #23129

Merged
merged 1 commit into from
Aug 16, 2021

Conversation

jsquire
Copy link
Member

@jsquire jsquire commented Aug 5, 2021

Summary

The focus of these changes is to cache JWT tokens used for authorization of AMQP connections and links to avoid making unnecessary requests due to network changes while the token is not near expiration. For features like Service Bus sessions, links can be opened/closed frequently, leading to a non-trivial amount of requests to acquire tokens that are likely to remain valid for the duration of their use.

Also included is the addition of a small amount of random jitter when calculating the time that AMQP authorization should be resent; this is intended to reduce contention when a new token needs to be acquired.

References and Related

@jsquire jsquire added Service Bus Event Hubs Client This issue points to a problem in the data-plane of the library. labels Aug 5, 2021
@jsquire jsquire added this to the [2021] September milestone Aug 5, 2021
@jsquire jsquire self-assigned this Aug 5, 2021
string[] requiredClaims) =>
Credential switch
{
_ when Credential.IsSharedAccessCredential => await AcquireSharedAccessTokenAsync().ConfigureAwait(false),
Copy link
Member Author

@jsquire jsquire Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot be sure that a shared key was not rolled/updated within the credential, which would would invalidate our cached token ahead of its expiration, so we don't want to cache these. The shared access credentials also manage the token lifetime and extend when appropriate, so the only benefit of caching would be to avoid a small number of allocations in a background task doing network IO.

///
private async Task<CbsToken> AcquireJwtTokenAsync()
{
var token = Volatile.Read(ref _cachedJwtToken);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AMQP authorization is refreshed only when a token is due to expire, a token was rejected, or a new connection/link is being established, most often taking place on a background thread. Because this isn't on a performance-critical path called during every network operation, ensuring a longer-lived token is more valuable than quick token acquisition for overall throughput.

Rather than doing something more complicated, like returning a short-lived token and requesting a fresh token in the background, I believe that we're better served by requesting the token on-demand and just synchronizing to ensure we don't make redundant requests. As a result, this is intentionally simple, just using the good old lock+double-check pattern.

@jsquire
Copy link
Member Author

jsquire commented Aug 5, 2021

/azp run net - eventhub - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jsquire
Copy link
Member Author

jsquire commented Aug 5, 2021

/azp run net - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jsquire
Copy link
Member Author

jsquire commented Aug 5, 2021

@JoshLove-msft: I'm planning on not merging this until after the August release, so that I've got time to run the suite of long-running stress tests. Any concerns with this not making it in immediately?

@JoshLove-msft
Copy link
Member

@JoshLove-msft: I'm planning on not merging this until after the August release, so that I've got time to run the suite of long-running stress tests. Any concerns with this not making it in immediately?

SGTM

@jsquire jsquire force-pushed the messaging/cache-token branch from de15c63 to 547f67d Compare August 6, 2021 19:28
The focus of these changes is to cache JWT tokens used for authorization
of AMQP connections and links to avoid making unnecesary requests due to network
changes while the token is not near expiration.

For features like Service Bus sessions, links can be opened/closed frequently,
leading to a non-trivial amount of requests to acquire tokens that are likely to
remain valid for the duration of their use.

Also included is the addition of a small amount of random jitter when calculating
the time that AMQP authorization should be resent; this is intended to reduce
contention when a new token needs to be acquired.
@jsquire jsquire force-pushed the messaging/cache-token branch from 547f67d to 26f9b2c Compare August 6, 2021 19:39
@jsquire jsquire merged commit 774caf6 into Azure:main Aug 16, 2021
@jsquire jsquire deleted the messaging/cache-token branch August 16, 2021 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Client This issue points to a problem in the data-plane of the library. Event Hubs Service Bus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants