Scaling out WCF, how to deal with callbacks? - c#

Suppose, I want to scale out (add more boxes) some WCF service. This looks pretty easy, set up load balancer that calls WCF services on multiple boxes using for example round robin algorithm.
However how to deal with situation when a WCF service have callback contract. When a client connects to some particular box, it receives events only raised by this computer WCF service instance. And I want client to receive events that were raised by any WCF service instance in group (cluster).
What is the best way to make WCF service know about events raised by other WCF service instances?
Some ideas: Multicast, broadcast, WCF NetPeerTcpBinding, Single server that subscribes to all WCF services in cluster (acting as event aggregate).
UPDATE: I have managed to create test system, using NetPeerTCPBinding as a mechanism to share events across servers. I haven't made a benchmark yet, but I feel that WCF P2P is to heavy for this tusk, I'm gonna implement UDP broadcast based event sharing system.

I would implement this by setting up a MSMQ queue that each server can subscribe to, and when an event occurs that the other servers need to know about, the service can publish it.
I use a library called NServiceBus to make this entire process simple. NServiceBus is a full-featured library that uses MSMQ (among other transports) to create pub/sub messaging buses, which would exactly solve your problem. It is easy to use and has a fluent interface for configuration, subscription, and publishing.
I will come back and edit this post later with an example, but the NServiceBus website has plenty of documentation to get you started until then.

Have you considered messaging? Sounds ideal.

Related

Publish/subscribe with Azure Service Bus

I have a Microservice (Web API), that publish messages to a Topic (Topic A).
Now I have another Microservice (Web API) that should subscribe to this topic and act upon the messages.
My question is simply: How should I do this since my Microservice that should subscribe to the Topic is a WebApi? In my web api, I want in somehow instantly know when a new message is available in the Topic. Should I poll the service bus via an endpoint?
I'm uncertain about the best practices about this.
All examples that I have seen using console applications to subscribe. But that's not my case since I have an web api.
There are different ways of doing this.
1. Using Azure Functions
This way you create two applications. Your standard web api, and separately you create an Azure Function that will handle the messages from the queue. There multiple benefits of this approach, on of them is that you are isolating the code handling the queue, so if you have many messages, it will not affect the performance of your API
2. Using a Singleton service inside your web application
The idea here is that your API application is handling queue messages in the background. This has the advantage that you have only one application doing everything, simpler to maintain for example. It has the disadvantage that a very big inflow of messages will slow down your APIs.
(Note, in the link above look for Consuming messaging from the Queue
Whether is a WebAPI or a console, it is the responsibility of the consumer to communicates and collect records. Being a WebAPI doesn't mean that it should only have public endpoints. Typical WebAPI, might have public endpoint (for external world) or can have private endpoints (for internal communications) or can have a combination of both. The responsibility of private endpoints could be reading data from service data-store, consuming external services via adapter services etc. In your case, upon initialization of your WebAPI, you might want to create a consumer object and start reading data and process as you want. Hope this help.
You can poll in a Web Job or background task. But the built-in way to do this is with an Azure Function triggered from the Topic, or with Azure Event Grid.
For listening in the background you can use IHostedService. Inside Method StartAsync
you can register message processors;
queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions)
And on StopAsync you can stop processing messages and close the client.

MVC - WCF - RabbitMQ - Domain Event via Message Queue to Consumer speedup or alternatives?

Domain Driven Design Passing Events to separate Bounded Contexts
A user action in MVC should generate an Event which is passed to a remote (same LAN) Event handler.
What I've tested:
MVC: fire and forget service call (asynchronous) ->
(IIS hosted) WCF which gathers data and populates a message ->
Sent via EasyNetQ/RabbitMQ ServiceBus ->
The event is consumed by a Subscriber (using a DI container initialized from a WCF service endpoint) which handles the event & it's data.
I did some testing to see how it works if the service is called fairly quickly by looping in the MVC side
for (int i = 0; i < 200; i++)
{
...
client.MyServiceMethod(someId, startDate);
...
}
The MessageQueue part is quick, based on the timestamps it is sent to the queue and received by the subscriber within the same second. Looping through the WCF service calls is very slow. It takes many seconds to loop through them. I tried switching from wsHttpBinding to netTcpBinding, and playing with the serviceThrottling in WCF.
WCF isn't compulsory, but it seems like a separate event handling project (on the publisher end) would be beneficial and could be physically located elsewhere from the MVC app (load reduction etc.). Is WCF plausible for a situation like this, or should I try using Windows services or some other self-hosted e.g. console app etc, or potentially using a thread in MVC to generate the event data, or are there better scenarios? What are the best practices in this type of Event handling system? Basically it seems like it would be beneficial to have something generating the Event data since it has to be handled somewhere while not slowing down the UI that the end user is using.
Instead of trying to roll your own infrastructure like this, I think you would do well to employ a tool like NServiceBus (not free) or MassTransit (free). (I would consider this best practice.)
I can't speak for MassTransit, but my experience with NServiceBus has been very good. You only need to specify which messages go to which queue. You can use several different queueing technologies, but I would recommend starting with the default MSMQ implementation. No WCF configuration nightmares necessary. ;)
All of your message handlers will also be automatically wrapped in a distributed transaction so that if a DB interaction fails, the entire message will be rolled back and you'll be able to try the message again in the future.
If I undertood well, your event creation process is "heavy" and you want to avoid to be created in the MVC process. I guess you are sending some information to the WCF service in order to let him prepare the event.
You could think of a 2 consumers scenario avoiding the WCF step:
Your MVC application creates and publish a "light" event with all data required in order to create the "heavy" event (basically with the input data you would pass to WCF)
An EventCreator subscriber consumes this message and prepares the heavy event
Your already existing consumer will then consume the heavy event
EasyNetQ already provides simple functions to publish and consume the message.
Most of the tutorials you find online suggest using TopShelf for hosting your consumers in a console application (debug) or windows service (production). EasyNetQ has an example here: EasyNetQ with TopShelf
If you want to "hide" the EasyNetQ dependecy on your MVC project, you could wrap the EasyNetQ IBus to a custom Bus and use an IoC container in order to inject a specific implementation of your bus. The example provided above uses Castle.Windsor as IoC container

why is wcf duplex required?

WCF duplex performs a callback after a method has run on the server that then runs code on the client.
If i want to execute a method on the client from the server at the push of a button on the server then i don't think WCF duplex is appropriate.
Why would i not just create a client and a server at each end of my 2 applications?
I was one of the people that commented on your previous question so I probably owe you an answer here :o)
You have posted rather a lot of code and I have not looked at it in detail. However, in general terms, there is a reason for using wsDualHttpBinding and duplex contracts in general instead of more of a peer-to-peer approach where you have services on both sides, as follows:
The duplex approach is appropriate where you have a clearly defined server that is running permanently. This provides the hub of the interaction. The idea is that clients are in some way more transient than the server. The clients can start up and shut down or move location and the server does not need to be aware of them in advance. When the client starts up, it is pre-configured to know where the server is, so it can "register" itself with the server.
In contrast, the server does not need to be preconfigured to know where the clients are. It starts up and can run independently of any clients. It just accepts "registrations" from all clients that have valid credentials whenever they come online, and can continue to run after the client goes offline. Also, if the client moves, it just re-registers itself with the server at its new location.
So the server is in some sense a more "important" part of the system. No client can participate in the communication without the server, but the server can operate independently of any client.
To do this with WCF duplex service, you have to do some extra work yourself to implement the publish/subscribe behaviour. Fortunately, the MSFT Patterns and Practises team have provided some guidance on how to do it
http://msdn.microsoft.com/en-us/library/ms752254.aspx
This is fundamentally different from a genuine peer-to-peer approach where there is no well-defined hub (i.e. server) for the network and each node can come and go without affecting the overall functioning of the network.
WCF Duplex is used when you have a Publish/Subscribe setting (also known as the Observer Pattern). Let's say you have a service that subscribes for notifications of some sort (e.g. new email). Normally, you would need to check periodically for updates. Using WCF Duplex, the subscriber can be notified automatically by the publisher when there are updates.

WCF Service dependencies

I have three wcf services A,B and C respectively ,since i wanted it to be SOA(Service Oriented Architecture) the way my setup works is when i send a request from client to server.
All the services are self hosted windows services.
Client sends request to service A (client has no clue about the other services B and C);
Service A eventually sends that request to Service B and Service C.
Service B and C sends response back to Service A which would be sent back to the client by service A.
Issue i m facing :If i make any changes in the code of Service B and rebuild and restart the service ,i am having issue getting the response back but when i restart all the remaining services then it works fine.
In other words my client doesn't get the response back unless i restart all the services(A,B and C) even though i just changed the code in only one service and rebuilt it.I know the thing works if i restart all the three services but i want to know is this the problem in my way of designing or it is something i have to deal with self hosted windows services.And all the services(A,B,C) are independent as none depends on each other.
Did some one ever see such things happened in SOA.I would be glad if some one can guide me to appropriate solution ?
Replace WCF between services with any sort of queue (one service publishes something, other can read when they are ready). Can be anything. Can be a simple table where you read from if there is something new. Can be RabbitMQ, NServiceBus, etc, whatever works for you.
Define messages you put into the queue: commands and events. Both are simple classes with properties, no logic there. Commands represent what the system is asked to do (RegisterUser, PlaceOrder, ect), events represent what the system has done (UserRegistered, OrderApproved, PaymentReceived, etc). Be explicit about actions, Don't do something like "I have changed all the properties of a user on the client, now I call SaveUser(user)". Your service supposes to know how to change objects, clients should only command what to do.
Never break your contract. It is easy, easier than it sounds: you can add things to your message contracts, but cannot remove. In other word you just keep your contract backwards compatible.
Now you have a much better design: services communicate only through messages in queues, messages are backward compatible. This means that you can stop any of the services at any time without impacting others: they will continue sending messages into queues, and when the stopped service comes back again it will catch up processing all the stuff from the queue.
Then, if you want, you can use the same approach with client interactions: if instead of calling WCF clients would only put their commands in some sort of a queue then service upgrades or other downtime would not impact user experience.
Example: if I use WCF to place an order or to put an item into a shopping card then if there is a problem or a service is down for maintenance I will not be able to do it. I would click a button and have a nasty error. More importantly my order will not make into the system.
In contrast, if there is a queue in the middle, I only put my command into the queue. Now even if my service is down at the moment, or experience a high load (and therefore slow) then my user experience is still the same and does not degrade. It is just my command will be processed a bit later, but as a client I don't really care. And my order will not be lost in this scenario. The system became fault-tolerate and self-balanced.
There are all sorts of fantastic tricks you can do if you simply put a queue in the middle instead of experiencing problems with spatial and temporal coupling that comes with WCF :)
And what I described is just the beginning... :)
You may want to consider using a service bus such as NServiceBus to help you accomplish your functionality.
The first issue it will help you address is the decoupling of your services via publish/subscribe messaging pattern. Rather than invoking web services in one or the other service, publish events that notify the respective services when something has occurred. In your case this would look something like this:
Client invokes web service in Service A.
Service A publishes a message "Client Command Received" which Service B and C subscribe to.
Service B and C handle this event and then publish events of their own.
Service A subscribes to both events and replies to the client.
The first and immediate benefit of using something NServiceBus is reliability. On top of that you are able to easily version your message without affecting your client or your respective services. NServiceBus has full WCF integration so your client can continue to send messages to your service as before.
One of the things that makes your scenario interesting is that you can't guarantee when Service B and C send their responses back to you. Do you keep the connection to the client open until Service has received their responses? Do you need both responses before you can send a the client its response? What happens if either or one of the service crash? What if there is a time limit to how long you can wait before a response is received by Service A? All of these questions and more can be answered with a feature in NServiceBus called Sagas. Check it out.
If using NServiceBus is not possible then things become more difficult. WCF doesn't support publish/subscribe out of the box so you will have to bake your own. At a minimum I would recommend using this to decouple your services. How you manage state and temporal coupling in your services is another matter. Save yourself the trouble.
There are other frameworks out there but if you want a developer centric, cost effective way to create a .NET based solution then recommend using NServiceBus.

Subscribing to MSMQ over the internet

I haven't been able to find a clear answer to this problem. Is there a good way to subscribe to a MSMQ through the internet? Ideally I need security both in authentication and encryption for this connection. But I would like the subscriber to act just like any other client that would be subscribed on the local network. I believe I have a couple of options here
Expose the MSMQ ports publicly
Put the MSMQ behind some type of WCF service (not sure if that works for a subscriber)
What other options do I have? We're sitting in a .NET environment and the main problem domain that is trying to be solved is to change the remote connections from a pulling system to an event based system to reduce the load on the main server.
One way is to use a queue ON the Internet.
I work at Microsoft and my team owns MSMQ and we also own the Windows Azure Service Bus service. For the scenario you describe you may want to take a look at using a Service Bus Queue, which has not only the advantage of being reachable for Internet senders but also eliminates the need to create inbound firewall rules on the receive side.
More here: http://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-queues/
The most natural option will be to use MSMQ over http, which is a feature of MSMQ:
http://msdn.microsoft.com/en-us/magazine/cc164041.aspx
The alternative would be to create an http WCF service possibly with duplex polling and use WS-Routing to an MSMQ WCF service.
Checkout the Gateway feature of NServiceBus.

Categories

Resources