question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] EventHubProducerClient is being throttled but not informing the calling application.

See original GitHub issue

Describe the bug EventHubProducerClient send requests throttled but without giving the information back to the client. Instead only a WARNING log is printed (where how much time to wait is also printed). Application cannot reduce the frequency of send unless the information is available to the application.

Also, the error code: 50002 (mentioned in the WARNING log) doesn’t have an entry in the linked website: https://aka.ms/sbResourceMgrExceptions (also mentioned in the WARNING log).

Exception or Stack Trace

06:50:05 [single-1] WARN  c.a.c.a.i.ReactorSender - entityPath[dummy], linkName[dummy], deliveryTag[350acd586c70467ca4f81c30714a5403]: Delivery rejected. [Rejected{error=Error{condition=com.microsoft:server-busy, description='The request was terminated because the entity is being throttled. Error code : 50002. Please wait 4 seconds and try again. To know more visit https://aka.ms/sbResourceMgrExceptionsS:N:<NAMESPACE>:EVENTHUB:DUMMY~32766,CL:3159,CC:3964,ACC:471701,LUR:<NAMESPACE>_105187,RC:991 TrackingId:0fc2c77200009ae30008e7b55eb65120_G25_B39, SystemTracker:<namespace>:eventhub:dummy~32766, Timestamp:2020-05-09T06:50:05', info=null}}]

To Reproduce Create an EventHub namespace with 1 EventHub having only 1 partition. Start consuming from an EventHub which has a lot of messages available using the same SDK’s EventProcessorClient with the following EventHandler implementation:

import com.azure.messaging.eventhubs.EventData;
import com.azure.messaging.eventhubs.EventDataBatch;
import com.azure.messaging.eventhubs.EventHubProducerClient;
import com.azure.messaging.eventhubs.models.CreateBatchOptions;
import com.azure.messaging.eventhubs.models.EventContext;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;


@Slf4j
public class Event implements Consumer<EventContext>, AutoCloseable {

    private final EventHubProducerClient eventHubProducerClient;
    private final CreateBatchOptions createBatchOptions;

    private final ThreadLocal<List<EventData>> toBePushed = ThreadLocal.withInitial(ArrayList::new);
    private final ThreadLocal<Integer> approxBatchSizeInBytes = ThreadLocal.withInitial(() -> 0);

    private static final int overheadPerBatchInBytes = 15360;
    private static final int overheadPerMsgInBytes = 30;
    private static final int maxMsgsPerBatch = 990;


    public Event(EventHubProducerClient eventHubProducerClient,
                 CreateBatchOptions createBatchOptions) {

        this.eventHubProducerClient = eventHubProducerClient;
        this.createBatchOptions = createBatchOptions;
    }


    private synchronized void pushToEH() {

        try {
            EventDataBatch eventDataBatch = eventHubProducerClient.createBatch(createBatchOptions);

            for (EventData eventData: toBePushed.get()) {
                if (!eventDataBatch.tryAdd(eventData)) {

                    eventHubProducerClient.send(eventDataBatch);
                    eventDataBatch = eventHubProducerClient.createBatch(createBatchOptions);

                    if (!eventDataBatch.tryAdd(eventData)) {
                        log.error("Event is too large for an empty batch. Max size: " + eventDataBatch.getMaxSizeInBytes());
                    }
                }
            }
            toBePushed.get().clear();

            if (eventDataBatch.getCount() > 0) {
                eventHubProducerClient.send(eventDataBatch);
            }
        } catch (Exception e) {
            log.error("Exception: ", e);
        }

        approxBatchSizeInBytes.set(0);
    }


    private void publish(byte[] payload) {

        toBePushed.get().add(new EventData(payload));
        approxBatchSizeInBytes.set(approxBatchSizeInBytes.get() + (payload.length + overheadPerMsgInBytes));

        if (toBePushed.get().size() > maxMsgsPerBatch
                || (approxBatchSizeInBytes.get() + overheadPerBatchInBytes >= createBatchOptions.getMaximumSizeInBytes())) {

            pushToEH();
        }
    }


    @Override
    public void accept(EventContext eventContext) {

        try {
            publish(eventContext.getEventData().getBody());
        } catch (Exception e) {
            log.error("Error in Event Handler: ", e);
        }
    }


    @Override
    public void close() {
        eventHubProducerClient.close();
        log.info("EventHubProducerClient stopped.");
    }
}

Expected behavior The throttling information must be passed back to the calling application so the application can throttle the behavior at its own end.

Setup (please complete the following information):

  • Version of the Library used: 5.1.0

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
srnagarcommented, May 12, 2020

The exception type that will be propagated in this case is AmqpException. This will have the errorCondition set to AmqpErrorCondition.SERVER_BUSY_ERROR. The wait time is currently not exposed as a field in the exception but is available in the error message - “… Please wait 4 seconds and try again”. I will see if this can be exposed as a Duration in the exception.

The error codes are language agnostic but I agree that they should be documented in a language-neutral page. Thanks for your feedback and I’ll follow up on making the documentation on error code better.

0reactions
shubhambhattarcommented, May 24, 2020

Thanks for the info @srnagar .

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshoot issues with Azure Event Hubs for Apache Kafka
If fetch request's delay exceeds request timeout, Event Hubs logs the request as throttled and responds with empty set of records and no...
Read more >
ISP Throttling: What is it & How to Stop Internet Throttling - Avast
Throttling occurs when your ISP slows down the speed of your internet connection. Here's why internet throttling happens and how to stop it....
Read more >
How to Tell if Your Internet Is Being Throttled - BroadbandNow
ISP throttling is a money-saving tactic used by internet companies to moderate network traffic, control bandwidth congestion, and mandate data ...
Read more >
Is My Internet Being Throttled? | Is Your Provider Slowing ...
ISP throttling Internet speeds or applying data caps is not always an indication of network congestion but may be used by ISPs to...
Read more >
Study claims streaming video apps are being throttled by ...
In these tests, YouTube was the most throttled mobile app. Netflix, Amazon Prime, and the NBC Sports app were also subject to data...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found