WCF duplex channel, de-coupling the request and the response - wcf

I'm contemplating a project where I'll be required to make use of what is variously called the "asynchronous" mode, or the "duplex" mode, or the "callback" mode of SOAP webservice. In this mode, the caller of the service provides in the SOAP header a "reply-to" address, and the service, instead of returning the output of the call in the HTTP response, creates a separate HTTP connection to this "reply-to" address and posts the response message to it. This is normally achieved in WCF using a CompositeDuplexBinding, like so:
<binding name="async_http_text">
<compositeDuplex clientBaseAddress="http://192.168.10.123:1234/async" />
<oneWay />
<textMessageEncoding messageVersion="Soap12WSAddressing10" />
<httpTransport useDefaultWebProxy="false" />
</binding>
This results in not one, but two HTTP connections per call: one from the client to the service, and then one from the service back to the client. From the point of view of the service implementation, nothing changes, you have a method that implements the interface method, and you take in the request and return the response. Fantastic, this is what I need, almost.
In my situation, the request and response can be separated by anything from minutes to days. I need a way to decouple the request and the response, and "store" the state (message, response URI, whatever) until I have enough information to respond at a later time (or even never, under certain circumstances).
I'm not terribly excited about having my methods essentially "paused" for up to days at a time, along with the required silly timeout values (if they're even accepted as valid), but I don't know how to go about putting a system like this together.
In order to be completely clear, I'm implementing a set of standards provided by a standards body, so I do not have flexibility to change SOAP message semantics or alter protocol implementations. This sort of interaction is exactly what was intended when the ReplyTo header was implemented in WS-Addressing.
How would you do it? Perhaps Workflow Foundation enables this sort of thing?

In such case don't use HTTP duplex communication as defined in WCF. It will simply not work because it is dependent on some other prerequisities - session, service instance living on the server, etc. It all adds a lot of problems with timeouts.
What you need is bi-directional communication based on fact that service exposes one way service and client exposes one way service as well (services can be two-way to support some kind of delivery notification). You will pass client's address in the first request as well as some correlation Id to differ multiple requests passed from the same client. You will call client service when the request is completed. Yes, you will have to manage all the stuff by yourselves.
If you are in intranet environment and your clients will be Windows based you can even think about changing your transport protocol to MSMQ because it has built-in support for all these requirements.
Edit:
I checked your updated question and you would call your communication pattern as Soap Messaging. I have never did it with WCF but it should be possible. You need to expose service on both sides of the communication - you can build your service to exactly follow needed contracts. When your service receives call you can use OperationContext.Current.IncommingMessageHeaders to access WS-Addressing information. You can store this information and use them later if you need them. The problem is that these information will not contain what you need. You have to fill them first on the client. This is generally possible by using OperationContextScope and filling OperationContext.Current.OutgoingMessageHeaders. What I'm affraid is that WCF can be "to clever" and override your changes to outgoing WS-Addressing information. I will probably try it myself during weekend.

It turns out the Windows Workflow Foundation (v4) does indeed facilitate this sort of message exchange.
Because WF allows you to decouple the request and response, and do basically whatever you want in the middle, including persist the workflow, idle it, and go outside and cut the grass, you get this capability "for free". Information can be found at these URLs:
Durable Duplex (MSDN)
Workflow 4 Services and duplex communications

Related

NServiceBus and WCF, how do they get along?

Simplified... We are using NServiceBus for updating our storage.
In our sagas we first read data from our storage and updates the data and puts it back again to storage.The NServicebus instance is selfhosted in a windows service. Calls to storage are separated in its own assembly ('assembly1').
Now we will also need synchronous read from our storage through WCF. In some cases there will be the same reads that were needed when updating in sagas.
I have my opinion quite clear but maybe I am wrong and therefore I am asking this question...
Should we set up a separate WCF service that is using a copy of 'assembly1'?
Or, should the WCF instance host nservicebus?
Or, is there even a better way to do it?
It is in a way two endpoints, WCF for the synchronous calls and the windows service that hosts nservicebus (which already exists) right now.
I see no reason to separate into two distinct endpoints in your question or comments. It sounds like you are describing a single logical service, and my default position would be to host each logical service in a single process. This is usually the simplest approach, as it makes deployment and troubleshooting easier.
Edit
Not sure if this is helpful, but my current client runs NSB in an IIS-hosted WCF endpoint. So commands are handled via NSB messages, while queries are still exposed via WCF. To date we have had no problems hosting the two together in a single process.
Generally speaking, a saga should only update its own state (the Data property) and send messages to other endpoints. It should not update other state or make RPC calls (like to WCF).
Before giving more specific recommendations, it would be best to understand more about the specific responsibilities of your saga and the data being updated by 'assembly1'.

when to use duplex service?

Well, I know that in a duplex contract the service can send messages to the client, but I would like to know when that is really useful.
I have a common application that send request to the service to get data from the a database, insert data... etc. Also, I need to store files about 40MB in the database, so I need a good performance. For this reason, I would like to use the net.tcp binding with transfer mode streamed, but the problem is that a net.tcp duplex service can't use the streamed transfer mode.
So I think I have some options.
1.- study if I really need a duplex contract for this kind of application. Perhaps in a chat application, for example, it has more sense a duplex contract because the server perhaps need to notify to the client when a contact is connected... etc. But in a common client that access to a data base, is necessary a duple contract? what kind of operations would can need a duplex contract?
2.- Other option it's not to have a duplex contract, but implement a no duplex contract in the server and other single contract in the the client, so when a client connect to the service, the service receive the needed information to connect to the service of the client. But, is this a good way to avoid a duplex contract?
3.- Really for my application I need tcp instead of a duplex HTTP that allows a streamed transfer mode? What is the advantages of the tcp over the HTTP in terms of performance?
Thanks.
You need duplex if you want to implement callback pattern. Callback means that client does not know when some event happens in server.
If you do not know when event happens you have two options to implement:
Polling - send requests every X minutes to check if event happened. Server should either return event details (if it happened) or return flag saying that you need to continue calling. Server also can return recommended timeout in advanced scenarios.
Callback - client sends some form of description what server should do if event happened. This may be pointer to function in C, delegate in .NET or endpoint schema in WCF. Server remembers that info and makes call from their side when time came.
As you can see duplex/callback means that at some point server works as client (initiates communication) and this is a big game change.
WCF duplex communications may require special network configuration because in many cases network allows you to call external services (you work as client) but forbids external resources to call you (external service works as client). This is implemented for security purposes.
Returning to your questions:
You do not need duplex if you only need to download big amount of data. You may need it if you want to catch updates that happened in server and notify clients. Duplex should work for Chat because in chat there are many scenarios when client needs to be notified with changes introduced by others.
What you described is hand-made variant of duplex channel. You should use proved and tested duplex implementation made by MS If you want server to call your method. Otherwise your option is polling.
You are right, you need tcp + streamed transfer mode to deal with big amount of data. TCP uses binary serialization which is more compact comparing to text serialization + with TCP you do not need to send any HTTP headers or SOAP envelops. Disable security if you do not need it. It has a big performance impact.
Addressing each point:
1, 2. I think that for your scenario a duplex service is an overkill. As you say yourself a duplex service is usually handy when both the client and service need to keep notifying each other on a constant basis, what you're doing, getting lots of data in/out of a database doesn't seem to be a good case for using duplex communication. Regarding netTcpBinding not allowing Streaming with duplex, you can just return a byte array (byte[]) instead of a stream. 40 MB is a lot, but I don't think Streaming will necessarily have a significant performance gain over a duplex service which will return a byte array (up to you to test each setup and compare the results). So you have a few options here, don't stream and return a byte array (you can do this with your duplex service) or you can just forget about making your service duplex since there doesn't seem to be a strong case for you to make it duplex and just return a Stream:
[OperationContract]
Stream RetrieveFile(long _fileId);
[OperationContract]
long SaveFile(Stream _stream);
3. netTcpBinding has a considerable performance advantage over HTTP bindings, but it comes with a price, mostly because its TCP ports are sometimes blocked by internet firewalls, although you can use netTcpBinding over the internet, it's not recommended. Choosing a binding depends on what you're looking to do, if your clients are going to consume your service over the internet, then netTcpBinding is not a good idea (blocked TCP ports, firewalls etc.), but if your clients are consuming the service in the same network (LAN) then netTcpBinding is the most sensible choice. wsDualHttpBinding (doesn't support streaming :#) is a good choice if you want to stick to a duplex service (equivalent of PollingDuplexHttpBinding in Silverlight), or any other HTTP based bindings if you let go of the idea of a duplex service.
Some articles that may help you out, performance comparison of various WCF bindings:
http://blog.shutupandcode.net/?p=1085
http://tomasz.janczuk.org/2010/03/comparison-of-http-polling-duplex-and.html
And about Streaming large data with WCF over HTTP, according to the authors, both samples have been tested with up to 2GB of data:
http://garfoot.com/blog/2008/06/transferring-large-files-using-wcf/
http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP
You shouldn't think that you must use netTcpBinding or you must use Streamed transfer for your service, netTcpBinding only becomes more performant than HTTP bindings after you enable throttling and configure some socket level properties. And streaming 40 MB will not have significant performance gains over buffered transfer. So you have a lot of options and a lot of trade-offs to make. There is no black and white and right or wrong, it's about how you customise your service to suit your needs best, most solutions will work. Your scenrio is a very common one and there are lots of stuff online about large data transfer in WCF, do more research ;)

WCF Keep Alive and Backup Strategy

Is that possible (using behavior and IClientMessageInspector.BeforeSendRequest) to change the comunication channel before send a message ?
I need to change this, because i have a backup/primary strategy for my proxy.
Based on your comment, it sounds like you want to be able to switch service endpoints in mid-call if the primary service is offline. I don't think there's any way to do that - at least not elegantly.
Once a communication channel is established, it's pretty much set until it is closed (or aborted). There's no way to switch it from one endpoint to a different (backup) endpoint - you couldn't even do it by creating a new channel because the proxy would still be using the primary endpoint.
Based on my understanding of WCF, about the closest you could come would be for the client to detect that the primary service was not responding (most likely through a timeout), and then it could switch to a proxy configured for the secondary/backup service.
Now, you might be able to, within IClientMessageInspector.BeforeSendRequest do some checking to see if the service is responsive, and if it does not response try to generate a new proxy with the backup service endpoint and send the message there...BUT I don't know if that would work, and even if it did it strikes me as a bit of a kludge.
Simplest solution is that the client simply switches to the alternate service endpoint if the primary endpoint is down, IMO.
Old thread, but for future reference.
I think WCF Routing (.NET4) is what you are looking for, namespace "System.ServiceModel.Routing.RoutingService". Search for "High Availability" on this page, Practical Messaging Scenarios with WCF 4, for an example.
From 1: "The back up list indicates to the Routing Service that if the primary endpoint, OneWayService1 is not available (i.e., it fails to respond), the Routing Service should try each subsequent endpoint beginning with OneWayService2 and ending with OneWayService4 until a service responds."

WebHttpBinding and Callbacks

I have asp.net site where I call my WCF service using jQuery.
Sometimes the WCF service must have an ability to ask user with confirmation smth and depend on user choice either continue or cancel working
does callback help me here?
or any other idea appreciated!
Callback contracts won't work in this scenario, since they're mostly for duplex communication, and there's no duplex on WebHttpBinding (there's a solution for a polling duplex scenario in Silverlight, and I've seen one implementation in javascript which uses it, but that's likely way too complex for your scenario).
What you can do is to split the operation in two. The first one would "start" the operation and return an identifier and some additional information to tell the client whether the operation will be just completed, or whether additional information is needed. In the former case, the client can then call the second operation, passing the identifier to get the result. In the second one, the client would again make the call, but passing the additional information required for the operation to complete (or to be cancelled).
Your architecture is wrong. Why:
Service cannot callback client's browser. Real callback over HTTP works like reverse communication - client is hosting service called by the client. Client in your case is browser - how do you want to host service in the browser? How do you want to open port for incoming communication from the browser? Solutions using "callback like" functionality are based on pooling the service. You can use JavaScript timer and implement your own pooling mechanism.
Client browser cannot initiate distributed transaction so you cannot start transaction on the client. You cannot also use server side transaction over multiple operations because it requires per-session instancing which in turn requires sessinoful channel.
WCF JSON/REST services don't support HTTP callback (duplex communication).
WCF JSON/REST services don't build pooling solution for you - you must do it yourselves
WCF JSON/REST services don't support distributed transactions
WCF JSON/REST services don't support sessionful channels / server side sessions
That was technical aspect of your solution.
Your solution looks more like scenario for the Workflow service where you start the workflow and it runs till some point where it waits for the user input. Until the input is provided the workflow can be persisted to the database so generally user can provide the input several days later. When the input is provided the service can continue. Starting the service and providing each needed input is modelled as separate operation called from the client. This is not usual scenario for something called from JavaScript but it should be possible because you can write custom WebHttpContextBinding to support workflows. It will still not achieve the situation where user will be automatically asked for something - that is your responsibility to find when the popup should appear and handle it.
If you leave standard WCF world you can check solutions like COMET which provides AJAX push/callback.

WCF Detect When Message First Arrives?

I have a self hosted WCF 4.0 service with an HTTPS endpoint. I have method that writes some trace info after the message comes in. However, some messages are 400k in size, so there is a long wait conceivably between when WCF has it and my console app has it. How can I get a hook or interception layer in there so I can at least know when a message is first coming in?
I think there is a WCF Performance Counter related to this, so there must be some way to know...
Thanks for all ideas!
This is not the same as Detect WCF client open channel operation , this is about knowing when the HTTP traffic first comes in. Maybe its not that I need to monitor things on my WCF service, maybe I need to monitor some other WCF layer that is intercepting HTTP. Can anyone say?
What about making a custom MessageEncoder that simply wraps the default implementation, but overrides ReadMessage() and logs some information before calling the wrapped implementation (which creates a Message instance)? At this stage the full message isn't even fully streamed over the wire, hence it's a very early point of the processing pipeline. Obviously, however, you don't know anything about the message yet. But if you want to get a timestamp, that might be a convenient place to get it.
One option is implement the IDispatchMessageInspector interface for your service with your message size checking code in the AfterReceiveRequest method override. Your code should look something like the code in this blog post.