Being throttled by Azure with retry policy of 10 minutes - c#

I have a simple console application that upload a message to a queue in Azure Service Bus, later I download the message and it throws this error: The request was terminated because the entity is being throttled. Error code : 50005. Please wait 00:00:10 seconds and try again. b1e7eb0b-5292-4b0c-8546-2877bfe961b8_G12.
I don't understand why this happens if I have a retry policy of 5 retries in a 10 minutes period. Here is the code. Could you please tell me why is this happenning?
public WebService UpAndDownloadMessage()
{
string connectionString = ConfigurationManager.ConnectionStrings["ServiceBus.NameSpace"].ConnectionString;
var queueName = ConfigurationManager.AppSettings["ServiceBus.QueueName"];
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
var key = DateTime.UtcNow;
var messageToUpload = new BrokeredMessage("This is a test message! " + key.ToString());
client.RetryPolicy = new RetryExponential(TimeSpan.FromMinutes(0.1), TimeSpan.FromMinutes(10), 5);
WebService service = new WebService()
{
Name = "AzureServiceBus",
InitDate = DateTime.UtcNow,
};
try
{
// Send the message
client.Send(messageToUpload);
// Get and delete the message
client.OnMessage(message =>
{
String.Format("Message body: {0}", message.GetBody<String>());
String.Format("Message id: {0}", message.MessageId);
});
service.EndDate = DateTime.UtcNow;
service.Status = Status.Operational;
service.ErrorMessage = "Operational";
return service;
}
catch (Exception ex)
{
service.EndDate = DateTime.UtcNow;
service.Status = Status.Down;
service.ErrorMessage = ex.Message;
service.ErrorMessage = service.ErrorMessage.Replace("\"", "");
service.ErrorMessage = service.ErrorMessage.Replace("\'", "");
return service;
}
}

Related

MqttNet version 4.1.3.563 Basic example

Following this example I have now therefore been required to update the MQTT.NET from version 3 (that works thanks the provided help) to version 4.
A very basic set of capabilities would be enough:
Connect to an adress with a timeout
Check if the connection has gone well
Receive messages
check disconnection
that was extremely easy in version 3
MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder()
.WithClientId("IoApp" + HelperN.MQTT.GetClientID(true))
.WithTcpServer("localhost", 1883);
ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(60))
.WithClientOptions(builder.Build())
.Build();
mqttClient = new MqttFactory().CreateManagedMqttClient();
mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnConnected);
mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnDisconnected);
mqttClient.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(OnConnectingFailed);
mqttClient.SubscribeAsync(...);
mqttClient.SubscribeAsync(...);
mqttClient.StartAsync(options).GetAwaiter().GetResult();
mqttClient.UseApplicationMessageReceivedHandler(args => { OnMessageReceived(args); });
but when it comes to version 4 if I have to relay on those examples I have problems.
Let's start from the connection
public static async Task Connect_Client_Timeout()
{
/*
* This sample creates a simple MQTT client and connects to an invalid broker using a timeout.
*
* This is a modified version of the sample _Connect_Client_! See other sample for more details.
*/
var mqttFactory = new MqttFactory();
strError = String.Empty;
using (var mqttClient = mqttFactory.CreateMqttClient())
{
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("aaaa127.0.0.1",1883).Build();
try
{
using (var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
{
await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token);
}
}
catch (OperationCanceledException exc)
{
strError = "Connect_Client_Timeout exc:" + exc.Message;
}
}
}
And I call this task from the main awaiting the result.
var connectTask = Connect_Client_Timeout();
connectTask.Wait();<-----never ends
Since I put a wrong address "aaaa127.0.0.1" I expect a failure after 5 seconds. But the connectTask.Wait never end. But even if I put the right address "127.0.0.1" it never exits.
So perhaps the error stands in the connectTask.Wait();.
Thanks
The solution is here
In short you have to do this:
static async Task Connect()
{
IManagedMqttClient _mqttClient = new MqttFactory().CreateManagedMqttClient();
// Create client options object
MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder()
.WithClientId("behroozbc")
.WithTcpServer("localhost");
ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(60))
.WithClientOptions(builder.Build())
.Build();
// Set up handlers
_mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync;
_mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync;
_mqttClient.ConnectingFailedAsync += _mqttClient_ConnectingFailedAsync;
// Connect to the broker
await _mqttClient.StartAsync(options);
// Send a new message to the broker every second
while (true)
{
string json = JsonSerializer.Serialize(new { message = "Hi Mqtt", sent = DateTime.UtcNow });
await _mqttClient.EnqueueAsync("behroozbc.ir/topic/json", json);
await Task.Delay(TimeSpan.FromSeconds(1));
}
Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
{
Console.WriteLine("Connected");
return Task.CompletedTask;
};
Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
{
Console.WriteLine("Disconnected");
return Task.CompletedTask;
};
Task _mqttClient_ConnectingFailedAsync(ConnectingFailedEventArgs arg)
{
Console.WriteLine("Connection failed check network or broker!");
return Task.CompletedTask;
}
}
and then just call Connect() and rely on the subscribed examples

Kafka consumer is not consuming message

I am new in Kafka. kafka consumer is not reading message from the given topic.
I am checking with kafka console as well. it is not working. i donot understand the problem. it was working fine earlier.
public string MessageConsumer(string brokerList, List<string> topics, CancellationToken cancellationToken)
{
//ConfigurationManager.AutoLoadAppSettings("", "", true);
string logKey = string.Format("ARIConsumer.StartPRoducer ==>Topics {0} Key{1} =>", "", string.Join(",", topics));
string message = string.Empty;
var conf = new ConsumerConfig
{
BootstrapServers = "localhost:9092",
GroupId = "23",
EnableAutoCommit = false,
AutoOffsetReset = AutoOffsetResetType.Latest,
};
using (var c = new Consumer<Ignore, string>(conf))
{
try
{
c.Subscribe(topics);
bool consuming = true;
// The client will automatically recover from non-fatal errors. You typically
// don't need to take any action unless an error is marked as fatal.
c.OnError += (_, e) => consuming = !e.IsFatal;
while (consuming)
{
try
{
TimeSpan timeSpan = new TimeSpan(0, 0, 5);
var cr = c.Consume(timeSpan);
// Thread.Sleep(5000);
if (cr != null)
{
message = cr.Value;
Console.WriteLine("Thread" + Thread.CurrentThread.ManagedThreadId + "Message : " + message);
CLogger.WriteLog(ELogLevel.INFO, $"Consumed message Partition '{cr.Partition}' at: '{cr.TopicPartitionOffset} thread: { Thread.CurrentThread.ManagedThreadId}'. Message: {message}");
//Console.WriteLine($"Consumed message Partition '{cr.Partition}' at: '{cr.TopicPartitionOffset}'. Topic: { cr.Topic} value :{cr.Value} Timestamp :{DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture)} GrpId: { conf.GroupId}");
c.Commit();
}
Console.WriteLine($"Calling the next Poll ");
}
catch (ConsumeException e)
{
CLogger.WriteLog(ELogLevel.ERROR, $"Error occured: {e.Error.Reason}");
Console.WriteLine($"Error occured: {e.Error.Reason}");
}
//consuming = false;
}
// Ensure the consumer leaves the group cleanly and final offsets are committed.
c.Close();
}
catch (Exception ex)
{
}
}
return message;
}
What is the issue with this code or there is installation issue with kafka
Is there a Producer actively sending data?
Your consumer is starting from the latest offsets based on the AutoOffsetReset, so it wouldn't read existing data in the topic
The console consumer also defaults to the latest offset
And if you haven't changed the GroupId, then your consumer might have worked once, then you consumed data, then commited the offsets for that group. When the consumer starts again in the same group, it will only resume from the end of the topic, or the offset of the last commit
You also have an empty catch (Exception ex), which might be hiding some other error
Try removing the timespan from consume method.

RabbitMQ response is been lost in controller

Good evening everyone, I've got a web app written using .NET and a mobile app.
I'm sending some values to rabbitMQ server through my web app and this is working fine, i put it in a queue but when the mobile app accepts the request, i don't get the returned value.
Here is my controller
public async Task<ActionResult> GetCollect(int id)
{
int PartnerId = 0;
bool SentRequest = false;
try
{
SentRequest = await RuleRabbitMQ.SentRequestRule(id);
if(SentRequest )
{
PartnerId = await RuleRabbitMQ.RequestAccepted();
}
}
catch (Exception Ex)
{
}
}
This is my RabbitMQ class
public class InteractionRabbitMQ
{
public async Task<bool> SentRequestRule(int id)
{
bool ConnectionRabbitMQ = false;
await Task.Run(() =>
{
try
{
ConnectionFactory connectionFactory = new ConnectionFactory()
{
//credentials go here
};
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.QueueDeclare("SolicitacaoSameDay", true, false, false, null);
string rpcResponseQueue = channel.QueueDeclare().QueueName;
string correlationId = Guid.NewGuid().ToString();
IBasicProperties basicProperties = channel.CreateBasicProperties();
basicProperties.ReplyTo = rpcResponseQueue;
basicProperties.CorrelationId = correlationId;
byte[] messageBytes = Encoding.UTF8.GetBytes(string.Concat(" ", id.ToString()));
channel.BasicPublish("", "SolicitacaoSameDay", basicProperties, messageBytes);
channel.Close();
connection.Close();
if (connection != null)
{
ConnectionRabbitMQ = true;
}
else
{
ConnectionRabbitMQ = false;
}
}
catch (Exception Ex)
{
throw new ArgumentException($"Thre was a problem with RabbitMQ server. " +
$"Pleaser, contact the support with Error: {Ex.ToString()}");
}
});
return ConnectionRabbitMQ;
}
public async Task<int> RequestAccepted()
{
bool SearchingPartner= true;
int PartnerId = 0;
await Task.Run(() =>
{
try
{
var connectionFactory = new ConnectionFactory()
{
// credentials
};
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.BasicQos(0, 1, false);
var eventingBasicConsumer = new EventingBasicConsumer(channel);
eventingBasicConsumer.Received += (sender, basicDeliveryEventArgs) =>
{
string Response = Encoding.UTF8.GetString(basicDeliveryEventArgs.Body, 0, basicDeliveryEventArgs.Body.Length);
channel.BasicAck(basicDeliveryEventArgs.DeliveryTag, false);
if(!string.IsNullOrWhiteSpace(Response))
{
int Id = Convert.ToInt32(Response);
PartnerId = Id > 0 ? Id : 0;
SearchingPartner = false;
}
};
channel.BasicConsume("SolicitacaoAceitaSameDay", false, eventingBasicConsumer);
}
catch (Exception Ex)
{
// error message
}
});
return PartnerId ;
}
I am not sure this works, can't build an infrastructure to test this quickly, but - your issue is that the RequestAccepted returns a Task which completes before the Received event is caught by the Rabbit client library.
Syncing the two could possibly resolve the issue, note however that this could potentially make your code waiting very long for (or even - never get) the response.
public Task<int> RequestAccepted()
{
bool SearchingPartner= true;
int PartnerId = 0;
var connectionFactory = new ConnectionFactory()
{
// credentials
};
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.BasicQos(0, 1, false);
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
var eventingBasicConsumer = new EventingBasicConsumer(channel);
eventingBasicConsumer.Received += (sender, basicDeliveryEventArgs) =>
{
string Response = Encoding.UTF8.GetString(basicDeliveryEventArgs.Body, 0, basicDeliveryEventArgs.Body.Length);
channel.BasicAck(basicDeliveryEventArgs.DeliveryTag, false);
if(!string.IsNullOrWhiteSpace(Response))
{
int Id = Convert.ToInt32(Response);
PartnerId = Id > 0 ? Id : 0;
SearchingPartner = false;
tcs.SetResult( PartnerId );
}
};
channel.BasicConsume("SolicitacaoAceitaSameDay", false, eventingBasicConsumer);
return tcs.Task;
}
There are couple of issues with this approach.
First, no error handling.
Then, what if the event is sent by the RMQ before the consumer subscribes to it? The consumer will block as it will never receive anything back.
And last, I don't think RMQ consumers are ever intended to be created in every request to your controller and then never disposed. While this could work on your dev box where you create a couple of requests manually, it won't probably ever scale to fix a scenario where dozens/hundreds of concurrent users hit your website and multiple RMQ consumers compete one against the other.
I don't think there is an easy way around it other than completely separate the consumer out of your web app, put it in a System Service or a Hangfire job and let it get responses to all possible requests and from the cache - serve responses to web requests.
This is a pure speculation, though, based on my understanding of what you try to do. I could be wrong here, of course.
byte[] messageBytes = Encoding.UTF8.GetBytes(string.Concat(" ", idColeta.ToString()));
I reckon 'idColeta' is blank.

Random Azure Function Apps failures: Host thresholds exceeded [Connections]

I have the following Function App
[FunctionName("SendEmail")]
public static async Task Run([ServiceBusTrigger("%EmailSendMessageQueueName%", AccessRights.Listen, Connection = AzureFunctions.Connection)] EmailMessageDetails messageToSend,
[ServiceBus("%EmailUpdateQueueName%", AccessRights.Send, Connection = AzureFunctions.Connection)]IAsyncCollector<EmailMessageUpdate> messageResponse,
//TraceWriter log,
ILogger log,
CancellationToken token)
{
log.LogInformation($"C# ServiceBus queue trigger function processed message: {messageToSend}");
/* Validate input and initialise Mandrill */
try
{
if (!ValidateMessage(messageToSend, log)) // TODO: finish validation
{
log.LogError("Invalid or Unknown Message Content");
throw new Exception("Invalid message content.");
}
}
catch (Exception ex)
{
log.LogError($"Failed to Validate Message data: {ex.Message} => {ex.ReportAllProperties()}");
throw;
}
DateTime utcTimeToSend;
try
{
var envTag = GetEnvVariable("Environment");
messageToSend.Tags.Add(envTag);
utcTimeToSend = messageToSend.UtcTimeToSend.GetNextUtcSendDateTime();
DateTime utcExpiryDate = messageToSend.UtcTimeToSend.GetUtcExpiryDate();
DateTime now = DateTime.UtcNow;
if (now > utcExpiryDate)
{
log.LogError($"Stopping sending message because it is expired: {utcExpiryDate}");
throw new Exception($"Stopping sending message because it is expired: {utcExpiryDate}");
}
if (utcTimeToSend > now)
{
log.LogError($"Stopping sending message because it is not allowed to be send due to time constraints: next send time: {utcTimeToSend}");
throw new Exception($"Stopping sending message because it is not allowed to be send due to time constraints: next send time: {utcTimeToSend}");
}
}
catch (Exception ex)
{
log.LogError($"Failed to Parse and/or Validate Message Time To Send: {ex.Message} => {ex.ReportAllProperties()}");
throw;
}
/* Submit message to Mandrill */
string errorMessage = null;
IList<MandrillSendMessageResponse> mandrillResult = null;
DateTime timeSubmitted = default(DateTime);
DateTime timeUpdateRecieved = default(DateTime);
try
{
var mandrillApi = new MandrillApi(GetEnvVariable("Mandrill:APIKey"));
var mandrillMessage = new MandrillMessage
{
FromEmail = messageToSend.From,
FromName = messageToSend.FromName,
Subject = messageToSend.Subject,
TrackClicks = messageToSend.Track,
Tags = messageToSend.Tags,
TrackOpens = messageToSend.Track,
};
mandrillMessage.AddTo(messageToSend.To, messageToSend.ToName);
foreach (var passthrough in messageToSend.PassThroughVariables)
{
mandrillMessage.AddGlobalMergeVars(passthrough.Key, passthrough.Value);
}
timeSubmitted = DateTime.UtcNow;
if (String.IsNullOrEmpty(messageToSend.TemplateId))
{
log.LogInformation($"No Message Template");
mandrillMessage.Text = messageToSend.MessageBody;
mandrillResult = await mandrillApi.Messages.SendAsync(mandrillMessage, async: true, sendAtUtc: utcTimeToSend);
}
else
{
log.LogInformation($"Using Message Template: {messageToSend.TemplateId}");
var clock = new Stopwatch();
clock.Start();
mandrillResult = await mandrillApi.Messages.SendTemplateAsync(
mandrillMessage,
messageToSend.TemplateId,
async: true,
sendAtUtc: utcTimeToSend
);
clock.Stop();
log.LogInformation($"Call to mandrill took {clock.Elapsed}");
}
timeUpdateRecieved = DateTime.UtcNow;
}
catch (Exception ex)
{
log.LogError($"Failed to call Mandrill: {ex.Message} => {ex.ReportAllProperties()}");
errorMessage = ex.Message;
}
try
{
MandrillSendMessageResponse theResult = null;
SendMessageStatus status = SendMessageStatus.FailedToSendToProvider;
if (mandrillResult == null || mandrillResult.Count < 1)
{
if (String.IsNullOrEmpty(errorMessage))
{
errorMessage = "Invalid Mandrill result.";
}
}
else
{
theResult = mandrillResult[0];
status = FacMandrillUtils.ConvertToSendMessageStatus(theResult.Status);
}
var response = new EmailMessageUpdate
{
SentEmailInfoId = messageToSend.SentEmailInfoId,
ExternalProviderId = theResult?.Id ?? String.Empty,
Track = messageToSend.Track,
FacDateSentToProvider = timeSubmitted,
FacDateUpdateRecieved = timeUpdateRecieved,
FacErrorMessage = errorMessage,
Status = status,
StatusDetail = theResult?.RejectReason ?? "Error"
};
await messageResponse.AddAsync(response, token).ConfigureAwait(false);
}
catch (Exception ex)
{
log.LogError($"Failed to push message to the update ({AzureFunctions.EmailUpdateQueueName}) queue: {ex.Message} => {ex.ReportAllProperties()}");
throw;
}
}
When I queue up 100 messages, everything runs fine. When I queue up 500+ messages, 499 of them are sent but the last none never is sent. I also start to get the following errors.
The operation was canceled.
I have Application Insights setup and configured and I have logging running. I am not able to reproduce locally and based on the following End-to-end transaction details from Application Insights, I believe the issue is happening at this point :
await messageResponse.AddAsync(response, token).ConfigureAwait(false);
Application Insights End-to-end transaction
host.json
{
"logger": {
"categoryFilter": {
"defaultLevel": "Information",
"categoryLevels": {
"Host": "Warning",
"Function": "Information",
"Host.Aggregator": "Information"
}
}
},
"applicationInsights": {
"sampling": {
"isEnabled": true,
"maxTelemetryItemsPerSecond": 5
}
},
"serviceBus": {
"maxConcurrentCalls": 32
}
}
Likely related is this error from Application Insights as well.
[
Has anyone else had this or similar issues?
If you follow the link from exception https://aka.ms/functions-thresholds, you will see the following limitation:
Connections : Number of outbound connections (limit is 300). For information on handling connection limits, see Managing Connections.
You are likely to have hit that one.
In each function call you create a new instance of MandrillApi. You haven't mentioned which library you are using, but I suspect it's creating a new connection for each instance of MandrillApi.
I checked Mandrill Dot Net and yes, it's creating a new HttpClient for each instance:
_httpClient = new HttpClient
{
BaseAddress = new Uri(BaseUrl)
};
Managing Connections recommends:
In many cases, this connection limit can be avoided by re-using client instances rather than creating new ones in each function. .NET clients like the HttpClient, DocumentClient, and Azure storage clients can manage connections if you use a single, static client. If those clients are re-instantiated with every function invocation, there is a high probability that the code is leaking connections.
Check the documentation of that library if API client is thread-safe, and reuse it between the function invocations if so.

Specified argument was out of the range of valid values. creationOptions at apnsBroker.Start()

I created an console app with .NET 4.0 like this:
static void Test2(string deviceToken, string message)
{
try
{
//Get Certificate
var appleCert = System.IO.File.ReadAllBytes("Certificates_moi.p12");
// Configuration (NOTE: .pfx can also be used here)
var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Sandbox, appleCert, "vnpt1234");
// Create a new broker
var apnsBroker = new ApnsServiceBroker(config);
// Wire up events
apnsBroker.OnNotificationFailed += (notification, aggregateEx) =>
{
aggregateEx.Handle(ex =>
{
// See what kind of exception it was to further diagnose
if (ex is ApnsNotificationException)
{
var notificationException = (ApnsNotificationException)ex;
// Deal with the failed notification
var apnsNotification = notificationException.Notification;
var statusCode = notificationException.ErrorStatusCode;
string desc = "Apple Notification Failed: ID={apnsNotification.Identifier}, Code={statusCode}";
Console.WriteLine(desc);
//lblStatus.Text = desc;
}
else
{
string desc = "Apple Notification Failed for some unknown reason : {ex.InnerException}";
// Inner exception might hold more useful information like an ApnsConnectionException
Console.WriteLine(desc);
//lblStatus.Text = desc;
}
// Mark it as handled
return true;
});
};
apnsBroker.OnNotificationSucceeded += (notification) =>
{
//lblStatus.Text = "Apple Notification Sent successfully!";
Console.WriteLine("Apple Notification Sent successfully!");
};
var fbs = new FeedbackService(config);
fbs.FeedbackReceived += (string devicToken, DateTime timestamp) =>
{
// Remove the deviceToken from your database
// timestamp is the time the token was reported as expired
};
// Start Proccess
apnsBroker.Start();
if (deviceToken != "")
{
apnsBroker.QueueNotification(new ApnsNotification
{
DeviceToken = deviceToken,
Payload = JObject.Parse(("{\"aps\":{\"badge\":1,\"sound\":\"oven.caf\",\"alert\":\"" + (message + "\"}}")))
});
}
apnsBroker.Stop();
}
catch (Exception ex)
{
throw;
}
}
There is an error at apnsBroker.Start();
- $exception {"Specified argument was out of the range of valid values.\r\nParameter name: creationOptions"} System.Exception {System.ArgumentOutOfRangeException}
Can anybody help me, please?
I fixed this issue. Move to another machine running .NET 4.5 and it worked.

Categories

Resources