1

I'm using AJAX to implement long polling on a page which I want to update whenever new rows are inserted into the database. The way this is done is with jQuery's .ajax() calling, for example, poll.php?ky=41, which queries the database a number of times for rows with an ID of > 41 (with a small wait in between) until a specified timeout. It will fulfil the request immediately if there is a result, or after the given timeout.

In effect, this keeps a hidden connection always open to the server, waiting for it to respond, in order to get notifications.

This works, but I'm using DreamHost and after 8 php53.cgi worker processes are spawned, no requests to my site are fulfilled (i.e. forever loading) until one times out. This affects every other page on my website. The HTTP Server is Apache 2.2.22-14.

To alleviate the problem, I have reduced the delays and the timeouts so it is closer to regular polling, and added longer delays when there have been no updates for a while. This means notifications may come a few seconds late, but so far my server has been running fine.

What I'm worried about is how well (or rather, how poorly) this will scale.

My question is: given that I'm on a shared host (DreamHost), and this page must be compatible with as many browsers as possible (except mobile), is there a more efficient way to get instant "push" notifications from the server?

Or, what other options do I have? Should I switch back to regular polling?

TL; DR

Polling is fast, but long-polling (waiting before fulfilling the AJAX request) ties up resources. The difference is that long-polling will get the result as soon as it arrives, whereas polling will only pick it up the next time an AJAX request is sent after the new information comes in. Ideally, I would like the advantage of long-polling without tying up threads & causing other users to wait before pages are served.

Elle
  • 3,695
  • 1
  • 17
  • 31
  • This may help http://en.wikipedia.org/wiki/Comet_(programming) – Zach Leighton May 17 '13 at 13:05
  • @ZachLeighton Thanks, I've combed over that page prior to this, but I need specific information on how to overcome the limitations I'm facing. – Elle May 17 '13 at 13:06
  • have u tought of using Websockets instead ? – Rene Koch May 17 '13 at 13:07
  • Wouldn't work in previous versions of IE: http://caniuse.com/websockets I need compatibility with Joe Schmoe's browser. – Elle May 17 '13 at 13:09
  • Maybe looking into the PHP library Multiplexed I/O is worthwhile: http://sourceforge.net/projects/phpmio/ – bouscher May 17 '13 at 13:17
  • the problem you've got is while you've got an ajax script there running a never ending php script that php script is eating up a php thread. If your server is limited to 8 threads then 8 people starting the poll will run you out of threads. Solution is to rather than long poll to long poll over shorter periods of time allowing the script to complete every request so it frees up the thread again. – Dave May 17 '13 at 13:18
  • Are you able to run a PHP socket server script on a certain port? Since it would only be one instance of the script listening to all incoming requests, it wouldn't need more than one PHP thread, persistently though. You wouldn't even have to change your browser technique. – Kiruse May 17 '13 at 13:19
  • @Dave Essentially, that's what I'm doing right now, but the reason I implemented long polling is to reduce the number of requests, one every 2 seconds for (say) 14 hours is undesirable. One every 25 seconds is preferable. – Elle May 17 '13 at 13:35
  • @Derija93 I don't think I can. I have shell access but since it is shared hosting, there are other webpages being served from the same machine. Therefore I don't think it's likely that I have that kind of power – Elle May 17 '13 at 13:35
  • @bouscher I don't think I can change/modify the PHP or anything, as I don't own the webserver machine. – Elle May 17 '13 at 13:40
  • 1
    Many requests are better handled than long requests. As the threads never really die they just get reused. It will also allow the system to skip a cycle if there's no available threads in the end. Now at some point you'll hit apache+php configuration issues being on shared hosting. After that go with perhaps a small vps and swap to nginx or my personal fave cherokee and use phpfpm then you can build an actual worker thread thats reserved for your poll loop – Dave May 17 '13 at 13:41
  • @Dave that's very informative, thank you. If you would like to expand on it an answer that would be great too – Elle May 17 '13 at 13:44
  • For your current stage the only bit really that I can expand on is when you run apache it fires up x number of apache threads/instances and y number of php threads these are specified in the configs for both. So if you have 8 then you have 8 ALWAYS available for you regardless of how many you're using. Now on 8 threads you can support more than 8 users normally as it relies on you releasing a thread which can then be reused. In your case your blocking a thread on longpoll so it effectively reduces your overall available resources to 7. – Dave May 17 '13 at 13:53
  • 1
    Since the threads are always open there's no overhead for you allowing your poll script to complete and then restart (if the db connection is done right there'll be little additional db load either between pooled conns and prep-statements even better memcached or similar) means you only lock the thread for the duration of the run then immediately release it for other processes to pickup and use it this is how you can support more than 8 users on 8 threads as they're recycled. Don't worry about recalling its always more efficient than longpoll unless you use realtime sockets and daemons – Dave May 17 '13 at 13:56
  • http://stackoverflow.com/a/13480576/524733 – Stephen Blum May 18 '13 at 02:16

2 Answers2

1

In this case, the solution is to simply use regular polling (e.g. an AJAX call every 500 ms) to get quick notifications rather than using long-polling and tying up threads.

From Dave,

Many requests are better handled than long requests. As the threads never really die they just get reused. It will also allow the system to skip a cycle if there's no available threads in the end. Now at some point you'll hit apache+php configuration issues being on shared hosting. After that go with perhaps a small vps and swap to nginx or my personal fave cherokee and use phpfpm then you can build an actual worker thread thats reserved for your poll loop

and

Since the threads are always open there's no overhead for you allowing your poll script to complete and then restart (if the db connection is done right there'll be little additional db load either between pooled conns and prep-statements even better memcached or similar) means you only lock the thread for the duration of the run then immediately release it for other processes to pickup and use it this is how you can support more than 8 users on 8 threads as they're recycled. Don't worry about recalling its always more efficient than longpoll unless you use realtime sockets and daemons

As of now the problem is resolved.

Elle
  • 3,695
  • 1
  • 17
  • 31
0

I think in php every open connection means a running thread. You have to make the connected time quite short and to use polling.

The only help would be to organize the polling as fast as possible, so I would try to store a very simple information queue for every session, say in apc_fetch/apc_store (if there is only one apache running for your app). A very simple page has_update.php?session_id just reads that status line and returns 0 or 1, and 0 most of the time, in the smallest format possible. So 5x per second should not be an performance issue too soon.

If and only if has_update.php returns 1 the normal ajax-call should fire.

flaschenpost
  • 2,205
  • 1
  • 14
  • 29
  • Yes this is correct. Polling is fast, but long-polling (waiting before fulfilling the AJAX request) ties up resources. The difference is that long-polling will get the result as soon as it arrives, whereas polling will only pick it up the next time an AJAX request is sent after the new information comes in. Ideally, I would like the advantage of long-polling without tying up threads. – Elle May 17 '13 at 13:42