14

下面是一个请求单个页面的 HTTP 1.1 调用示例:

GET /jq.js HTTP/1.1
Host: 127.0.0.1
Accept: */*

我了解HTTP Pipelining,可以在不中断连接的情况下发送多个请求。

  • 有人可以发布一些如何将此请求发送到服务器的文本示例,我希望能够通过命令行或使用 PHP 套接字来完成。
  • 是否也需要在 Web 服务器上启用对流水线的支持?
  • 主要 Web 服务器(apache、nginx)默认支持流水线还是需要启用它
  • 4

    1 回答 1

    23

    来自w3c 协议详细信息

    8.1.2.2 流水线

    支持持久连接的客户端可以“管道”其请求(即,发送多个请求而不等待每个响应)。服务器必须以与接收请求相同的顺序发送对这些请求的响应。

    在连接建立后立即假设持久连接和管道的客户端应该准备好在第一次管道尝试失败时重试他们的连接。如果客户端进行了这样的重试,它必须在知道连接是持久的之前进行管道传输。如果服务器在发送所有相应响应之前关闭连接,客户端也必须准备好重新发送他们的请求。

    客户端不应使用非幂等方法或非幂等方法序列对请求进行管道传输(参见第 9.1.2 节)。否则,传输连接的过早终止可能会导致不确定的结果。希望发送非幂等请求的客户端应该等待发送该请求,直到它收到前一个请求的响应状态。

    因此,第一个事实是您应该处于 KeepAlive 状态。所以你应该在你的请求头中添加Connection: keep-alive关键字,但是一些网络服务器可能仍然接受没有这种保持活动状态的流水线。另一方面,这可能会被服务器拒绝,服务器可能会也可能不会接受您在保活模式下的连接。因此,在任何时候,无论是否处于 keepalived,您都可能在一个连接中发送 3 个流水线请求,并且只能得到一个响应。

    这个要点我们可以找到一个用 telnet 测试它的好方法。

    Connection: keep-alive请求带有标题的keepalive :

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:51:58 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Keep-Alive: timeout=5, max=100  <======= Keepalive!
    Connection: Keep-Alive
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:51:58 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    

    有用。

    在不要求 Keepalive 的情况下:

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:49:37 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:49:37 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    Connection closed by foreign host.
    

    同样的结果,我没有要求它,但它看起来像一个 Keepalive 答案(在 5 秒后关闭,这是 Apache 中设置的值)。和一个流水线的答案,我得到了我的两页。

    现在,如果我通过设置阻止在 Apache 中使用任何 Keepalive 连接:

    Keepalive Off
    

    并重新启动它:

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 18:02:41 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Connection: close
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    Connection closed by foreign host.
    

    只有一个答案......所以服务器可以拒绝我的流水线请求。

    现在,对于服务器和浏览器的支持,我认为您的维基百科来源已经足够了 :-)

    于 2013-10-27T18:09:14.243 回答