I've got some question about Azure Service Bus functionalities.
If I use PartitionKey in my Topic that will handle the order of the messages in that specific partition. I've found some articles about the problem ( https://github.com/Azure/azure-content/blob/master/articles/service-bus/service-bus-partitioning.md) but i just want to use simple Client.OnMessage method to handle the messages. Is there a way to handle this it a clear way or I need to use Session based message handling?
PartitionKey: If a message has the BrokeredMessage.PartitionKey property but not the BrokeredMessage.SessionId property set, then Service Bus uses the PartitionKey property as the partition key. If the message has both the SessionId and the PartitionKey properties set, both properties must be identical. If the PartitionKey property is set to a different value than the SessionId property, Service Bus returns an InvalidOperationException exception. The PartitionKey property should be used if a sender sends non-session aware transactional messages. The partition key ensures that all messages that are sent within a transaction are handled by the same messaging broker.
If the message always handle by the same message broker that not means inside the partition the order stay the same? I just want to handle this case.
Is there a way to replace / update a message in the Service Bus if the MessageId equals. Basically, if there is a message in service bus that get an update from my application and client not handled yet I just want to update that message. I know that is not a normal way of doing things in service bus architecture.
Related
I currently have an azure service bus topic that I'm subscribed to and want to implement retry logic based on the number of times a message has been on the topic. Is there a method in the Microsoft.Azure package that provides us with this information? Do I need to configure the message that is received by the C# service bus subscriber client to send that information? Do I need to change anything on the topic itself?
You can use the Message.SystemProperties.DeliveryCount property for that:
Number of deliveries that have been attempted for this message. The count is incremented when a message lock expires, or the message is explicitly abandoned by the receiver. This property is read-only.
(source)
If you ever switch to the newest SDK, Azure.Messaging.ServiceBus, it is the ProcessMessageEventArgs.Message.DeliveryCount property, see the docs
First of all, excuse my English, it's very bad. I am using MassTransit with Azure Service Bus for asynchronous communication between microservices. I need to use middleware consume filters to get metadata from message.
Currently I have several consumers that "consume" different messages, but all from the same receive endpoint. Each one of these consumers has its own "ConsumeFilter" (zero, one or more), which are filters for scopes of type IFilter<ConsumeContext> and are registered in the "ConsumerDefinition " class of each consumer, with the method .UseConsumeFilter(typeof(TFilter <>), context), with the intention that each consumer will only have its filter applied.
However, the filters must be "being added" to the endpoint receiver since when I receive a message, it goes through all the filters defined in all consumers.
Is it possible that regardless of whether all consumers are connected to the same receive endpoint, only the filters of their consumer are applied to each message?
Thank you very much.
Regards
Borja
If you have consumer specific filters, you have several options. You can create a filter that is either:
Specific to a message type ConsumeContext<TMessage>
Specific to a consumer type ConsumerConsumeContext<TConsumer>
Specific to a consumer and message type ConsumerConsumeContext<TConsumer, TMessage>
In the message-specific case, you can configure that on the receive endpoint. In this case, the filter executes before the consumer.
In the consumer-specific cases, you can configure those on the consumer configurator (the second argument to Configure, in the ConsumerDefinition). These would be invoked after the consumer has been created, but prior to dispatching the message to the Consume method.
I produced a video showing how each of these options works.
I am trying to use Azure EventHub in order to process messages and it works fine as long as I have one sender and one consumer.
I simple make my consumer listen to a specific Consumer Grooup and all is fine
Now the problem is when I send different types of messages that I want processed by different Consumer Group I dont see how that can be done
I am creating my sender like this
private static EventHubProducerClient eventHubClient = new EventHubProducerClient(eventHubConnectionString, eventHubName);
But I find no way to tell it what Consumer Group it should send to, it simple sends to hub itself and that hub has multiple resource groups
How do I decide what consumergroup gets this message?
I googled for hours without finding the way to "map" input messages from specific senders to a specific output Consumer Group
You cannot specify which message is sent to a specified Consumer group. Messages are sent to partitions, partitions are all included in each consumer group, you can check the diagram in this doc. The screenshot as below:
Now for you question: when I send different types of messages that I
want processed by different Consumer Group I dont see how that can be
done.
As a workaround, when you send messages, you can specify a property for each message. When read these messages from consumer group, you can also use the property to determine if you want to process it or abandon it.
Hope it helps.
I have a web service called S
My client have a web service called C
My client send a request to my web service (web service S)
Web service S will send a response to client ( C )
After that, my service (S) will create 1 invoice message and send it to client web service (C)
Client web service return result to my web service (S)
How to implement it?
As I understand, you want to return a response to client app, but still continue with some processing.
There are a few possibilities here:
Start a new thread in 2., that will create the invoice and send it to client WS. This however can be error-prone - your web service might die or be shut down in the middle of creating the invoice and client WS will never know.
Use something like hangfire to schedule invoice creation. Hangfire stores scheduled tasks in DB, so it will be eventually executed, even in case of failure. This does not require additional configuration other than setting up the backend db. Processing happens in the same hosting process of your Service.
Use a ServiceBus or MSMQ - the idea is simmilar as with Hangfire - you send a message (saying like "create invoice with parameters X") to the Bus, the Bus makes sure the message gets delivered to anyone that listens for it. Then you register a listener that would handle that kind of message and create the invoice. This would require more work, since you have to choose the Service Bus engine, take a moment to understand it, install, configure, etc.
This is a good case for a domain event. I don't know what the first request is - perhaps placing an order?
When the order is placed then you would raise an event indicating that an order was placed. The event could contain either some information about the order or a reference (id) that can be used to retrieve it. Then other listeners would respond accordingly.
One benefit is that it keeps different parts of your application decoupled. For example, the class that submits an order doesn't need to know that there's going to be an invoice. It just raises an event indicating that an order has been placed and then goes on its way.
That becomes even more important if you want to have multiple behaviors when an order is placed. Perhaps you also want to send an email confirming that your received the order. Now you can add that additional behavior as an event listener with no modification to the code that places the order.
Also, your application could grow so that perhaps there's another service for placing orders. (I'm running with "placing orders" although I don't know what the specific event is.) You don't want multiple points in your application that follow all of the post-ordering steps. If those steps change then you'd have to modify code in all of those places. Instead you just raise the event.
Here's a popular article that describes the concept well. There are numerous implementations of an event bus. Here's one.
In pseudocode, you could now have a few event handlers, each of which is completely decoupled from your ordering code.
The event itself is raised immediately after the order is submitted.
var order = SubmitOrder(info);
eventBus.Raise(new OrderSubmitEvent(order));
Then you have some event handlers which are registered to respond to that event.
public class SendInvoiceOrderEventHandler : IEventHandler<OrderSubmitEVent>
{
public void HandleEvent(OrderSubmitEvent e)
{
//e contains details about the order. Send an invoice request
}
}
public class SendConfirmationOrderEventHandler : IEventHandler<OrderSubmitEVent>
{
public void HandleEvent(OrderSubmitEvent e)
{
//send an email confirmation
}
}
Based on the processing of the incoming request I have to store the original (unserialized) message as string to a database.
So far I implemented a DispatchMessageInspector and a ServiceBehavior that I used to decorate my service implementation. My DispatchMessageInspector has a property to which I store the message string. My service implementation includes some business rules that check the request and if this check fails I'd like to store the original message.
How can I achieve to access the message string property of my DispatchMessageInspector from the service implementation in an elegant way?
You can add a Message Property containing the raw message in a form you like. Then in your service, you can access them through OperationContext.Current.IncomingMessageProperties["RawMessage"].