Skip to content

http: reuse socket only when it is drained

It is not rare for a server to reply a response without reading the whole body, e.g. a 404 response can be fired once the server sees the url. In the client side, the response has been completely transferred to the remote peer but there is data queued to write to the socket(i.e. the socket is not drained).

This PR tries to improve the agent's behavior in this weird case, although weird, it happens every day in our production environment.

Currently, a socket gets reused by the agent once the entire response is read from the socket, plus all data of the request are flushed to the socket. In the case we talked above, such a mechanism might lead to a request to be attached to a non drained socket, if the request is large(overwhelming the TCP flow control window), this almost happens every time.

I argue that it is a punishment for a request to be attached to a non drained socket, because it does not make any progress(no data can be sent to the network), what's worse, it prevents the request from being assigned to a drained one, which might occur soon or already in the free pool(consider the default lifo scheduling strategy, that is, always assign the latest free socket to incoming requests).

This commit mitigates this problem by defering the time of claiming a socket as free. Not the time when all data of the current request are flushed to the socket, but the time when the socket is drained. Note that ensuring every request is assigned to a drained socket does not add extra latency, compared with the previous code(Writing to a non drained socket is just effectless).

Merge request reports

Loading