Long Polling/HTTP Streaming General Questions

Yeah, the Comet-like techniques usually blowing up the brain in the beginning — just making you think in a different way. And another problem is there are not that much resources available for PHP, cuz everyone’s doing their Comet in node.js, Python, Java, etc.

I’ll try to answer your questions, hope it would shed some light on this topic for people.

How will the server know when an update have been sent? will it need to query the databse continually or is there a better way?

The answer is: in the most general case you should use a message queue (MQ). RabbitMQ or the Pub/Sub functionality built into the Redis store may be a good choices, though there are many competing solutions on the market available such as ZeroMQ, Beanstalkd, etc.

So instead of continuous querying your database, you can just subscribe for an MQ-event and just hang until someone else will publish a message you subscribed for and MQ will wake you up and send a message. The chat app is a very good use case to understand this functionality.

Also I have to mention that if you would search for Comet-chat implementations in other languages, you might notice simple ones not using MQ. So how do they exchange the information then? The thing is such solutions are usually implemented as standalone single-threaded asynchronous servers, so they can store all connections in a thread local array (or something similar), handle many connections in a single loop and just pick a one and notify when needed. Such asynchronous server implementations are a modern approach that fits Comet-technique really great. However you’re most likely implementing your Comet on top of mod_php or FastCGI, in this case this simple approach is not an option for you and you should use MQ.

This could still be very useful to understand how to implement a standalone asynchronous Comet-server to handle many connections in a single thread. Recent versions of PHP support Libevent and Socket Streams, so it is possible to implement such kind of server in PHP as well. There’s also an example available in PHP documentation.

How do I check for the results during the Ajax connection is still active? I’m aware of jQuery’s success function for ajax calls, but how do I check the data while the connection is still ongoing?

If you’re doing your long-running polls with a usual Ajax technique such as plain XHR, jQuery Ajax, etc. you don’t have an easy way to transmit several responses in a single Ajax request. As you mentioned you only have ‘success’ handler to deal with the response in whole and not with its part. As a workaround people send only a single response per request and process it in a ‘success’ handler, after that they just open a new long-poll request. This is just how HTTP-protocol works.

Also should be mentioned that actually there are workaround to implement streaming-like functionality using various techniques using techniques such as infinitely long page in a hidden IFRAME or using multipart HTTP-responses. Both of those methods are certain drawbacks (the former one is considered unreliable and sometimes could produce unwanted browser behavior such as infinite loading indicator and the latter one leaks consistent and straightforward cross-browser support, however certain applications still are known to successfully rely on that mechanism falling back to long-polling when the browser can’t properly handle multipart responses).

If you’d like to handle multiple responses per single request/connection in a reliable way you should consider using a more advanced technology such as WebSocket which is supported by the most current browsers or on any platform that supports raw sockets (such as Flash or if you develop for a mobile app for instance).

Could you please elaborate more on message queues?

Message Queue is a term that describes a standalone (or built-in) implementation of the Observer pattern (also known as ‘Publish/Subscribe’ or simply PubSub). If you develop a big application, having one is very useful — it allows you to decouple different parts of your system, implement event-driven asynchronous design and make your life much easier, especially in a heterogeneous systems. It has many applications to the real-world systems, I’ll mention just couple of them:

  • Task queues. Let’s say we’re writing our own YouTube and need to convert users’ video files in the background. We should obviously have a webapp with the UI to upload a movie and some fixed number of worker processes to convert the video files (maybe we would even need a number of dedicated servers where our workers only will leave). Also we would probably have to write our workers in C to ensure better performance. All we have to do is just setup a message queue server to collect and deliver video-conversion tasks from the webapp to our workers. When the worker spawns it connects to the MQ and goes idle waiting for a new tasks. When someone uploads a video file the webapp connects to the MQ and publishes a message with a new job. Powerful MQs such as RabbitMQ can equally distribute tasks among number of workers connected, keep track of what tasks had been completed, ensure nothing will get lost and will provide fail-over and even admin UI to browse current tasks pending and stats.
  • Asynchronous behavior. Our Comet-chat is a good example. Obviously we don’t want to periodically poll our database all time (what’s the use of Comet then? — Not big difference of doing periodical Ajax-requests). We would rather need someone to notify us when a new chat-message appears. And a message queue is that someone. Let’s say we’re using Redis key/value store — this is a really great tool that provides PubSub implementation among its data store features. The simplest scenario may look like following:
    1. After someone enters the chat room a new Ajax long poll request is being made.
    2. Request handler on the server side issues the command to Redis to subscribe a ‘newmessage’ channel.
    3. Once someone enters a message into his chat the server-side handler publishes a message into the Redis’ ‘newmessage’ topic.
    4. Once a message is published, Redis will immediately notify all those pending handlers which subscribed to that channel before.
    5. Upon notification PHP-code that keeps long-poll request open, can return the request with a new chat message, so all users will be notified. They can read new messages from the database at that moment, or the messages may be transmitted directly inside message payload.

I hope my illustration is easy to understand, however message queues is a very broad topic, so refer to the resources mentioned above for further reading.

Leave a Comment