蛋疼的haproxy,原来你是这样支持请求转发的
2010-12-07 19:52

在一个WEB环境中,根据path区分静态文件和动态数据的请求,并把静态文件和CGI放在不同的服务器上。

后来,蛋疼的现象出现了:CGI服务器上发现了对静态文件的请求!!!

GouRiDe的haproxy有BUG?

翻啊翻啊,居然原因就在haproxy说明文档的第一页:

==============================================================

1.1. The HTTP transaction model
-------------------------------

The HTTP protocol is transaction-driven. This means that each request will lead
to one and only one response. Traditionnally, a TCP connection is established
from the client to the server, a request is sent by the client on the
connection, the server responds and the connection is closed. A new request
will involve a new connection :

[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ...

In this mode, called the "HTTP close" mode, there are as many connection
establishments as there are HTTP transactions. Since the connection is closed
by the server after the response, the client does not need to know the content
length.

Due to the transactional nature of the protocol, it was possible to improve it
to avoid closing a connection between two subsequent transactions. In this mode
however, it is mandatory that the server indicates the content length for each
response so that the client does not wait indefinitely. For this, a special
header is used: "Content-length". This mode is called the "keep-alive" mode :

[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ...

Its advantages are a reduced latency between transactions, and less processing
power required on the server side. It is generally better than the close mode,
but not always because the clients often limit their concurrent connections to
a smaller value.HAProxy currently does not support the HTTP keep-alive mode,
but knows how to transform it to the close mode.

A last improvement in the communications is the pipelining mode. It still uses
keep-alive, but the client does not wait for the first response to send the
second request. This is useful for fetching large number of images composing a
page :

[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ...

This can obviously have a tremendous benefit on performance because the network
latency is eliminated between subsequent requests. Many HTTP agents do not
correctly support pipelining since there is no way to associate a response with
the corresponding request in HTTP. For this reason, it is mandatory for the
server to reply in the exact same order as the requests were received.

Right now, HAProxy only supports the first mode (HTTP close) if it needs to
process the request. This means that for each request, there will be one TCP
connection. If keep-alive or pipelining are required, HAProxy will still
support them, but will only see the first request and the first response of
each transaction. While this is generally problematic with regards to logs,
content switching or filtering, it most often causes no problem for persistence
with cookie insertion.

==============================================================

原来,浏览器和haproxy建立连接的时候,haproxy根据第一个GET(POST..)中的路径等得出转发规则,比如转发到服务器A。

但是,浏览器会在一个连接上发送多个GET请求,而haproxy仅根据第一个请求的规则转发,不理会第二个请求的规则,还是继续转发给A。

这么牛叉的代理,居然不支持这么基础的应用,怎一个蛋疼了得!

解决办法有:

1、haproxy上配置force close,让每个连接只能发一次请求。(keep-alive的优势让他见鬼去吧)

2、动静分离,采用不同的域名。当然,为了安全,动态数据的haproxy可能还是需要force close的。

发表回复