Search code examples
phpajaxapachelong-polling

Long Polling with Ajax and PHP - Apache freezes


We try to implement long-polling based notification service in our company's ERP. Similar to Facebook notifications.

Technologies used:

  • PHP with timeout set to 60 seconds and 1 second sleep in each iteration of loop.
  • jQuery for AJAX handling.
  • Apache as web server.

After nearly month of coding, we went to production. Few minutes after deployment we had to rollback everything. It turned out that our server (8 cores) couldn't handle long requests from 20 employees, using ~5 browser tabs each. For example: User opened 3 tabs with our ERP, with one long-polling AJAX on each tab. Opening 4th tab is impossible - it hangs until one of previous 3 is killed (and therefore AJAX is stopped).

'Apache limitations', we thought. So we went googling. I found some info about Apache's MPM modules and configs, so I gave it a try. Our server use prefork MPM, as apachectl -l shown us. So I changed few lines in config to look something like this:

<IfModule mpm_prefork_module>
    StartServers          1
    MinSpareServers       16
    MaxSpareServers      32
    ServerLimit          50%
    MaxClients          150
    MaxClients           50%
    MaxRequestsPerChild   0
</IfModule>

Funny thing is, it works on my local machine with similar config. On server, it looks like Apache ignores config, because with MinSpareServers set to 16, it lauches 8 after restart. Whe have no idea what to do.


Solution

  • Passerby in first comment of previous post gave me good direction to check out if we hit max browser connections to one server.

    As it turns out, each browser has those limit and you can't change them (as far as I know). We made a workaround to make it work.

    Let's assume that I was getting AJAX data from

    http://domain.com/ajax
    

    To avoid hitting max browser connections, each long-polling AJAX connects to random subdomain, like:

    http://31289.domain.com/ajax
    http://43289.domain.com/ajax
    

    and so on. There's a wildcard on a DNS server pointing from *.domain.com to domain.com, and subdomain is unique random number, generated by JS on each tab.

    For more information, check out this thread.

    There's been also some problems with AJAX Same Origin Security, but we managed to work it out, using appropriate headers on both JS and PHP sides.

    If you want to know more about headers, check it out here on StackOverflow, and here on Mozilla Developer's page. Thanks!