
Today we will talk about
Comet and
server push in general.
Regular web applications, like sites, work according to the traditional request-response-request model, while, due to the peculiarities of the HTTP protocol and some server implementations of handlers, the application does not store information between requests, so each call is independent, and the identification or sessionality is provided by higher-level tools (for example, the well-known implementation of sessions in PHP). In addition, a request for a new information is always sent by a client who is interested in obtaining the most current version of the data. In applications that are critical to updating, this often becomes a bottleneck. In one of our previous projects, there were several periodic AJAX requests for updating data. Although for such a case there are options and calling several handlers on the server side with a single request from the client.
')
But there is another approach, when the server independently determines that there is new data (and he finds out about it the very first) and delivers it to the client program, which does not waste time on requests, but receives it itself when something new has appeared. To do this, however, it is necessary to keep a constant connection to the server, for example, via a bidirectional socket. And if in traditional software with this particular difficulty is not observed, that to implement long-standing connections for web applications is quite difficult. In the most primitive way they do it through IFrame, however this is not the only possibility, and the developers of top libraries and plugins have tried to do so, so look in your favorite framework, the Comet implementation should be there (it definitely is in the Dojo Toolkit, there are jQuery plugins built-in feature in GWT). You can also read about the various methods of implementation
in this set of materials .
But how to make a server? The usual version of Apache + PHP is not very suitable, although, of course, it is possible on it, but the solution will be far from optimal and will not withstand the typical load. By the way, about the load. For Comet applications, the load is the number of clients that can be served at the same time, meaning the number of open connections with clients, and not data transfer. And the number of such connections for ordinary servers should reach tens of thousands, typical figures - 20-50 thousand connections in parallel. And here a bunch of Apache / PHP does not help. Something else is needed.
For the Java world, there are implementations for application servers, for example, Jetty (probably the most well-known and standard implementation of Comet, here is a
good article in Russian from IBM), a server framework based on
the Grizzle platform ,
Atmosphere , appeared not so long ago, so implement your own logic and Your server for a specific application is not difficult.
What else to do? I can recommend them
open project APE or Ajax Push Engine . This is a small server written in C, which is compiled as a daemon and listens to its port, by default, 6969, but it can be configured to work together with Apache. Unlike other solutions, APE is a specialized HTTP server that supports GET / POST requests, that is, you can connect to the server from any language and system, as long as HTTP requests are understood. And this is a self-sufficient solution, in principle, it can be limited to APE alone, without additional servers (in Jetty, the implementation still requires an application server and a web server). According to the developers, APE works well under load and can hold up to 100 thousand connections at the same time, in the future horizontal scaling will be added.
It should be noted that by its architecture, the APE project consists of three parts:
- The epoll-driven HTTP server is the very foundation, the server that handles connections and holds connections, allowing Server Push to be implemented in any way suitable for the client, be it XHR long-polling or via an iframe, and in the future, native browser capabilities will be utilized ( web sockets)
- The APE JavaScript Framework is an equally important part of the project, a MooTools-based client script that can integrate server capabilities into any AJAX client applications. It also implements a modular system and extensions, so that on top you can write any wrapper for another library or embed it transparently in your solution. The library implements the imitation of sockets and pipe, so that the developer gets a high-level abstraction, and if you get even higher, then the event model is available to him and you can just forget about the implementation details.
- Plugin system - the server can be expanded by adding its own functionality through plug-ins. Now available only through C-modules, however, they are extremely simple, server-side JavaScript is expected in the future, which will truly be an excellent solution (oh, I would have to screw PHP there, although, of course, you can use a simple C-plugin, but still).
On the server side, APE uses the epoll mechanism, as well as a hash-table implementation (DJB Hash Algorithm). This turns out, in addition to maximum performance, also difficulties in porting - the server wants to build the Linux kernel 2.6.19+ and libc6-dev, and so far I have failed to force it to build under Cygwin (the stopper is precisely in terms of the epoll mechanism built into the kernel ).
For the exchange of information between the server and the client, as well as between clients (through the server), APE implements several methods. The first is the Channels, when users subscribe to certain channels, and when a new information associated with this channel appears on the server, it is transmitted to all clients who listen to the channel. Thus, you can immediately send out new data to all customers, which can be an unlimited number. You can also use APE as a queue of messages stored in memory — each connected user has one or more queues. The recipient of the message can be either a channel, then everyone will receive the message, either directly another user, or an external service. Channels can be both interactive and read-only.
APE takes on the role of a proxy server, allowing you to exchange messages with external services (for example, your application server), as well as receive data from them and send them to channels or specific users. Thus, it is possible to build a system in which the APE will be the front-end for users, which handles connections, and then the back-end server is already running, delivering and receiving data in the form of messages using the internal APE protocol, but not knowing anything about the number of connected clients , he only needs to be able to communicate with the APE server.
The interaction between the client and the server is made through a
special protocol . Users can initiate commands, for example, send a message or create a connection, in response to which the server sends RAW data, usually JSON. However, server modules can extend the built-in command set, so you can describe your own set of actions, depending on your needs.
Although the
official documentation is still in development (of course, this is a wiki), and does not report on the available modules, several basic modules are available in the source repository, which can be useful both as a reference tool for developing your solutions and for embedding them into the already existing infrastructure. For example, libape-mysql allows you to connect to the database and receive new information from there (however, note that the module version is 0.01), and libape-chat will show a demo version of a simple chat system. The most interesting promises to be libape-spidermonkey, although so far there is no information about it, except for the source.
The project is very young, but already shows its potential, so if you plan to start any serious applications that require simultaneous work with multiple users (chat or gaming system), or data delivery is critical, I advise you to pay attention to APE.
PS If anyone can build this server under the Win32 system - please share the solution!