First, What Do I Mean by Polling?
No I'm not conducting a survey or soliciting political data, I'm talking about web server polling. Polling is the process of repeatedly asking a server if there is any new information available. Sometimes the interval between poll requests is a long period, and other times it's very short. If you want to get updates for your clients in a near real time fashion, you will need to poll the server regularly and often.
Problems with Polling
Polling is simple and easy; just make a request and create and process a response. Server and client code is easy to create, and is not blocked by firewalls or routers. Like with most shortcuts in life though, it comes with some side effects. Here's a few to start:
- Excessive server load made worse with more clients, and more frequent polling
- Slower than real-time update detection, even when polling frequently
- Significantly increased battery usage/drain on mobile devices
Long Polling is a type of polling that addresses some of these by holding server-client connections open for long periods. This helps get updates at closer to real time and improves mobile battery usage, but it still puts large loads on the server, is not reliable in all scenarios, and is not allowed by all firewalls and routers, etc.
If you want to pay for loads of server hardware that is doing most of its work telling clients that there's no new data, then by all means get out your wallet and go with polling.
Server Sent Events - The Better Way
Server Sent Events (SSE) is a unidirectional communication system specifically designed to solve the problems posed by polling. With SSE a client simply opens a connection with the server, and waits for new information. Since SSE is based on HTTP, it is not rejected by firewalls and routers, etc. Battery usage is low due to limited processing required, and negligible radio/network use to maintain the connection. Updates from the server arrive at the client as soon as they are sent, so realtime response times are supported by default.
What About Server Load?
Hm ya I skipped over that part, but I had a good reason. While the client implementation of SSE is very easy and well supported on many platforms, server implementations capable of serving SSE to a large number of clients are much less common.
The problem most servers have is the way they consume system resources to handle each request. Most web servers are configured with the request response model, which is the standard format for loading web pages and resources. A client will request a resource from the server, the server will allocate resources, fulfill the request, and then free the allocated resources for the next request. Servers allocate a healthy amount of resources to the request in order to ensure it is completed quickly, so that the client isn't left waiting needlessly, and that so the server is ready for the next request. This model breaks down quickly for SSE implementations on these servers, because the allocated system resources are not returned to the pool; SSE connections are long lasting, and so server resources are eaten up until there're none left for new requests, or even the connections it already has.
An SSE connection itself does not require significant system resources in order to be maintained. Unlike a web request, SSE does not need to respond to the client quickly, and so fewer dedicated resources are required. A more appropriate server model for SSE is to have a single thread handle all SSE operations. The single thread can manage all the client connections, and sit idle while there're no new clients, and no data to send to connected ones. Additional threads can be allocated to the server permanently or dynamically should the number of clients or messages require it.
So what technology is best suited for such a server? Fortunately there are a few options and it's not too complicated, but there are some key points to consider. Firstly, at time of writing you're not (or not easily) going to find a ready-made SSE capable web server, that you can just turn on and start using. While it has been around for a number of years, SSE has only recently come to more attention as web applications become more and more functional.
Since SSE is based on HTTP, you must obviously have an HTTP server. If your SSE connections require HTTPS, then you're going to need to handle that too. What if your server is already hosting other applications, and you need to host SSE on the same server but you can't use a new port? What I'm trying to lead you to with all this is that it's best to host your SSE server behind a mature web server. Requests to a specific URL can be passed internally to your service, and can be on any port.
You've got your server set up to forward SSE requests through, so now you need to build an SSE web service; what programming language should you use? Likely any modern language could be used, but here're the ones I was drawn to first. C++ is a great choice as you get the versatility you need, coupled with the fine-tuned resource control, and the performance of a compiled application. If you don't need high level performance or C++ isn't your thing, NodeJS could be for you. It's a natural fit for SSE as it's single threaded by default, and a lot of the lower level coding has already been done for you.
There's also an option from an unexpected source: PHP. Originally developed for serving dynamic websites, most developers overlook PHP as an option for lower-level computing. Modern PHP has come a long was since it was created, and with PHP 7 now boasts some of the best performance of any scripting language. Using the socket functionality built-in, it's possible to create with PHP a full-fledged web server supporting SSE; the server is based around a long-running PHP script, and therefore handles many connections on a single process.
That's right, you made it! Hopefully you'll have gained an appreciation for the much overlooked technology that is SSE. Please please please save the server processing power, and switch from polling to SSE for good. Better experience for users and easy to implement; why wouldn't you use SSE?