WebSync 3.2 Released!

by jerod.venema 2. September 2010 21:48

Hey everyone!

We have a new release of WebSync, version 3.2. This is an awesome release, as it adds a bunch of new features and gives a dramatic boost in performance.

Here's the quick summary; for a detailed list, check out the changelog.

  • Improved connection management in the .NET client, including enforced timeouts to ensure connections are destroyed no matter what after a specified period of time
  • Shutdown management so WebSync shuts down quickly and gracefully when reset
  • Improved error handling on initial load, including detection of invalid method signatures for event handlers
  • Improved Azure support via the stateless SQL provider
  • Improved documentation to work via the file system in IE
  • Huge performance improvement with respect to message throughput

The biggest change is the performance improvement. Previously, WebSync was able to deliver upwards of 30,000 messages a second. With WebSync 3.2, it's now capable of delivering over 100,000 messages per second!

As always, for those of you using On-Demand, simply adjust your client script to point to client.js?v=3.2.0, and you'll get all the latest changes. For those of you using WebSync Server, check out the Portal and download the latest copy from your Order History.

Happy coding!

Tags: ,

release | websync

Delayed Client Loading with WebSync and jQuery

by jerod.venema 17. August 2010 02:15

Warning: technical content ahead!

Recently, we were recently doing some work for a client when we came across a minor problem. We were building an application that had a bit of a unique requirement: the entire application had to work with the inclusion of a single <script> tag. Scripts could be added dynamically, but the end user had to only see a single tag.

"Simple enough", we thought; we'll simply combine the JS and CSS server-side, and be done with it. Of course, that would have meant manually extracting the JavaScript for the WebSync client from the server code. Now, that's not difficult to do (it's just an embedded resource), but we were curious if there was an even simpler solution. An extra request was completely acceptable, and since we were already using jQuery, we figured we'd just use that to load the script. The result was this:

$(function(){
  $.getScript("/client.ashx", function(){
    client.initialize();
    client.connect();
    // ...etc
  });
});

"Great", we thought. Problem solved. But then we realized that none of our client requests were being sent anymore! We pondered for a moment, and then remembered that the WebSync client is designed to monitor the "contentReady" event of the DOM so as to avoid the dreaded never-ending loading indicator. So, if the client script loads after the DOM event has already fired, the client is never notified that it is allowed to start making requests.

Thankfully, the designers of WebSync put some thought into this problem, and had a solution already waiting in the wings:

$(function(){
  $.getScript("/client.ashx", function(){
    fm.utilities.ready();
  });
});

That handy extra line tells the WebSync client that the DOM is ready to be used. It then fires any events that were queued up in the addOnLoad() utility function, running them immediately. That's it! So what're you waiting for - get coding!

Tags: , , ,

websync | jquery

WebSync 3.1 Released!

by jerod.venema 21. July 2010 21:24

Hey everyone!

It's that time again - time to check out the latest version of WebSync! In 3.1, we've got a bunch of new stuff, and a number of other fixes too:

  • General
    • Full support for the .NET Compact Framework, version 2.0+ (woohoo!)
    • Updated the core serialization so it can handle incorrect but salvageable JSON inputs
    • Updated examples so that the serialized data is the same between the .NET and JavaScript examples
    • Updated the StatelessProvider API to take a ClientRecord parameter for ConnectClient method implementations for future compatibility
  • Server
    • Added a new static method for deserializing incoming message and publications directly from a raw HTTP request (so you can pre-process them if you need)
    • Added a few minor performance improvements
  • Clients
    • [.NET] Added a new "OnRequestCreated" event for the .NET client and publisher to allow full control of the web request before it's delivered
    • [.NET] Fixed a bug in the .NET client where the subscription reference would get held after the channel was unsubscribed
    • [JavaScript] Added handling for complete network failures (such as pulling the computer's network jack) to the JavaScript client
    • [All] Fixed a bug in the server that allowed a client that had been disconnected to publish
    • [All] Fixed a bug in the .NET and JavaScript clients with mult-channel subscriptions

As a random side note, the JavaScript client is now very determined to stay connected; we tried just about everything to prevent it from staying online, and it always jumped right back in...

For those of you using WebSync On-Demand, your new URL is: http://sync3.frozenmountain.com/client.js?v=3.1.0

For those of you using WebSync Server, check out our downloads page. If you've already purchased and want the latest, log in to the Portal and check out your "Order History" tab.

Thanks everyone for your feedback, and enjoy!

Tags: , , ,

websync

Up and Coming

by jerod.venema 28. April 2010 00:57

Well, it's been awhile since we've written anything here, so I figured it was about time to get some more news out. We've been hunkered down working hard on the next revision of WebSync, which is coming soon (don't worry, I'll post about it here so you'll get all the juicy details). In the meantime, however, I thought I'd write down a couple of interesting things that have come up in the past month or so.

The Most Difficult Thing™

Writing a comet server is hard. I don't think anyone would deny that. Implementing a solution that scales vertically, horizontally, is robust and is easy to troubleshoot is no walk in the park. But the real question is: is that the most difficult thing we've had to do?

Well, the answer is probably yes ;). But, there's a *very* close second. And that is creating an API that's simple to use, but also powerful enough to handle all the corner cases that developers want to use it for.

That's been a major focus for us with our upcoming version of WebSync: a clean, easily understood API that anyone can use, but that also can be twisted and manipulated in crazy ways so developers who are pushing WebSync to the max can still do what they want/need with it.

A Rose by Any Other Name

Although Shakespeare's claim that it might smell as sweet might be true, if you called a Rose a Skunkweed, there might be fewer people who would try to smell it. The same principle applies to APIs - if you don't use a name or convention that makes logical sense when naming your methods, properties and events, there will be few people who would try to use it, making the API difficult to use

Not only does a poor API make your software difficult to use, it makes development with it frustrating, which is a terrible thing indeed; nothing will turn developers off your software faster than being given stupid choices that have no obvious distinction. Our goal for the new version of WebSync? Make the software so easy to use that you don't need documentation. (Don't worry - we ramped up the quality of our documentation too, so you can use it, you just are less like to need to do so.) We had many...ahem...vociferous dicussions...about how to name our API to make it the absolute best API around, not just for a comet server, but for any software component available.

The end result is hopefully an API that's so clean and simple to understand, that even if your intellisense breaks, you'll know exactly what calls to make and arguments to use when implementing your awesome solution with WebSync. And if you find the API has problems or is confusing in places - we want to know! You'll find all our contact info here.

Tags: , ,

programming | websync

Regarding WebSync On-Demand and SSL

by jerod.venema 20. February 2010 01:08

We've had a number of questions about SSL for WebSync On-Demand, so I thought I'd write up a quick post about what's actually going on behind the scenes.

First, let me clarify that WebSync Server works great over SSL. All you have to do is load the script tag over SSL, and everything else will be taken care of automagically; WebSync detects the secure connection, and all requests will immediately switch to SSL, no other changes required.

That said, with WebSync On-Demand, the issue is not so straightforward, and centers around load balancing algorithms and the need for sticky sessions while maintaining our "proxying" capability. To understand the problem, you have to know that typically, load balancers allow sticky sessions via several methods, two common methods being IP-based balancing and query parameter-based balancing.

IP-based load balancing works great with WebSync Server. However, with WebSync On-Demand, we have to account for proxying, which allows developers to add custom processing to the requests; this is what allows you to, for example, add authentication and authorization to your WebSync On-Demand requests. However, that also means that a given client's session isn't tied to a specific IP address, so that load balancing scenario goes out the window.

Enter query-based load balancing. This works very well, as the query is unique per-user, and follows along nicely with the request even if it has been proxied. The problem that comes up, however, is that if you introduce SSL, the query parameter is encrypted when it reaches the load balancer, so it can't use the query parameter to load balance the request. Whoops!

As a result, we have to place SSL decryption in *front* of our load balancer, so that when the load balancer gets the request, it's able to use the query parameter and maintain our sticky sessions. This is a bit more complicated, and we're still working though the details, but we are planning at some point in the near future to add SSL to the list of supported features for WebSync On-Demand!

Tags: ,

websync

Comet Best Practices: Subscribing and Initial State Load

by anton.venema 5. February 2010 04:29

Many complications arise when building a real-time web application that employs "comet" or "reverse Ajax" to push data from the server. This is mostly due to the fact that real-time web applications require multi-threading, either directly or indirectly, and many of the same issues that arise in threading scenarios directly parallel the issues present in comet-based websites.

A frequently found issue has to do with the timing of subscribing to a comet channel versus the initial state load of the web page.

For example, consider a simple chat application. When the page loads up, the user expects to see some recent chat messages, as well as start receiving any newly published messages. The initial state load is a distinct operation from the subscription to receive new messages. As such, one must be executed before the other. There are only two possible options:

  1. Load state, then subscribe.
  2. Subscribe, then load state.

The first option results in the possibility of missing messages. It's feasible (and likely under load) for a user to publish a message after the state has loaded, but before the subscription has completed. This message would not be included in the state load, and it would not be delivered to the user over comet since the subscription was not present at the time of delivery.

The second option results in the possibility of duplicated messages. It's feasible (and again likely under load) for a user to publish a message after the subscription has completed, but before the state has loaded. This message would be delivered to the user over comet since the subscription was present at the time of delivery, and it would be included in the state load.

It has been suggested that the initial state load should be delivered in the response to the subscription request. This is absolutely possible with WebSync, but it does not remove the problem - it just narrows the gap in which the problem can occur. The scenario where messages go missing or are duplicated becomes less likely, but we find ourselves in a dangerous situation when we try to hide bugs instead of fix them. Testing becomes more difficult and we run the risk of unleashing a bug that is more difficult to track down.

So what do we do?

In general, the best thing to do is not lose messages. (As always, there are exceptions, but this is the general case we have found.) So, subscribe first, and load state data afterwards, usually through an Ajax request.

  • Page loads and a loading indicator is shown.
  • WebSync client is created and subscribes to the channel.
  • In the subscribe onSuccess handler, POST a request for initial state with Ajax.
  • In the Ajax onSuccess handler, populate the UI and remove the loading indicator.

To get rid of the duplicate messages, set a loaded flag to true once the UI has been populated. If the WebSync client receives a message and the loaded flag is false, push it onto a list. Once the loaded flag has been set to true, read through the list and process new messages, discarding duplicates. Duplicates can be identified by a server-generated ID that is attached to every message publication.

Tags:

programming | websync

Building a Managed Comet Server Part 1 - Scalability in ASP.NET

by anton.venema 18. November 2009 23:34

A common misconception about IIS and the .NET framework is that it is unable to scale well to tens of thousands of simultaneous requests. WebSync has proven that this is not the case, so why does that misconception still exist?

Not just a page anymore

In classic ASP, there was no way to make an incoming request go "idle" and just wait for something else to push it along. Instead, requests blocked on the thread pool, eventually saturating it so no further requests could be processed.

ASP.NET takes the same approach with standard requests, but provides another option as well - the IHttpAsyncHandler. This handler is designed to allow multiple requests with long-running executions to take minimal CPU usage and not saturate the thread pool, a perfect solution for building a comet server. It's no surprise, then, that this is the foundation on which WebSync is built.

Beyond the basics

Of course, creating the async handler is pointless if each request just blocks on a thread from the CLR thread pool waiting for events. Even if each request blocked for just a few seconds, you'd quickly exhaust the thread pool under load. The requests have to be offloaded for batch analysis in a separate bounded thread pool. The bounded thread pool can then make use of shared data structures to balance the request load while waiting for events to trigger a response.

To make this work, the CLR thread pool has to have a large number of threads available for the handling of incoming and outgoing requests, and the secondary bounded thread pool has to have just a few threads for the handling of everything in between. The trick is to get incoming requests off the CLR thread pool quickly for long-running processes so the secondary thread pool can bear the weight and keep the CLR thread pool light on it's feet.

Tags: , , ,

programming | websync