-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
[BUG] ServiceBusSessionReceiverClient closes only after timeout #39565
Comments
Thank you for your feedback. Tagging and routing to the team member best able to assist. |
Hello @pawel-wilczopolski hope you're doing good. @conniey and I discussed this today. So, the internal state machine of AMQP library is asynchronous and the reason for it wait on force close is to ensure any lingering messages, dispositions (complete|abandon) enqueued and other state in transit is processed, so things are cleaned up gracefully. If a continuous receive and high throughput is desired, it is recommended to use the ServiceBusProcessorClient. Please see here. As it says there, the use of Synchronous Client (ServiceBus[Session|Receiver]Client) is typically discouraged, because the user has to deal with more errors and possible message expirations. On the other hand, the ServiceBusProcessorClient handles errors automatically and takes care of multi-threading, so receive from multiple sessions can happen in parallel. For the long term, ServiceBusProcessorClient will help the applications be more reliable. If Synchronous client is still needed, and if you’re going to build a new ServiceBusSessionClient instance or restart the service after the close, you may do a fire-and-forget close, i.e, invoke close on a separate thread and giving it a few seconds before the restart/building new client using a new builder. The code may looks like- // The ServiceBusSessionReceiver is no longer needed.
// Fire and forget the client close
try {
CompletableFuture.supplyAsync(() -> {
// call ServiceBusSessionReceiver::close.
return null;
})
.toCompletableFuture().get(5, TimeUnit.SECONDS);
} catch (Exception e) {
// log(e);
}
// Service restarts or application creates new ServiceBusSessionReceiver |
Hi all,
I cannot use ServiceBusProcessorClient because it hides a lot of errors that I need to handle on my side. Your solution is not resolving the real issue. I found out that you have a bug because the waiting logic begins too fast.
In other words – we start waiting 1 minute BEFORE we get the ACK from the server that would cause the graceful shutdown immediately. Please refer to this.
Regards,
Paweł Wilczopolski
From: Anu Thomas Chandy ***@***.***>
Sent: Thursday, April 11, 2024 12:43 AM
To: Azure/azure-sdk-for-java ***@***.***>
Cc: Pawel Wilczopolski ***@***.***>; Mention ***@***.***>
Subject: Re: [Azure/azure-sdk-for-java] [BUG] ServiceBusSessionReceiverClient closes only after timeout (Issue #39565)
Hello @pawel-wilczopolski<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_pawel-2Dwilczopolski&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=HXFQ3pqBriDJ5Fy_brwlqr7slA4OrpjHCKqO4kvqFDM&m=bA1gV65wqjRe2lAi81ye89XYjbY4V3az-9PSi4Bc-o08O6PfKEIu3j4Tccv8m7jc&s=3og3Po7PP6dlUKSZJWABLmfj2SZOgJPEpZq2LTCDkys&e=> hope you're doing good. @conniey<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_conniey&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=HXFQ3pqBriDJ5Fy_brwlqr7slA4OrpjHCKqO4kvqFDM&m=bA1gV65wqjRe2lAi81ye89XYjbY4V3az-9PSi4Bc-o08O6PfKEIu3j4Tccv8m7jc&s=4qL1Vp_FvUv4g4M_D6NxnUkXSURX_3ZeGJW3varTNSw&e=> and I discussed this today. So, the internal state machine of AMQP library is asynchronous and the reason for it wait on force close is to ensure any lingering messages, dispositions (complete|abandon) enqueued and other state in transit is processed, so things are cleaned up gracefully.
If a continuous receive and high throughput is desired, it is recommended to use the ServiceBusProcessorClient. Please see here<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Azure_azure-2Dsdk-2Dfor-2Djava_tree_main_sdk_servicebus_azure-2Dmessaging-2Dservicebus-23when-2Dto-2Duse-2Dservicebusprocessorclient&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=HXFQ3pqBriDJ5Fy_brwlqr7slA4OrpjHCKqO4kvqFDM&m=bA1gV65wqjRe2lAi81ye89XYjbY4V3az-9PSi4Bc-o08O6PfKEIu3j4Tccv8m7jc&s=d7wScfcArik_u-c7hMieyD3tmCX4hMjBndAILklD-DQ&e=>. As it says there, the use of Synchronous Client (ServiceBus[Session|Receiver]Client) is typically discouraged, because the user has to deal with more errors and possible message expirations. On the other hand, the ServiceBusProcessorClient handles errors automatically and takes care of multi-threading, so receive from multiple sessions can happen in parallel. For the long term, ServiceBusProcessorClient will help the applications be more reliable.
If Synchronous client is still needed, and if you’re going to build a new ServiceBusSessionClient instance or restart the service after the close, you may do a fire-and-forget close, i.e, invoke close on a separate thread and giving it a few seconds before the restart/building new client using a new builder. The code may looks like-
// The ServiceBusSessionReceiver is no longer needed.
// Fire and forget the client close
try {
CompletableFuture.supplyAsync(() -> {
// call ServiceBusSessionReceiver::close.
return null;
})
.toCompletableFuture().get(5, TimeUnit.SECONDS);
} catch (Exception e) {
// log(e);
}
// Service restarts or application creates new ServiceBusSessionReceiver
—
Reply to this email directly, view it on GitHub<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Azure_azure-2Dsdk-2Dfor-2Djava_issues_39565-23issuecomment-2D2048553634&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=HXFQ3pqBriDJ5Fy_brwlqr7slA4OrpjHCKqO4kvqFDM&m=bA1gV65wqjRe2lAi81ye89XYjbY4V3az-9PSi4Bc-o08O6PfKEIu3j4Tccv8m7jc&s=h4bBCyIldjVmDWflTEJXxxFjZyKcrHdG9at1RDockUM&e=>, or unsubscribe<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_notifications_unsubscribe-2Dauth_BFMFPJQ7PLUME3CZXDLNNTTY4W55VAVCNFSM6AAAAABFZJCK2OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBYGU2TGNRTGQ&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=HXFQ3pqBriDJ5Fy_brwlqr7slA4OrpjHCKqO4kvqFDM&m=bA1gV65wqjRe2lAi81ye89XYjbY4V3az-9PSi4Bc-o08O6PfKEIu3j4Tccv8m7jc&s=g-c5lzdaj88g7aYYtzSlBETN2B1EqnOdSka9EEfu0CE&e=>.
You are receiving this because you were mentioned.Message ID: ***@***.******@***.***>>
|
Adding additional notes on the safety of the above workaround provided - when offloading the closure with a client-side timeout, there are two execution paths, both leading to eventual shutdown and garbage collection of reactor-executor thread, i.e., the reactor-executor thread won’t stay around and will not have any impact. • [Execution-Path-1] Either application or host (VM, container) exit after calling close(). In the first case, since the JVM exits, all threads get cleaned up as part of the exit. In the second case, the old reactor-executor thread will continue its final cleanup activities on the background (without blocking the main thread) and exit. We’ve created a work item to improve this experience. Linking it here, please track it there. Closing this. |
Describe the bug
After invoking ServiceBusSessionReceiverClient
close()
method, the operation lasts for thetryTimeout
period (1 minute by default) ofAmqpRetryOptions
.The client should be closed immediately instead of waiting 1 minute.
Exception or Stack Trace
The following log is always visible after timeout (default 1 minute) is reached:
"Timed out waiting for RequestResponseChannel to complete closing. Manually closing."
To Reproduce
Code Snippet
Expected behavior
The ServiceBusSessionReceiverClient should be closed immediately.
Setup (please complete the following information):
The text was updated successfully, but these errors were encountered: