我对Erlang inets的保持活动功能以及ibrowse http客户端(最新版本)感到困惑。根据{{3}}:
8.1.2.2 Pipelining
A client that supports persistent connections MAY "pipeline" its
requests (i.e., send multiple requests without waiting for each
response). A server MUST send its responses to those requests in the
same order that the requests were received.
Clients which assume persistent connections and pipeline immediately
after connection establishment SHOULD be prepared to retry their
connection if the first pipelined attempt fails. If a client does
such a retry, it MUST NOT pipeline before it knows the connection is
persistent. Clients MUST also be prepared to resend their requests if
the server closes the connection before sending all of the
corresponding responses.
Clients SHOULD NOT pipeline requests using non-idempotent methods or
non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
premature termination of the transport connection could lead to
indeterminate results. A client wishing to send a non-idempotent
request SHOULD wait to send that request until it has received the
response status for the previous request.
有两种模式,'管道'基于持久连接,它们之间的区别在于它们之间的区别在于,当管道传输时,可以在同一连接上发送请求,而无需等待先前的响应。用来。换句话说,我们应该在使用' keep-alive'之前等待每个响应,然后在同一个连接上发送其他请求。
结果,我认为'保持活力'实施应该像:
%% each httpc_handler(gen_server) maintains a persistent connection
%% with type of keep-alive
httpc_handler:handle_request(Request, keepalive) ->
%% check if there is request not finished yet
case is_there_old_request() of
true -> queue:in(RQueue, Request);
%% then send the request
false -> gen_tcp:send(Request)
end.
httpc_handler:handle_response(Response) ->
send_back(Response),
case queue:out(RQueue) of
undefined -> ...;
%% send the next request
Request -> gen_tcp:send(Request), ...
end.
但事实上,inets和ibrowse的实现就像:
httpc_handler:handle_request(Request, keepalive) ->
%% send without check
gen_tcp:send(Request),
case is_there_old_request() of
true -> queue:in(RQueue, Request);
false -> ...
end.
httpc_handler:handle_response(Response) ->
send_back(Response),
case queue:out(RQueue) of
undefined -> ...;
Request -> receive_next_response
end.
我认为它实际上是管道'模式没有幂等限制。
那么,我在代码中遗漏了什么,或者只是误解了RFC?
答案 0 :(得分:1)
问题已由提交修复:
https://github.com/RYTong/otp/commit/d3e737dd9034e693203d7907797c0df8af6100e9
在erlang OTP R16中。
答案 1 :(得分:0)
在查看最新的OTP源之后,幂等逻辑实际上在httpc_manager:select_session
中。如果请求不是幂等的,则返回no_connection
,提示系统创建新连接。整个过程中存在进一步的逻辑,但我确实在httpc_handler
中确定了用于处理流水线操作和保持活动的单独函数。