Current time: 12-13-2017, 07:22 PM Hello There, Guest! (LoginRegister)

Post Reply 
 
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Use Persistent Connections (keep-alive)
07-16-2010, 03:28 AM
Post: #1
Use Persistent Connections (keep-alive)
Hi Folks;

I'm trying to optimize my site (as best I can :-) and I keep seeing this issue reported;

Use persistent connections (keep alive):
FAILED - http://www.askmarvin.ca/forums/index.php

I don't much about keep-alives but it seems that they are working for images - it's just the .php file itself ?

I'm running IIS 5.0 w/PHP 5.2.5 & the IIS ISAPI module. Try as I might I can't seem to find any info on how to enable keep-alives with PHP on IIS 5.0 - does anyone know?
Find all posts by this user
Quote this message in a reply
07-16-2010, 03:39 AM
Post: #2
RE: Use Persistent Connections (keep-alive)
Hey Marvin,

I had the same problem before with my coldfusion pages when I started to use GZIP for the main document.

You need to set a php header for content length.

For coldfusion I did something like this:

Code:
<cfsavecontent variable = "raw">
content here...
</cfsavecontent>

<cfset gmt = gettimezoneinfo()>
<cfset gmt = gmt.utcHourOffset>

<cfif gmt EQ 0>
   <cfset gmt = "">
<cfelseif gmt GT 0>
   <cfset gmt = "+" & gmt >
</cfif>

<cfset filePath = "#GetCurrentTemplatePath()#">
<cfset fileObj = createObject("java","java.io.File").init(filePath)>
<cfset fileDate = createObject("java","java.util.Date").init(fileObj.lastModified())>
<cfset fileDate = '#DateFormat(fileDate, 'ddd, dd mmm yyyy')# #TimeFormat(fileDate, 'HH:mm:ss')# GMT#gmt#'>

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip">
  
  <cfset raw = #htmlCompressFormat(raw, 2)#>
  
  <cfscript>
  fileOut = createobject("java", "java.io.ByteArrayOutputStream").init();
  out = createobject("java","java.util.zip.GZIPOutputStream").init(fileOut);
  out.write(raw.getBytes(), 0, len(raw.getBytes()));
  out.finish();
  out.close();
  </cfscript>
  
  <cfheader name="Content-Encoding" value="gzip">
  <cfheader name="Last-Modified" value="#fileDate#">
  <cfheader name="Content-Length" value="#len(fileOut.toByteArray())#">
  <cfheader name="Expires" value="#GetHttpTimeString(DateAdd('d', 7, Now()))#">
  <cfcontent type="text/html; charset=utf-8" reset="true" variable="#fileOut.toByteArray()#">  
    
<cfelse>
  <cfheader name="Expires" value="#GetHttpTimeString(DateAdd('d', 7, Now()))#">
  <cfheader name="Last-Modified" value="#fileDate#">
  <cfoutput>#htmlCompressFormat(raw, 2)#</cfoutput>
</cfif>

Hope this helps.

Sincerely,
Travis Walters
Find all posts by this user
Quote this message in a reply
07-16-2010, 04:10 AM
Post: #3
RE: Use Persistent Connections (keep-alive)
Hi Travis!

I thought it would be a matter of changing a setting on the web server but it looks like it requires a programmatic approach - that makes it a bit beyond my reach Confused

I wonder if it's even causing much of a performance hit - I believe keep-alives are working for everything else but php.
Find all posts by this user
Quote this message in a reply
07-16-2010, 04:21 AM
Post: #4
RE: Use Persistent Connections (keep-alive)
Hey There,

If you are on a windows server, try going to your internet information settings (IIS) manager.

If you right click your website, click properties, and make sure enable http keep-alives is checked.

I am not really experienced on unix or linux servers so if you are using one of those, perhaps someone else on here can help.

Sincerely,
Travis Walters
Find all posts by this user
Quote this message in a reply
07-16-2010, 04:37 AM
Post: #5
RE: Use Persistent Connections (keep-alive)
Hi Travis;

It's Windows 2000 / IIS 5.0 and keep-alives are enabled on the server and on the specific website.

Maybe I'm chasing a ghost (I don't really know what I'm doing) because this is what the requests look like which would seem (to me) to indicate that keep-alives are enabled?

Request 1:

URL: http://www.askmarvin.ca/forums/index.php
Host: http://www.askmarvin.ca
IP: 70.66.128.238
Location: Parksville, Canada*
Error/Status Code: 200
Start Offset: 0 s
DNS Lookup: 159 ms
Initial Connection: 75 ms
Time to First Byte: 150 ms
Content Download: 215 ms
Bytes In (downloaded): 7.2 KB
Bytes Out (uploaded): 0.5 KB

Request Headers:

GET /forums/index.php HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-shockwave-flash, */*
Accept-Language: en-us
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; PTST 2.219; PTST 2.219)
Host: http://www.askmarvin.ca
Connection: Keep-Alive

Response Headers:

HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Date: Thu, 15 Jul 2010 18:30:36 GMT
Content-type: text/html
X-Powered-By: ASP.NET
X-Powered-By: PHP/5.2.5
Set-Cookie: session_id=f8e1eeda8d6fdea15e256c35eec13352; path=/forums/; domain=.askmarvin.ca
Content-Encoding: gzip
Vary: Accept-Encoding


Request 2:

URL: http://www.askmarvin.ca/forums/style_images/AskMarvin/topleft.jpg
Host: http://www.askmarvin.ca
IP: 70.66.128.238
Location: Parksville, Canada*
Error/Status Code: 200
Start Offset: 0.545 s
Initial Connection: 65 ms
Time to First Byte: 96 ms
Content Download: 0 ms
Bytes In (downloaded): 1.4 KB
Bytes Out (uploaded): 0.5 KB

Request Headers:

GET /forums/style_images/AskMarvin/topleft.jpg HTTP/1.1
Accept: */*
Referer: http://www.askmarvin.ca/forums/index.php
Accept-Language: en-us
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; PTST 2.219; PTST 2.219)
Host: http://www.askmarvin.ca
Connection: Keep-Alive
Cookie: session_id=f8e1eeda8d6fdea15e256c35eec13352

Response Headers:

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 1110
Expires: Fri, 15 Jul 2011 18:30:36 GMT
Date: Thu, 15 Jul 2010 18:30:36 GMT
Content-Type: image/jpeg
ETag: "65db83521916cb1:92e"
X-Powered-By: ASP.NET
Cache-Control: max-age=31536000
Accept-Ranges: bytes
Last-Modified: Sun, 27 Jun 2010 16:53:52 GMT
Content-Encoding: gzip
Vary: Accept-Encoding
Find all posts by this user
Quote this message in a reply
07-16-2010, 04:47 AM
Post: #6
RE: Use Persistent Connections (keep-alive)
Notice in Request #1 the "Content-Length" value is not there while in Request #2 it is.

I believe that is the key to getting your keep alive working for the main document.

I am just not sure how to do it short of programming.

How do you have the main document being gzipped? Is that programmatic or do you have a setting somewhere?
Find all posts by this user
Quote this message in a reply
07-16-2010, 05:25 AM
Post: #7
RE: Use Persistent Connections (keep-alive)
It's done programmatically and turned off in php.ini. I think this is the code that turns it on;

PHP Code:
//---------------------------------------
        // Close this DB connection
        //---------------------------------------

        
$DB->close_db();

        
//---------------------------------------
        // Start GZIP compression
        //---------------------------------------

        
if ($ibforums->vars['disable_gzip'] != 1)
        {
            
$buffer ob_get_contents();
            
ob_end_clean();
            
ob_start('ob_gzhandler');
            print 
$buffer;
        }

        
$this->do_headers();

        print 
$ibforums->skin['template'];

        exit;
    }

    
//-------------------------------------------
    // print the headers
    //------------------------------------------- 

I don't know if that helps as this is mostly above my head Big Grin
Find all posts by this user
Quote this message in a reply
07-16-2010, 07:16 AM
Post: #8
RE: Use Persistent Connections (keep-alive)
Here is a wild guess but it looks like there is a function somewhere called do_headers().

You might be able to add some sort of line there like:

Code:
$len = filesize($filename);
header("Content-Length: $len;\n");

I found that on a quick Google search. My PHP ability is a bit limited.
Find all posts by this user
Quote this message in a reply
07-18-2010, 03:48 AM (This post was last modified: 07-18-2010 04:39 AM by marvin-miller.)
Post: #9
RE: Use Persistent Connections (keep-alive)
(07-16-2010 04:47 AM)green-watch.org Wrote:  Notice in Request #1 the "Content-Length" value is not there while in Request #2 it is.

I believe that is the key to getting your keep alive working for the main document.

I am just not sure how to do it short of programming.

How do you have the main document being gzipped? Is that programmatic or do you have a setting somewhere?

I think you're on the right track - I found this on the Internet and, while you probably already know it it, I posted it for my own (and future) reference. It's probably going to be handy for other IIS users who encounter this.

Quote:"What's causing IIS to send Connection:Closed in the HTTP headers even though the browser requests Connection:Keep-Alive?

A bit of history will get you to the answer. HTTP isn't a static protocol standard, and new features are added all the time. The original protocol was designed to be stateless, and IIS closed the client's TCP connection at the end of every transmission. Contrary to popular belief, HTTP 1.0 could keep a TCP connection open but in every exchange, both the client and the server had to request that the session stay open. In HTTP 1.1, Keep-Alive connections are the standard, so the connection remains open unless explicitly closed. If you've looked at the packets from HTTP sessions recently, you've probably noticed that the Keep-Alive headers are, in effect, no longer necessary.

For successful Keep-Alive implementation, the client and server must negotiate a way to communicate how much information is being transferred. Internet Engineering Task Force (IETF) Request for Comments (RFC) 2616 (http://www.w3.org/pro tocols/rfc2616/rfc2616-sec8.html #sec8) requires this negotiation for a persistent HTTP session. Section 8.1.2.1 states that

In order to remain persistent, all messages on the connection MUST have a self-defined message length (i.e., one not defined by closure of the connection), as described in section 4.4.

In HTTP 1.1 and HTTP 1.0, this persistent session is achieved through the Content-Length HTTP header. Using the Content-Length header, the server can inform the browser exactly how much information the body of the transmission contains. However, what if you're running a Web application and the server doesn't know exactly how much information it's sending to the client? To permit a Keep-Alive connection in this scenario, HTTP 1.1 included a chunked transfer encoding feature. (For more information about chunked transfer encoding, see Section 3.6 of IETF RFC 2068 at http://www.w3.org/ protocols/rfc2068/ rfc2068.) Using this method, IIS breaks up a transmission into a larger transmission in discreet chunks, each chunk with a unique Content-Length header.

An interesting aspect of chunked encoding is that the client can also use this technique to send information to the server. In IIS 4.0, such a request causes IIS to allocate memory for the expected upload. In fact, if the client sends repeated requests to IIS 4.0 for such a transfer but never sends the information, the requests can effectively shut IIS 4.0 down while the session that's making the requests is alive. For information about this special malformed header attack, see the Microsoft article "Chunked Encoding Request with No Data Causes IIS Memory Leak" (http://support.microsoft.com/support/kb/...6/93.asp). To download the fix for this bug, go to http://download.microsoft.com/download/i...4.2.739.1/ nt4/en-us/chkenc4i.exe. (No Windows NT service packs include this fix.)

So, to answer the question, you know that to support Keep-Alive headers, IIS must send the content length. Thus, you must look at the various methods that IIS can use to deliver content and how those methods relate to using Keep-Alive headers.

IIS can send static content or dynamic content by using Active Server Pages (ASP), Internet Server API (ISAPI), or CGI files. IIS can easily keep a static content session alive because the file length is known and fixed. (it seems to be doing this now with the image files)

A scripting engine such as ASP uses Keep-Alive headers by calculating the length of the content and sending the known content length to the server. The server then uses chunked encoding, if necessary. ASP can use Keep-Alive headers only if you've enabled buffering (the default in IIS 5.0) and you don't flush the buffer. (For more information about ASP and Keep-Alive headers, see the Microsoft article "HTTP Keep-Alive Header Sent Whenever ASP Buffering is Enabled," http://support.microsoft.com/sup port/kb/articles/q238/2/10.asp.)

IIS ISAPI applications can also use Keep-Alive technology, including chunked transfer encoding. (For more information about ISAPI and Keep-Alive headers, see the Microsoft article "Chunked Transfer Encoding," http://msdn.microsoft.com/library/defaul...sref/html/ psdk/asp/devs1pev.asp.) However, you must specifically develop the application to employ these techniques; otherwise, IIS must close the connection after a transfer.

CGI applications in IIS 5.0 and IIS 4.0 can't use the Keep-Alive features of HTTP 1.1, no matter what the applications do. For this reason, you'll see that IIS sends the Connection:Closed HTTP header even though the browser indicates that it wants a Keep-Alive connection and you've enabled Keep-Alive headers in IIS."

from Forcing Keep-Alive Sessions (WindowsIT Pro)

Following up on this article I found this (How to enable chunked transfer encoding with IIS). The important part about it seems to be this;

Send Chunked Data in ISAPI Programming
In Internet Server Application Programming Interface (ISAPI) programming, if you want to send chunked data, add a "Transfer-Encoding: chunked" header, and then send the correctly formatted chunked stream by using InternetWriteFile:

Quote:POST / HTTP/1.1
Host: x.x.x.x:port
Connection: keep-alive
TRANSFER-ENCODING: chunked

Is that why you coughed up this bit of code?;

PHP Code:
$len filesize($filename);
header("Content-Length: $len;\n"); 

After looking through the code for my site it seems that the location where the headers are set globally is here;

PHP Code:
//-------------------------------------------
// print the headers
//-------------------------------------------

    
function do_headers() {
        global 
$ibforums;

        if (
$ibforums->vars['print_headers'])
        {
            @
header("HTTP/1.0 200 OK");
            @
header("HTTP/1.1 200 OK");
            @
header("Content-type: text/html");

            if (
$ibforums->vars['nocache'])
            {
                @
header("Cache-Control: no-cache, must-revalidate, max-age=0");
                @
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
                @
header("Pragma: no-cache");
            }
        }
    } 
Find all posts by this user
Quote this message in a reply
07-18-2010, 10:04 PM
Post: #10
RE: Use Persistent Connections (keep-alive)
Yes that is why I suggested that piece of code that I found.

It looks like your do_headers() is some sort of global function that you might be able to add the content length easily.

However, I am not an advanced or even intermediate PHP programmer so my code might be a bit off. I just found it through Google.

If nobody here knows the answer, you might find a PHP forum through Google and ask on there how to set a PHP header for content-length and see if that influences the results on webpagetest any. I think it should if the content length is set correctly.
Find all posts by this user
Quote this message in a reply
Post Reply 


Forum Jump:


User(s) browsing this thread: 1 Guest(s)