Wednesday, September 16, 2009

Scale-out of Silverlight HTTP polling duplex WCF service in a web farm scenario

Introduction

In my recent articles I have introduced a sample pub/sub application using Silverlight’s HTTP polling duplex protocol, an AJAX client talking the same protocol, as well as discussed server side performance of the protocol. The latter post pointed out scalability challenges associated with deploying a WCF service using the Silverlight HTTP polling duplex protocol in a web farm scenario. This article introduces one possible solution to the scale-out problem, enabling an applications utilizing the protocol to accommodate an arbitrary number of concurrent clients through scale-out of the backend infrastructure.

The source of the scalability limitations of Silverlight 3 PollingDuplexHttpBinding on the server is the sessionful nature of the WCF channel the binding creates, which requires in-memory state to be maintained for the lifetime of the session. Specifically, there are two problems associated with hosting such a service in a practical scale-out scenario in a web farm:

  1. Backend affinity. Subsequent calls from the same client session must be directed to the same web farm backend by the network load balancer (NLB). Oftentimes (in particular in third-party hosted scenarios) the user does not have the level of control over the NLB configuration to ensure backend affinity.
  2. Backend recycling. An application hosted in a web farm should not rely on any transient state maintained on a backend instance between subsequent client calls – the backend can be recycled and recreated at any time between client calls. In particular, any in-memory state may be lost, including the in-memory WCF session state.

The approach to solve these challenges described here suggests the WCF service handles the HTTP long polls explicitly and maintains the sessionful state in a scaled-out backend infrastructure, therefore avoiding any in-memory state that spans subsequent client calls on the web front-end , and not requiring backend affinity from the NLB. In order to describe this approach, one must first understand the mechanics of the Silverlight HTTP polling duplex protocol.

Silverlight HTTP polling duplex protocol

The Silverlight HTTP polling duplex protocol has been designed to enable data push from the server to the client while optimizing for the web browser client environment. Web browsers typically enforce a limit on the number of concurrent TCP connections to a single web server to make denial of service attacks on that server harder. For example, Internet Explorer 8 by default allows 6 TCP connections (equal to the limit of concurrent HTTP requests) to a single backend host. A Silverlight application hosted in a web browser is subject to these limitations.

A single Silverlight application enables multiple logically distinct duplex sessions to be established with a single backend using the WCF duplex session channel abstraction. A session in this protocol involves two independent mechanisms for sending messages from the client to service and from the service to the client. Messages from the client to service within a particular session are sent using individual, short lived HTTP requests, followed by empty HTTP responses from the server. Messages from the server to the client within a particular session are sent using an HTTP response to a long lasting HTTP request the client makes to the server (the “long poll”). The client side implementation of the polling duplex protocol ensures that the server always has such pending HTTP request available; as soon as the server sends a message to the client using the response to the long poll, the client issues a new long poll.

One implication of the long polling mechanism is that at any point in time one TCP connection between the client and the server is dedicated to the long poll. If multiple duplex sessions between a Silverlight application and the server were to issue their individual long polls, the browser connection limit would quickly be reached, preventing other communication. Therefore, a single long poll request per backend server is shared across all logical duplex sessions within a single Silverlight application. This ensures that only one TCP connection from the browser connection limit is utilized for the polling duplex protocol at any time. The polling duplex protocol on the server side multiplexes the messages for multiple sessions over that single long poll. Similarly, the protocol on the client dispatches the messages received over the single long poll to appropriate logical session on the client. The protocol is based on the WS-MakeConnection specification.

Silverlight HTTP Polling Duplex Protocol 

The server side of the protocol maintains an in-memory queue of messages to be sent to a particular client, abstracting the existence and handling of the long polls away from the application layer. While this allows the connection between the client and the server to be modeled as a WCF IDuplexSession channel on the server, it imposes the scalability issues associated with maintaining in-memory state. In a scenario where the server is scaled out to multiple instances behind a load balancer without backend affinity, it is possible that subsequent long polls from a single client will reach different instances of the backend. In particular, it may reach an instance that does not maintain the message queue for the client issuing the long poll. In addition, a recycled backed may loose the in-memory message queue.

Enabling scale out of the polling duplex backend service

The approach to enabling scale out of a backend service using the polling duplex protocol relies on removing the polling duplex layer of the protocol from the server and relying on the application implementing equivalent logic directly on top of the HTTP protocol. In particular, this approach implies the application must explicitly handle the long polls from the client, understand the one-to-many relationship between a long poll and a logical session, as well as provide a scalable store for messages to be sent to the client(s) accessible from all instances of the backend.

Scaleable Silverlight HTTP Polling Duplex Protocol

These are the key implications of such a refactoring of the server:

  1. The service contract of the WCF service changes from duplex to simplex. The service is now exposed directly over HTTP and as such consists of request/response service operations.
  2. The service contract must contain an operation contract for handling the long polls from the client (let’s call it a “MakeConnect” operation following the naming from WS-MakeConnection specification).
  3. All service operations except MakeConnect must be one way. This means the operations do not return any application level response to the client (an empty HTTP response is sent). If the service has any messages to send as a result of processing the client call, it needs to use the long polling processing logic to do so. Typically this would involve storing the message to be sent to the client in a scalable backend storage to be picked up by the long poll processing logic in due time (this is depicted as the dotted arrow on the diagram above).
  4. Given the the wire format of the protocol remains unaffected, existing clients continue to function without any changes.

Doing all of the above may appear a daunting task at first, but with the appropriate choice of technologies on the backend and a few helper classes I am going to show it is not hard at all.

Show me the code

I am going to use the pub\sub sample using the Silverlight HTTP polling duplex protocol I wrote about before as a starting point, and describe the steps that were necessary to convert the WCF backend to a scalable, web-farm friendly implementation. It is a good idea to read about and run the original sample to understand its functionality before moving on. The Visual Studio solution containing the complete pub\sub sample after conversion is available for download.

The converted VS solution contains a new project called Microsoft.ServiceModel.PollingDuplex.Scalable, which includes helper classes and methods that facilitate the conversion of an arbitrary duplex WCF service to a service exposed over the Silverlight polling duplex binding. The key components and conversion steps are described below.

Service contract change from duplex to simplex

The IPollingDuplex service contract from Microsoft.ServiceModel.PollingDuplex.Scalable project enables explicit handling of long polling messages by the service implementation:

[ServiceContract]
public interface IPollingDuplex
{
    [OperationContract(
        AsyncPattern = true,
        Action = "http://docs.oasis-open.org/ws-rx/wsmc/200702/MakeConnection",
        ReplyAction = "*")]
    IAsyncResult BeginMakeConnect(MakeConnection poll, AsyncCallback callback, object state);
    Message EndMakeConnect(IAsyncResult result);
}

[MessageContract(WrapperName = "MakeConnection", WrapperNamespace = "http://docs.oasis-open.org/ws-rx/wsmc/200702")]
public class MakeConnection
{
    [MessageBodyMember(Name = "Address", Namespace = "http://docs.oasis-open.org/ws-rx/wsmc/200702")]
    public string Address { get; set; }
    // …
}

The contract is intentionally asynchronous, as handling of long polls is by definition a blocking operation (and likely asynchronous itself depending on the technology used for storing the messages the server needs to send to the client). This contract enables the server to receive the long poll and respond with an arbitrary message back (the response must target one of the logical sessions associated with the client who made the long poll request).

A service that wants to implement the polling duplex protocol in a scalable manner must have service contract derived from the IPollingDuplex service contract above. In addition, the application service contract must be simplex (as opposed to duplex). For example, this is the service contract for the pub\sub service from the original sample:

[ServiceContract]
public interface IPubSub : IPollingDuplex
{
    [OperationContract(IsOneWay = true)]
    void Subscribe(string topic);

    [OperationContract(IsOneWay = true)]
    void Publish(string topic, string content);
}

Notice the callback contract is gone, as well as the Subscribe and Publish operations are one way: the notifications to clients are now sent in the form of a response to the IPollingDuplex.MakeConnect call.

Implementing MakeConnect

IPollingDuplex.MakeConnect operation receives the MakeConnection message which contains the unique address of the client making the request in the MakeConnection.Address property. The implementation should determine if there are any notifications to be sent to any of the sessions associated with this client (the model assumes 1-N relationship between a client and a logical duplex session with the client, as described before). If there is a notification to be sent to one of the sessions, the response message should be constructed in two steps: first create an instance of the message with the desired action and payload:

Message response = Message.CreateMessage(MessageVersion.Default, “uri:someaction”, somePayload);

(The message format and action must of course match what the client expects to receive given its service contract).

And then the polling duplex protocol SOAP headers need to be added to the message to indicate which of the sessions on the client this notification should be dispatched to. There is a helper method on the MakeConnection class to make it easy:

MakeConnection poll;
string sessionId;
response = poll.PrepareRespose(response, sessionId);

MakeConnect implementation should hold onto the request without responding for a specific time (e.g. 15 seconds) even if there are no notifications to be sent back to the particular client. If after that time there is still no notification scheduled to be sent for any of the sessions on the client, the implementation of MakeConnect should respond with an empty HTTP 200. This is made easy with a call to MakeConnection.CreateEmptyResponse():

MakeConnection poll;
Message response = poll.CreateEmptyResponse();

Accessing session information from “application” service operations

Application service operations other than IPollingDuplex.MakeConnect (e.g. Publish and Subscribe in this sample) must have access to the client and session information from the polling duplex protocol. For example, the IPubSub.Subscribe method needs this information to register a particular client+session to receive notifications related to a particular topic. The IPubSub.Publish method may need this information to avoid sending a notification back to the client+session that has just invoked the Publish method.

The way to get at the session information from an incoming application message is to call an extension method on the OperationContext (the method is implemented in the Microsoft.ServiceModel.PollingDuplex.Scalable project):

PollingDuplexSession incomingSession = OperationContext.Current.GetPollingDuplexSession();

The PollingDuplexSession contains two identifiers that uniquely identify the client and the session on the client:

public class PollingDuplexSession
{
    public string Address { get; set; }
    public string SessionId { get; set; }
}

The PollingDuplexSession.SessionId is the same identifier as the MakeConnection.PrepareResponse method requires (note that MakeConnection class already knows about the client’s address).

Exposing the service

The simplex service can now be exposed directly over an HTTP binding as opposed to polling duplex sessionful binding:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="PubSub">
        <httpTransport/>
      </binding>

    </customBinding>
  </bindings>
  <services>
    <service name="Microsoft.Samples.Silverlight.PollingDuplex.Service.PubSubService">
      <endpoint address="" binding="customBinding" bindingConfiguration="PubSub"
       contract="Microsoft.Samples.Silverlight.PollingDuplex.Service.IPubSub" />
    </service>
  </services>
</system.serviceModel>

Scalable server side storage for messages to be sent to the client

The approach described here removes the in-memory queue the server side implementation of the polling duplex protocol maintains for storing messages the server needs to send to the client. Instead, the application code must now decide where these messages are stored and how the store is queried from within the IPollingDuplex.MakeConnect implementation. There are a few requirements the store technology must meet in order to ensure scalability:

  1. The store must be accessible from all scaled-out instances of the WCF service.
  2. The store should provide an asynchronous mechanism of querying for data to avoid blocking the thread on which the WCF service received the MakeConnect call. The entire purpose of making the IPollingDuplex contract asynchronous is to optimize system resource use during processing of the long poll, which is by definition a long running, blocking operation.

The sample code of the solution stops short of recommending a particular backing store. In fact, it uses a mock up of the store that is in-memory based, which means the sample would not even scale out as is. However, it provides a good demonstration of the refactoring steps specific to the protocol itself.

Aleksey Savateyev, a colleague of mine, has taken this sample to an entirely different level by prototyping a pub\sub solution that uses Windows Azure Queues as the backend storage, and allows scale-out of the polling duplex WCF service using the pattern described here to an arbitrary number of web roles in the Windows Azure platform. Aleksey promised to blog about this approach, so check out Aleksey’s site.

51 comments:

  1. Hi Tomasz

    This looks a great solution. The only issue I see is that if you change the contract so for instance add a method to IPubSub it's not possible to re-generate the client proxy through visual studio as it doesn't generate the DuplexContract client side. Is there anyway to get around this issue that you know of?

    Thanks

    ReplyDelete
  2. Andy, unfortunately out of the box proxy generation or re-generation based on metadata is broken with this approach, since it modifies the server side contract. An approach to updating the service reference during development is to keep a side-by-side duplex service contract and expose a mock up service implementing it with an endpoint based on the polling duplex binding, just for the purpose of proxy generation. If proxy generation is desired as a feature offered to third parties after the service has been deployed in production, one possible approach is to expose a fixed WSDL and XSD document(s) at a known address.

    ReplyDelete
  3. Excellent article.

    Are there any limitations for using this kind of solution in secure communication scenarios (https transport + web farm)?

    ReplyDelete
  4. This approach should work the same way for HTTPS and HTTP. Please note that as of Silverlight 3 the TLS\SSL negotiation, server authentication, and client X.509 certificate provisioning (if client authentication is requested by the server) are fully controlled by the browser hosting the application. Silverlight application controls security only to the extent of controlling the transport scheme (HTTP vs HTTPS). Optionally, the WCF client proxy may attach a username/password security token using WS-Security mechanisms when HTTPS transport is used.

    ReplyDelete
  5. Amazing post... thanks so much for sharing.

    ReplyDelete
  6. Can you explain why someone with a great message store cannot just use it instead of in-memory in the original solution?

    ReplyDelete
  7. This is an interesting idea. An approach where one replaces the in-memory queues maintained at the polling duplex channel level with a distributed store should be feasible. In fact, it would allow the service to continue using the duplex service contract, as the shape of the service contract could remain unchanged. Flow control is one challenge such approach would have that does not exist in the solution described here: the server would not have immediate visibility into whether the client is still polling for the messages, and therefore the server does not know when to terminate the logical session to stop sending messages to the client. Another consideration is that a session representation of the same logical session could be created simultaneously on several web farm instances depending on the load balancer behavior. In general, however, such approach is very much worth considering.

    ReplyDelete
  8. Hi!
    Firstly, thank you for your HTTP polling duplex series articles, it is very interesting and useful to me :)
    About "the mechanics of the Silverlight HTTP polling duplex protocol", as you said "Messages from the server to the client within a particular session are sent using an HTTP response to a long lasting HTTP request the client makes to the server (the “long poll”). The client side implementation of the polling duplex protocol ensures that the server always has such pending HTTP request available". I wonder how HTTP polling duplex protocol act when a user subscribe to a topic, then its internet connection is lost for a few seconds and up again. Do that user still possible receive notification messages later? What happens when notification messages arrives exactly at the time the internet is dropped? Does the internet drop causes the long lasting HTTP request between client and server dropped too? Because i think it is very easy for my customers with not so good adsl drops internet for a seconds like that

    Thank you!
    Your sincerely!
    Duc To

    ReplyDelete
  9. Duc To, the bottom line is that the HTTP protocol does not provide any delivery guarantees, and polling duplex protocol inherits lack of this assurance. If your application requires delivery guarantees, you should take appropriate measures at the application level to provide it (for example, retries). When a TCP connection underlying an HTTP long poll is dropped, all WCF duplex session channels tunneled through that long poll request (i.e. all channels created to the same server scheme/host/port combination) will be faulted. The application logic on the client should ensure the channels are re-created if it is desired. Please also note that HTTP proxies sometimes decide to terminate inactive TCP connections, which will cause the behavior above. A mitigation built into the polling duplex protocol uses the ServerPollTimeout (default of 15 seconds) as a maximum period after which the server will respond to the long poll even if there are no messages to send to the client. Setting the ServerPollTimeout to a lower value will reduce the risk of dropped connections at the cost of increased network traffic.

    ReplyDelete
  10. Many thanks, Mr. Janczuk.. Very informative and full-fill answer :)

    Your sincerely!
    Duc To

    ReplyDelete
  11. Hi, First your article is amazing, and solves a real problem with the polling duplex. Thank you for sharing it. We have implemented your solution with database storage solution (SQL server 2005). We followed a similar layout of the tables to the ones you have in-memory. Everything worked as expected, however the performance was horrible. It took almost 2 seconds for a notification to get to the client. First we felt that it was the database connection that was the problem, but it wasn’t. The issue was we needed to simulate a long poll, the same way you use a WaitHandle.Wait() until a message arrives, once we used a database we couldn’t use this method anymore. The only way to simulate the long poll was to keep checking the database (polling the database), and in our case we only checked it once, so we didn’t really have a long poll scenario. Trying to have a long poll with the database was moving the polling problem to the database. I am looking for a storage that will notify me when a message arrives. I was thinking of using message queues, but I would need one queue per client connection… (which does not make sense). We can not use Azure, we need something on the network. Any ideas how to solve this scalability issue regarding the storage?

    ReplyDelete
  12. If the latency of polling a SQL database is unacceptable in your scenario, using Azure queues as the backing store would be very unlikely to help you anyway. One way to reduce the latency is to use an in-memory distributed cache to store the messages. You may want to check out the Velocity project (http://msdn.microsoft.com/en-us/data/cc655792.aspx) which is a technology addressing the very need of efficient sharing of data across nodes in a farm.

    ReplyDelete
  13. I was a bit skeptical about HTTP polling but have been pleasantly suprised with how well the PollingDuplex channel works. Previously I used a TCP socket connection for my notifications but when the time came to encrypt the communications things got a bit more complicated with the additional plumbing and it was significantly easier to use the PollingDuplex channel over SSL.

    One question I have is how can I return a SOAP fault in EndMakeConnect so I can use e.Fault on the client? I've tried Message.CreateMessage with different permutations of MessageFault but I always generate an InnerChannel fault whereas I'd like to catch the error in the NotifyReceived handler.

    ReplyDelete
  14. Hi. I'm trying your code, but I got some errors when I compiled it after some changes I did. I was looking at Reference.cs, and I figured out it is not generating the same code for the reference (I mean, it doesn´t have CallbackContract section in header ServiceContractAttribute. Here is a sample of the code of the generated reference:

    //------------------------------------------------------------------------------
    // auto-generated
    // This code was generated by a tool.
    // Runtime Version:2.0.50727.4200 >>> Your version is 2.0.50727.4918
    //
    // Changes to this file may cause incorrect behavior and will be lost if
    // the code is regenerated.
    // /auto-generated
    //------------------------------------------------------------------------------

    namespace WebApplication1.ServiceReference1 {


    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IPubSub")]
    public interface IPubSub {
    ... etc

    As u can see, it doesn't have CallbackContract in header. Any suggestions? Thanks in advance for your help.

    ReplyDelete
  15. Alexis, please check the first two comments to this post, I believe I already answered a similar question before.

    ReplyDelete
  16. I was considering writing something close to this solution, but I have to say you've done an excellent job thinking this through and explaining it.. Well Done!

    ReplyDelete
  17. I can't understand, why, but In some time silverlight stops sending requests to server. Maybe it is because server sends big requests, something like 30Kb. The connection lives for just 4-5 minutes, sometimes more, and then it dies. Could you please explain this?

    ReplyDelete
  18. I've seen the same as 3axap - it's very strange that Silverlight just stops sending requests. Could it be anything to do with the silverlight plugin being suspended if the browser is not the active application???

    ReplyDelete
  19. Hey Tomasz, thanks for the great info here. I want to address Andy's issue for proxy generation for the duplex service.

    The problem usually arises in WCF when an Interface inherits from another Interface. In this case: IPubSub inherits form IPollingDuplex, which is then implemented in the PubSubService class.

    To fix the auto proxy gen, remove the IPollingDuplex inheritance to IPubSub and then move it to PubSubService class instead, like this:

    public class PubSubService : IPubSub, IPollingDuplex { .... }

    This should solve the problem.

    Cheers!

    Nasir Aziz

    Andy said...
    Hi Tomasz

    This looks a great solution. The only issue I see is that if you change the contract so for instance add a method to IPubSub it's not possible to re-generate the client proxy through visual studio as it doesn't generate the DuplexContract client side. Is there anyway to get around this issue that you know of?

    Thanks

    September 20, 2009 1:32 PM

    ReplyDelete
  20. I'm having trouble with this. Everything works fine except

    e.request.GetBody().Content

    My client does not see NotificationData.

    ReplyDelete
  21. Thanks for some really great posts!

    How would you modify your "scaled-out" version to use JSON encoding instead of SOAP? I'm putting together a web service that will service iPhone applications, and JSON-over-HTTP looks like the best approach for that platform.

    Thanks in advance!

    ReplyDelete
  22. Tim, it is not easy to change the framing or encoding in the polling duplex binding that shipped in Silverlight. Coincidentally, I am currently prototyping a REST-based pub\sub protocol which has the full content type support of HTTP (including JSON). I plan to blog it in about 2 weeks.

    ReplyDelete
  23. Thanks for the heads-up. I realize it's not easy, that's why I asked the expert first ;)

    Good luck. I look forward to the article.

    Cheers!

    ReplyDelete
  24. Hi Tomasz

    Do you have a fixed sample of your PollingDuplexSampleScalable ?

    The one which can be downloaded here is broken. When you update the Service on the Client the NotifyReceived is undefined. I guess something is just confused/unfinished in your sample code.

    Cheers

    Bernd

    ReplyDelete
  25. Hi Gurus ;)

    I spent some days now following Tomasz samples and all the related blogs of mostly frustrated people trying to create a reliable Load-Balance capable real-time update using PollingDuplex.

    My question here is : WHY Polling Duplex ?

    In most cases your RIA Website works like that:
    1. Navigate to a page.
    2. The page loads some data from a WebService and displays it.
    3. When there is a relevant update of the data on the server, it should immediately reflected on the client.

    OK, step 3 needs some magic - but not necessarily PollingDuplex.

    I would suggest to create your own "real-time updating WebService". This will keep you in full control and with RIA its unbelievably easy to create even a load-balance capable solution.

    So what I do is:
    1. My page requests the data to be displayed from a WebService.
    2. Then it calls another WebService which checks the scalable storage for changes.
    2.1. This call is async - so the client can go on even if the service will not come back immediately.
    2.2.a. When the WebService detects a relevant change it returns this change.
    2.2.b. When the WebService cant detect a relevant change within 30seconds, it returns an empty result.
    2.3. When the WebService returns a result or empty, the client updates its data and calls the WebService again.
    2.4. When the Client doesnt need more "real-time updates" it cancels the WebService and goes on with whatever next.

    So you see, this is a kind of self made "long time polling" which is load-balance capable and keeps you in full control as far as you are in control of your WebServices.

    Now I need the Gurus telling me what are the disadvantages of this solution compared to the PollingDuplexScalable Tomasz suggested.

    Cheers

    Bernd

    ReplyDelete
  26. Hi Bernd,
    this is exactly what we do. The main advantage of this solution is, as you described, the full control and less magic behind the scenes. Furthermore we can use REST-based communication. I'm also very interested in potential disadvantages.
    Cheers
    Alex

    ReplyDelete
  27. Bernd, the Add Server Reference (and Update Service Reference) functionality of Visual Studio will not generate the correct Silverlight proxy after the service has been refactored to allow load balancing - see the second comment to this post for a more detailed explanation.

    ReplyDelete
  28. Hi Tomasz,

    I had developed an application with help of your articals. But I am not getting large data. A table having 10 columns ( 256 char ) and 10000 rows.

    Can you suggest changes required for that??

    ReplyDelete
  29. Hi Thomasz,
    Thanks for the excellent article. I created a chat application using your sample code. Now that Silverlight 4 is out do i still have to use this approach to build a scale-out app or can i use the out of box Silverlight 4 Http Polling Duplex?

    ReplyDelete
  30. Jurassic, Silverlight 4 does not add any new scale-out specific features and the mechanism described in this article is still applicable. If scale-out of HTTP long polling is of particular interest to you, please check out the http://laharsub.codeplex.com open source project which experiments with this technology.

    ReplyDelete
  31. Hello,

    first, thanks a lot for both PollingDupleix samples, they're very useful.

    Two quick questions :
    - How do you generate the *good* reference.cs without VS2010 automation ? You write it manually ?
    - I noticed PollingDupleix is not supported on WindowsPhone7, but I noticed that this "scalable" example seems to be compatible, can you confirm ?

    Thanks again.

    ReplyDelete
  32. Pacome,

    in general you can generate client proxy for a WCF service using either the Add Service Reference feature in Visual Studio, or the slsvcutil.exe tool that ships with Silverlight 4 SDK. In the context of the scale-out method describe above, the only way to generate a client proxy automatically is to do so _before_ refactoring the service implementation to allow scale-out (i.e. when the service is still in the duplex form and exposed over HTTP long polling binding.

    We have not performed any validation of the polling duplex protocol with Windows Phone 7, so I cannot confirm one way or the other if it works on the Phone platform. However, given that battery power is an important constraint on the mobile devices, I would recommend looking at the notification APIs specifically targetting the mobile platform (http://msdn.microsoft.com/en-us/library/ff402537(v=VS.92).aspx) instead of polling duplex.

    ReplyDelete
  33. Thanks for your reply Tomasz, it's more clear for me.

    About Windows Phone 7 notifications, I already read a lot of mail threads about it, and to be honest, it seems the only existing way is to use Azure (marketing boys won the war ?)...

    In order to use Silverlight notifications inside video games, several ways exists and the best one is to use low level sockets. It's not implemented in WP7 for the moment, that's why I was looking for another flexible solution, and yours seemed to be the good one.

    Thanks again for your help.

    ReplyDelete
  34. Pacome,

    you may also want to check out http://laharsub.codeplex.com, an open source project addressing similar scenario as Silverlight's polling duplex. It offers a .NET backend you can deploy anywhere you can run .NET (including Azure), and a selection of clients (Silverlight, .NET, and jQuery). I have not tried recompiling the client for WP7, but given it is only using generic HTTP features, I don't suppose this would be a problem. Also check out the performance measurements for Laharsub - it performs better than polling duplex in Silverlight.

    ReplyDelete
  35. are there any license restrictions for the code in Microsoft.ServiceModel.PollingDuplex.Scalable.dll included in the sample download?

    ReplyDelete
  36. Anonymous, it is public domain, do whatever you desire with the code (but don't hold me accountable for losses etc. etc.)

    ReplyDelete
  37. Couldnt agree more with that, very attractive article

    clomid

    ReplyDelete
  38. Thanks for your efforts.

    It's too bad this whole continuous data delivery paradigm is so hard to implement. Push still has no quality solution I'm afraid. Your code does help though. SL4/5 hasn't come up with an industry solution to this yet?

    Code confusion: your use of the "Microsoft.???" naming convention continuously forces me to stop and ask "is this a Microsoft supplied library/code/example/etc.?" I suggest you use verbiage that identifies your code more clearly.

    For instance : "Microsoft.ServiceModel.PollingDuplex", did Microsoft provide this? Is this namespace to be found within some Microsoft assembly? Convolutes the issue I believe.

    Lastly, Ten. Regardless of how I configure any polling duplex silverlight client or the web.config for the service all I can manage is 10 simultaneous client connections. Tried this on 3 different web servers (iis6,7,vsserver). Any clues as to how to fix this. (did all the service behavior gymnastics with session max and such.)

    Thanks.

    ReplyDelete
  39. Hi ,

    I took the sample and did many modification to accomodate my need. However, I am trying to design it so that once the duplex service receives the new session request I'm getting the object like
    IClientPushNotification callback =OperationContext.Current.GetCallbackChannel and trying to pass the callback object to another service through a service call. Problem is siince my IClientPushNotification is already a sevice contract, I can't make it again a DataContract to pass over the wcf channel to the other serice. I tried KnownType, [System.ServiceModel.ServiceKnownTypeAttribute(typeof(IClientPushNotification))] like these, but none of them works. I know its a different issue not directly related to the topic here , but thought someone could help.

    Anyone has any idea, how to dear with this kinda situation?

    ReplyDelete
  40. Use NetTCPBinding

    ReplyDelete
  41. Hello Tomsaz,

    Would you please provide the source code "PollingDuplexSampleScalable.zip"?

    Thanks
    Murugesan K

    ReplyDelete
    Replies
    1. The code of the sample can be downloaded from https://github.com/downloads/tjanczuk/blog/PollingDuplexSampleScalable.zip

      Delete
  42. Hi Tomasz

    This is a Great Solution. I am in the process of implementing the same in our application. It looks like the publishing is happening fine and the data is returned in the channel, but my client is not receiving the data. My call backs are not getting executed. It will be really great if you can hint me on what I might be doing wrong.

    Thanks in Advance

    Thanks and Regards
    Neezha Sakthivel

    ReplyDelete
  43. This comment has been removed by the author.

    ReplyDelete
  44. This comment has been removed by the author.

    ReplyDelete
  45. I am evaluating options for implementing pub sub mechanism, I would like to have wpf clients connecting to pub sub server using netTCPBinding. How can we use this example to work with WPF and netTCPBinding. I want to host the services under IIS 7.5 in web farm ( tow web server with load balancers). Is client continuously polls the queue in your scenario for messages? if yes the what is frequency. What would be the performance impact in case number of clients increases to 1000 users and there is notification to be sent every second.

    ReplyDelete
    Replies
    1. At this point I recommend NOT using the technology highlighted in this article. Have a look at SignalR instead.

      Delete
  46. I know this is quite an old post now, but one thing that was missed on the service contract is the CloseSession method. This can simply be added to the IPollingDuplex service contract as:

    [OperationContract(Action = "http://schemas.microsoft.com/2008/04/netduplex/CloseSession", ReplyAction = "*")]
    Message CloseSession();

    In the implementation, you can pull out the address/session ID from the headers, and apply any logic to remove the session as appropriate. The response can simply return an empty message (such as that created by the MakeConnection.CreateEmptyResponse method in this example).

    Thanks,
    Dan

    ReplyDelete
    Replies
    1. ...just to add to this, the CloseSession operation is called when disposing/closing the client channel, giving the opportunity to clean up. Of course, not forgetting the issues as described at http://msdn.microsoft.com/en-us/library/aa355056.aspx!

      Delete

My Photo
My name is Tomasz Janczuk. I am currently working on my own venture - Mobile Chapters (http://mobilechapters.com). Formerly at Microsoft (12 years), focusing on node.js, JavaScript, Windows Azure, and .NET Framework.