PHP Connection: Close

2019-06-05 05:50发布

问题:

I have a PHP application that I have been having some problems with, some pages take a very long time to load.

After a couple of hours I have figured out the problem, but I have no idea how to fix it.

The problem seems to be with the header Connection: keep-alive. I used a Firefox plugin called "Tamper Data" which allows you to "tamper" with the headers and stuff. Once I used that tool to change the connection header to Connection: close the delay on some pages stopped.

How, in PHP, can I make sure that the Connection: close header is used?

I tried putting header("Connection: close"); at the top of a PHP file, and reloaded the page. It still sends the Connection: keep-alive header, not the one I am trying to send.

How can I achieve what I am trying to do?

EDIT: I have just realized that on this subdomain the content-length header is not sent at all for most pages. It is only sent right after a form submission followed by a redirect.

EDIT 2:

This is the page: http://volunteer.essentialtransit.com/job/13/just-a-test-at-eta/

Click the "Apply now" link and fill out some random txt, you don't need to attach a file. Notice when you are redirected back to the "job" detail page that it will take a very long time to load.

回答1:

Your problem has nothing to do with connection states. It might seem related to connections because Apache automatically spawns a new child thread for each new request originating from a different source. With keep-alive, it will attempt to reuse the previous thread, which is busy from a PHP script (from your application). It's a little more complicated actually but this is the basic. Just note that "Connection: Close" is being sent, but it's supposed to close the connection only after the script has finished (sent all buffers out).

Now I'm going to tell you how to debug your script. I'll do this because if you don't fix your problem and you gain more traffic, your host will kick you out for extreme resource usage.

So:

  1. Append set_time_limit(5) or higher to confirm there's a background script problem
  2. Check for requests to local resources, requests that would only work on your staging server (you can use WireShark for this)
  3. Check for external requests, cURL, file_get_contents() calls, anything with a timeout
  4. Benchmark and optimize lengthy scripts (you can try xdebug for this)
  5. Log all PHP notices, warnings and errors to a file; you should get at most zero errors
  6. Finally, it's a good practice to triple-check your entire application. One for data entry, second for data operations and third for modules interconnection. But you should focus on AJAX background scripts that can't return output

Of course, skip anything that doesn't apply.



回答2:

So, I determined what the problem was, and found a work-around to this issue.

The script that processed the form just processed the input and redirected to another page, but it actually didn't output anything. On most pages on the site the content-length header is either not sent, or is set at the correct value. But for some reason when posting to a page, and then redirecting without the processing script outputting anything to the browser, the content-length was being set at 0.

I tried setting the content-length myself, but didn't have much luck, as it didn't seem to make a difference.

So, all I did was make the processing script have some output. So now when the form is submitted the processing script outputs a page with a redirect script (and a 'click to continue' message just in case) that leads to the correct page. So while this adds a very brief delay between the form submission and the correct page being seen it causes the content-length to be set correctly and the problem is solved.

While this is not an ideal solution it is manageable and makes the script work.