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

On-Demand Supports SSL

by anton.venema 13. July 2010 18:41

It's here! On-Demand officially supports SSL.

Using On-Demand SSL is trivial. Just change the script tag to load over https:// (i.e. https://sync3.frozenmountain.com/client.js). As long as your page is SSL-secured, the client will automatically configure itself to encrypt all communications.

Happy coding!

Tags: , ,

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

Building a Better Stock Ticker

by jerod.venema 11. March 2010 23:15

(Cross-posted to Comet Daily)

One of the most common use-cases for Comet is the ubiquitous stock ticker demo. There are several reasons why this particular demo is so popular: it’s easy to understand why people want stock quotes in real-time, it’s obvious that changes are occurring (even without any user interaction), and at least for a simple demo, it’s fairly simple to implement.

Although building a demo is quite trivial, building a stock ticker that has useful functionality quickly raises a number of questions, many of which have been directed to me at Frozen Mountain. One question in particular has been directed to me multiple times, and is more of a design question: what’s the best way to implement a stock ticker using Comet?

Note: for the purposes of this article, I’m going to assume we’re working with a Comet server built on the Bayeux protocol, such as WebSync.

The Problem

The “best way to implement a stock ticker” is rather ambiguous, so let’s take a moment and first define our scenario clearly so we know what the problem really entails.

Let’s work with a fairly common scenario. Assume each user has a “portfolio” of stocks, each stock containing between 10 and 50 points of data (such as min price, max price, current value, etc). Each user also had the ability to show or hide certain data points. Since we’re talking about 10-50 data points per stock, and we obviously want to avoid sending 5x the amount of necessary data, we want to send each user only the exact set of information they require.

At First Glance

If you just take this problem at face value without digging into the details, one approach jumps out pretty quickly. The data set is unique per user, so just send each user their own set of data! This approach would look something like this:

  • Create a unique channel for the user
  • Build a custom “portfolio” object for each user
  • Change the serialization of that object to only include the properties selected by the user
  • For every user, when new data arrives, check to see if the new data matches the list of properties the user cares about, and if so, send it to them

While this approach would (somewhat) work, it has a couple fairly notable disadvantages:

  • State must be maintained for each user on the server, increasing memory usage substantially
  • A lot of additional checking needs to be done to determine if the data should be sent
  • The stock data gets tied directly to a specific user

Our first disadvantage, maintaining state, can be resolved with more hardware and persistent storage. Obviously, if we can eliminate the need to maintain state for thousands of users, we reduce the application complexity, remove the need for persistent storage (in case of a soft application reset), and we’re going to need a lot less hardware. Pretty straightforward.

Our second disadvantage, additional data checking, is less important, but still a hassle. When the data is sent, it has to be checked to make sure it’s in the list of data this user cares about. If the sum total of the data is nothing, then the request doesn’t actually need to be sent at all. Not impossible by any stretch of the imagination, but annoying. And software should never be annoying.

Our third disadvantage with this approach, the tight coupling of data to individual users, is a little more interesting. Typically, to get data streaming, the data is published from a separate process - a windows service, linux/unix daemon, whatever. This process contains no information about the web users, and is just managing the data. That means we need to make an adjustment to either the process (to make it aware of the users by using a common storage mechanism, such as a database) or the web application (to make it pre-process the data, such as in WebSync’s “BeforePublish” event, and push the data to the individual users). Neither of these options sound like ideal, and both would still require the web application to be stateful.

So with all these issues, where does that leave us? If we analyze the problems with our “first glance” approach, it becomes obvious that the what we’re looking for is a solution that is both 1) stateless and 2) loosely coupled between the data and users.

Now that we’ve agreed on that…let’s locate that solution!

Channel Mania

Let’s re-state our problem a little, now that we’ve gotten a little more in-depth. Basically, we need to have a way for any user to be able to access live changes for any, all, or none of the data points. If we think about this in terms of the Bayeux protocol, what we’re really saying is that each data point needs its own channel.

That means no more per-user channels, which in turn means our application can be stateless, which also implies that we can keep our publishing of data separate from our consuming of the data. Ok, interesting. Of course, this solution immediately raises some questions as well.

First, isn’t creating a channel for every data point a lot of extra overhead? Well, there are two places where we really have to care about overhead: the server process that’s managing all the messages and the size of the actual message itself. The message size can be easily managed by keeping channel length small, so that’s not a big problem. The server processing of the messages is actually a very interesting discussion…

While I can’t speak for certain about implementations of the Bayeux protocol other than WebSync, I believe our implementation may be similar to many others in this particular aspect. WebSync makes using multiple channels a very efficient method of message distribution. In fact, WebSync only actually creates a channel when at least one user subscribes to it, and destroys it once the last subscription to that channel is gone. What that means is that publishing a message to 10,000 channels when users are only subscribed to 5 channels results in 9,995 messages immediately getting discarded, which is the fastest possible operation that can be performed. So we’re ok on server overhead too.

Final Result

Now we’ve answered our two main objections to this solution: we can keep message sizes small, and having lots and lots of channels is actually a very good thing for efficient message distribution. We’ve also noted that this solution allows us to reach our goals of statelessness and clean separation of tasks between the publishing and consuming of data. So, as a result, we end up with all kinds of channels, each of which might look something like:

    "/ticker/GOOG/max"
    "/ticker/GOOG/min"
    "/ticker/GOOG/current"

So the only question that remains is how to actually subscribe to all these channels without creating a ton of additional requests? Well guess what - the Bayeux protocol accounts for this very scenario. When you make a subscribe request, you can subscribe to multiple channels in a single shot:

  client.subscribe({
      channels: [
          "/ticker/GOOG/max",
          "/ticker/GOOG/min",
          "/ticker/GOOG/avg"
      ],
      onReceive: function(args){
          // handle the incoming data...args.channel will describe the 
          // channel, so if we need to we can update specific table 
          // columns, rows, etc.
      }
  });

Another interesting aspect of this approach is that it is highly extensible. We’re now able to work with 2D data (stocks => rows, data points => columns) but we can extend our approach out to 3D data with another path portion on the channel such as "/ticker/GOOG/{date}/avg", and start displaying data in a cube instead of a table!

Man, now I want to make a 3D stock ticker…

Tags: ,

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

PHP's json_encode has weird forward slash escaping

by jerod.venema 12. December 2009 01:46

OK, we've just uploaded a new version of our PHP publisher and proxy.

We are using the built in json_encode function of PHP (new in version 5.2.1+) to create our JSON strings, and it turns out that there's a bug, or at least a pseudo-bug, in how the json_encode function is implemented. For some reason, they escape forward slashes in the output. This is rather odd, and was the underlying issue that could eventually result in an "invalid json" complaint in our javascript client.

It appears that this issue may be resolved in PHP 5.3+, so those of you running the latest version may not have seen any issues. In either case, the updated scripts should work.

Anyhow, for those of you using WebSync with PHP, grab a new copy of the PHP libraries from our downloads section and you'll be good to go.

Special thanks to Andrew Betts for finding and reporting this one to us.

Tags: ,

WebSync 2.4.2 Released

by Administrator 22. October 2009 23:37

As always, once you have a new version of a product out, the requests come flooding in. To that end, hot on the heels of our recent 2.4.1 release, we're now releasing WebSync version 2.4.2, fully backwards compatible and ridiculously over-tested!

WebSync Server

For WebSync Server, this release fixes one issue, and introduces some nice new features. Here are the details.

Bugfixes

  • We've applied a fix to address issues with encoding of extended characters sets. UTF-8 encoding is now used across the board.

Features

  • The javascript client is now more resilient to bad data; as a result, the javascript client will now display a nice message if you attempt to send invalid data through WebSync, letting you know exactly what caused the problem.
  • The "Unsubscribe" event will be fired for users that are getting disconnected due to idling, which means all clients are guaranteed to unsubscribe to any channel to which they've subscribed.
  • The database name is no longer required to be "WebSync"
  • Support for external config files was added
  • Connection string names and HTTP Direct Publish settings can now be specified in the config file, allowing you to override attributes you've set in code

WebSync On-Demand

For WebSync On-Demand users, you will also get the benefits of the additional error checking and extended character sets, and will also get a great new feature - meta data! In the past, the one difficulty with using WebSync On-Demand was knowing when users subscribed to or unsubscribed from a given channel. With version 2.4.2, this problem is a thing of the past, as we've added support for meta-information. To take advantage of this feature, you simply add an additional property when subscribing to a channel, "onMetaReceive". This function will receive notifications when new users subscribe or unsubscribe from the specified channel, and you can make your application update accordingly. You can learn more about this new property by reading the subscribe documentation. And for those of you wondering what happens when someone kills their browser without properly unsubscribing first - when WebSync performs its automatic cleanup, you'll be notified that the user has unsubscribed, so you're covered there too!

Don't forget to update your client javascript url to:

http://sync.frozenmountain.com/client.js?v=2.4.2

Those of you using the .Net API, please get a new copy of the WebSync.Core.dll from our downloads section.

Tags: ,

Client Versioning

by Administrator 22. October 2009 22:30

With the latest release of WebSync On-Demand comes a new client versioning system. We want you to always have access to the latest copy with the most recent enhancements and fixes, but still allow you to choose when and how you release it into your application.

A typical client script would look something like:

<script src="http://sync.frozenmountain.com/client.js" type="text/javascript"></script>

This will always return the most recent copy of the JavaScript client with the latest fixes.

To target a specific version of the client, simply update the query string to include the version number.

<script src="http://sync.frozenmountain.com/client.js?v=2.4.1" type="text/javascript"></script>

The "v" parameter stands for "version" and can be used to download a specific client version. For production applications, you may want to include the version as a matter of habit. We do our very best to ensure that 100% backwards compatibility is maintained, but integration in browsers can sometimes do interesting things, especially when multiple frameworks/scripts are merged together into the same page. When a newer version arrives, you can then run your application in a test environment with the latest copy to iron out any potential conflicts before pushing it out to your clients.

Tags: , ,