I'm creating a sample .net core solution in local and IIS larger message consuming in a queue within a second but I'm deployed in Linux server to could take more time to consume a message in a queue. I don't know how to resolve it kindly help me. Below I attached my sample code here.
string topic = "QueueTest";
QueueConnectionFactory.OptimizeAcknowledge = true;
QueueConnectionFactory.AlwaysSyncSend = false;
using (IConnection connection = QueueConnectionFactory.CreateConnection("admin", "admin"))
{
connection.Start();
Apache.NMS.ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
using (IDestination dest = session.GetQueue(topic))
using (IMessageConsumer consumer = session.CreateConsumer(dest))
{
// TimeSpan span4 = TimeSpan.FromSeconds(3);
IMessage msg = consumer.Receive();
if (msg != null)
{
ITextMessage message = msg as ITextMessage;
string data = message.Text;
}
}
}
Check for receiveBufferSize and sendBufferSize and you can add this to your connection url :
?transport.receiveBufferSize=65536&transport.sendBufferSize=16384
Related
I created a simple Azure Service bus (Queue) and a client that is sending message to service bus. Using below code to send message:
using Microsoft.Azure.ServiceBus;
using Microsoft.Extensions.Configuration;
public async Task SendMessageAsync<T>(T message, string queueName)
{
try
{
var queueClient = new QueueClient(_config.GetConnectionString("AzureServiceBus"), queueName);
string messageBody = JsonSerializer.Serialize(message);
var byteMessage = new Message(Encoding.UTF8.GetBytes(messageBody));
queueClient.SendAsync(byteMessage);
Console.WriteLine((message as Employee).FirstName);
}
catch (Exception ex)
{
var c = ex;
}
}
Sending message using:
using SenderApp;
Console.WriteLine("Hello, World!");
QueueService service = new QueueService();
for (int i = 0; i < 100; i++)
{
Employee e = new Employee();
e.FirstName = "1 " + i.ToString();
e.LastName = "2 " + i.ToString();
service.SendMessageAsync<Employee>(e, "employeequeue");
}
When I try to see active messages, There is nothing in the queue:
However I do see some traffic. But the number of message I sent (over 100) is not equal to number of incoming request show (62) at the bottom of the image. I am not sure what is happening to my messages? This defeats the purpose of the queue.
Please guide me why I am not seeing any messages. What is the best way to handle this ?
I am using following nuget packages:
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="5.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
A message sent to an Azure Service Bus queue will be delivered to the queue unless operation is failing. In that case, an exception will be thrown. Check the following:
Exception handling doesn't swollow exceptions
Await asynchronous send operations to ensure messages are dispatched
Namespace/queue used for sending is what you use to receive
There are no competing consumers, actively receiving messages from the queue.
Validate TCP ports needed for AMQP are not blocked. If those ports are blocked, you could configure your client to use WebSockets.
So I still dont know what caused this issue. But I realized Microsoft.Azure.ServiceBus package was deprecated and later I started using Azure.Messaging.ServiceBus package to connect to service bus and things started to work.
I used following code to send message to queue:
string connectionString = "Endpoint=sb://test.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=f3f+qMYTyVwE18YNl5J6ygJFi30v6J/Smph5HZvyQyE=";
string queueName = "employeequeue";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);
// create the sender
ServiceBusSender sender = client.CreateSender(queueName);
// create a message that we can send. UTF-8 encoding is used when providing a string.
ServiceBusMessage message = new ServiceBusMessage("Hello world! " + id);
// send the message
await sender.SendMessageAsync(message);
return "Sent";
Used following code to receive message:
string queueName = "employeequeue";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);
// create a receiver that we can use to receive and settle the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
string body = receivedMessage.Body.ToString();
// complete the message, thereby deleting it from the service
await receiver.CompleteMessageAsync(receivedMessage);
More info is available # https://github.com/Azure/azure-sdk-for-net/blob/Azure.Messaging.ServiceBus_7.7.0/sdk/servicebus/Azure.Messaging.ServiceBus/README.md
I created a Azure Topic and a subscription with Session-Enabled to be true. I can send a message to the topic with a non empty SessionId. But When I tied to read the message with the following code, it throws the timeout execption at subClient.AcceptMessageSession. Did I do anything wrong? The similar code (with QueueClient) works fine for a direct session enabled Azure Queue.
SubscriptionDescription subscriptionDescription = namespaceManager.GetSubscription(Topic_Name, Subscription_Name);
SubscriptionClient subClient = SubscriptionClient.CreateFromConnectionString(connectionString, Topic_Name, Subscription_Name);
if (subscriptionDescription.RequiresSession)
{
msgSession = subClient.AcceptMessageSession(TimeSpan.FromSeconds(120));
if (msgSession != null)
{
message = msgSession.Receive(TimeSpan.FromSeconds(5));
}
}
else
message = subClient.Receive(TimeSpan.FromSeconds(5));
if I send a message (Cloud 2 Device) via the IoT-Hub:
var serviceMessage= new Message(Encoding.ASCII.GetBytes("Hello Device"));
serviceMessage.Ack = DeliveryAcknowledgement.Full;
commandMessage.MessageId = Guid.NewGuid().ToString();
await serviceClient.SendAsync("myDeviceID", serviceMessage); //Send message here
And try to receive the acknoledgement from the client:
bool feedbackReceived = false;
while(!feedbackReceived){
FeedbackReceiver<FeedbackBatch> feedbackReceiver = serviceClient.GetFeedbackReceiver();
var feedbackBatch = await feedbackReceiver.ReceiveAsync(TimeSpan.FromSeconds(1));
if(feedbackBatch != null)
{
feedbackReceived = feedbackBatch.Records.Any(fm => fm.OriginalMessageId == serviceMessage.MessageId);
if (feedbackReceived)
{
await feedbackReceiver.CompleteAsync(feedbackBatch);
feedbackReceiver = null;
}
}
}
My client gets the message immediatelly and sends an feedback:
DeviceClient deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(bridgeID, deviceKey), TransportType.Amqp);
Message receivedMessage = await deviceClient.ReceiveAsync();
await deviceClient.CompleteAsync(receivedMessage);
It take up to 15 seconds until my Cloud gets the feedback.
If I send messages in a loop, then the first message needs something between 1 and 15 sconds and every following response needs exactly 15 seconds.
Why does that need so long? Can I change it?
The receive-method in my cloud gets an answer immediatelly:
var incommingMessage = eventHubReceiver.ReceiveAsync();
incommingMessage.Wait();
If the client sends a message:
var message = new Message(Encoding.ASCII.GetBytes("My Message"));
await deviceClient.SendEventAsync(message);
A whole project with the problem is on gitHub:
https://github.com/Ben4485/Azure_IotHub_Get_Response
Of course 15 seconds are a lot. However, the feedback isn't a single message but always a batch (a JSON document with an array of feedback) that contains more feedbacks from more devices. It's possible that the system tries to acquire more feedback as possible before sending them to the system.
Paolo.
I'm trying to create an azure application which can recieve messages on a TCP port. I have configured an input endpoint shown below :
Endpoint Name:GPRSEndpoint
Type:Input
Protocol:TCP
Port:10000
My azure worker role code looks like this:-
TcpListener listener = new TcpListener(RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["GPRSEndpoint"].IPEndpoint);
listener.ExclusiveAddressUse = false;
listener.Start();
while (true)
{
Thread.Sleep(100);
if (listener.Pending())
{
Trace.WriteLine("Incoming Request", "Information");
TcpClient c = listener.AcceptTcpClient(); //waiting for client to connect
Stream s = c.GetStream();
StreamReader sr = new StreamReader(s);
string text = sr.ReadLine();
if (text != null && text.Length > 0)
{
Trace.WriteLine("Saving GPRS Packets into Storage Table", "Information");
//Saving GPRS Packets into Storage Table
Site site = new Site();
site.GPRSPacket = text;
var insertOperation = TableOperation.Insert(site);
siteTable.Execute(insertOperation);
}
c.Close();
}
Trace.TraceInformation("Working", "Information");
}
}
And finally my client program looks like this:-
TcpClient c = new TcpClient();
Console.WriteLine("\nConnecting to Azure...");
IPAddress AzureWorkeraddress = IPAddress.Parse("168.63.239.54");
//String AzureWorkeraddress = "http://clienttcpcloud.cloudapp.net/";
//IPAddress AzureWorkeraddress = IPAddress.Parse("65.52.184.129");
c.Connect(AzureWorkeraddress, 10000); //Azure Worker Role's INPUT TCP Endpoint 168.63.239.54 or (http://clienttcpcloud.cloudapp.net/)
Console.WriteLine("\n<<<<<<<<<<<<<<<<<<Server Connected>>>>>>>>>>>>>>>>>>\n");
Console.WriteLine("Sending to Azure...");
Stream s = c.GetStream();
StreamWriter sw = new StreamWriter(s);
sw.WriteLine(text);
sw.Flush();
Console.WriteLine("\n\nGPRS Packet Sent!!!");
s.Close();
c.Close();
I've tried changing the port number to several values, but it still fails to respond. The error that i get is:-
**A Connection failed because the connecting party did not properly respond after a period of time, or the established connection failed, because connected host failed to respond 168.63.239.54:10000**
I really don't know what the problem is.....
There is a sample application at http://blog.maartenballiauw.be/post/2010/01/17/Creating-an-external-facing-Azure-Worker-Role-endpoint.aspx. Have you tried that and compared what it is doing to what you are doing?
I am trying to build a simple Web API REST service in Azure with a service bus queue worker on the back end. I can send a single message from the Web API to the worker just fine. However, I was trying to send more messages just to see how everything works. So, I created a simple controller that looks like this:
for (int i = 0; i < 100; i++)
{
var msg = new BrokeredMessage("Ping");
BioConnector.QueueConnector.OrdersQueueClient.Send(msg);
}
When I call the controller, I am only getting about 1/2 or so of the messages being received by the worker. The rest seem to be dropped.
I had issues with getting only about half the messages using the sample code posted here, so I wrote my own test code. I've tried it with > 100 queue messages and have always had 100% send/rec'd parity. Perhaps you had a similar issue with the code.
Create a new C# console project.
Add a reference to the Microsoft.ServiceBus assembly located in C:\Program Files\Microsoft SDKs\Windows Azure.NET SDK\2012-06\ref\Microsoft.ServiceBus.dll.
In the app.config, change it to this with your own values provided:
<appSettings>
<add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://blahblah.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=pDk0b....=" />
</appSettings>
Add these using directives:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
using System.Configuration;
using System.Threading;
Change the code method to the following:
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationSettings.AppSettings["Microsoft.ServiceBus.ConnectionString"];
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
QueueDescription queueDesc = new QueueDescription("TestQueue");
if (!namespaceManager.QueueExists(queueDesc.Path))
{
namespaceManager.CreateQueue(queueDesc);
}
QueueClient topicClient = QueueClient.CreateFromConnectionString(connectionString, queueDesc.Path);
int sentMsgCount = 0;
int recdMsgCount = 0;
for (int i = 0; i < 100; i++)
{
BrokeredMessage msg = new BrokeredMessage("Test message " + i);
topicClient.Send(msg);
sentMsgCount++;
Console.WriteLine("Sent Message: " + msg);
}
QueueClient subClient = QueueClient.CreateFromConnectionString(connectionString, queueDesc.Path);
bool moreMessages = true;
while (moreMessages)
{
BrokeredMessage recdMsg = subClient.Receive(TimeSpan.FromSeconds(3));
if (recdMsg != null)
{
Console.WriteLine("Received Message: " + recdMsg);
recdMsgCount++;
recdMsg.Complete();
}
else
{
moreMessages = false;
}
}
Console.WriteLine("# of sent msgs: " + sentMsgCount + ", # of rec'd msgs: " + recdMsgCount);
Console.Read();
}
}
This was a weird problem. Through a random walk through "trying things" I ended up changing the string name of the queue and then everything started working again. I didn't change anything but the name of the queue - no changes to any configuration parameters at all.
It appears to be something buggy with that particular queue on Azure.
Azure Service Bus provides durable messaging so you will not loose any messages. Some items to investigate further:
1) Is there another instance of the worker role that is pulling off messages from that queue
2) are you using peek-lock as the receive mode as that will be the only way to guarantee at least once delivery. Receive and delete mode does not have the guarantee
3) are the messages going into dead-lettered queue due to either message expiry or exceeding max delivery count, I.e. They are received but not completed several times
4) if none of the above apply then raise a support ticket and the Azure product team can investigate the symptoms because as I mentioned this is a durable messaging system so no messages will be "lost".
I had the WindowsAzure.ServiceBus NuGet package in my project and used QueueClient.Send() to send messages and faced the same messages lost issue.
My solution to completely solve the issue:
On the send side, I had to use REST API to send messages.
On the receive side, this is how I extracted the message body:
using (var stream = brokeredMessage.GetBody<Stream>())
{
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{
var msg = streamReader.ReadToEnd();
// Convert the JSON message to an object
// var obj = JsonConvert.DeserializeObject<ObjectType>(msg);
}
}