当我们有 TCP/IP 时,为什么 HTTP 操作需要幂等?
如果 TCP/IP 是一个可靠的协议,可以代表我们重试请求,为什么我们需要 HTTP GET、PUT 或 DELETE 来实现幂等呢?
Why do we need HTTP GET, PUT, or DELETE to be idempotent if TCP/IP is a reliable protocol that will retry requests on our behalf?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
TCP/IP 不会重试请求,而是在必要时重新传输构成每个请求的原始数据包。
如果请求失败(在 HTTP 层),则由客户端重试,而不是网络堆栈。
特别是,如果客户端(无论出于何种原因)未能收到指示 RESTful 操作是否成功的响应代码,则客户端必须能够重新发送相同的操作,而不必担心任何意外的副作用。
这些故障可能发生 - 当服务器处理操作时,中间防火墙可能使连接超时。服务器不会知道发生了这种情况,一旦收到请求,它就必须继续执行。
TCP/IP does not retry requests, it retransmits the original packets that make up each request, if necessary.
If a request fails (at the HTTP layer) it's the job of the client to retry it, not the network stack.
In particular, if the client (for what ever reason) fails to receive the response code indicating whether a RESTful operation succeeded or not, the client must be able to resend the same operation without having to worry about any unintended side effects.
These failures can happen - an intermediate firewall might have timed-out the connection while the server was processing the operation. The server won't know that this has happened, as soon as it has received the request it has to carry on regardless.
HTTP 的 GET、PUT 和 DELETE 是幂等的,因为在某些网络故障模式下,客户端无法知道请求是否完成或完成程度如何。
例如,如果客户端请求删除某个资源,但服务器在客户端收到完整响应之前关闭了连接,则客户端不知道该资源是否被删除。然后客户端就会陷入困境:也许操作失败,在这种情况下应该重新发送 DELETE 以便将应用程序推进到所需的状态。但也许它成功了;如果我重试,发送相同的 DELETE 请求会起作用吗?也许它会起作用。也许它会返回 500 错误(这只会增加客户端的困惑)。也许它将适用于不同的资源!幂等性要求使客户端确信他们可以重试请求并使其正常工作。这并不意味着您会得到完全相同的响应;第一个请求可能会收到 200 OK,第二个请求可能会收到 404 Not Found 或 410 Gone。但客户不必担心重试会产生意想不到的副作用。
HTTP's GET, PUT, and DELETE are idempotent because, in some network failure modes, the client cannot know whether the request completed or how fully.
For example, if a client requests a DELETE of a resource, but the server closes the connection before the complete response is received by the client, the client does not know whether the resource was deleted or not. The client then has a dilemma: perhaps the operation failed, in which case the DELETE should be re-sent in order to advance the application to the desired state. But perhaps it succeeded; will sending the same DELETE request work if I retry? Perhaps it will work. Perhaps it will return a 500 error (which just adds to the client's confusion). Perhaps it will apply to a different resource! The idempotency requirement allows the client to be confident that they can retry the request and have it work. That doesn't mean you'll get exactly the same response; the first request might receive 200 OK and the second 404 Not Found or 410 Gone. But the client doesn't have to worry about unintended side-effects from retries.
您似乎将 HTTP 协议级别的幂等性与 TCP 级别的字节流可靠性混淆了。
HTTP 幂等性:
幂等(维基百科) 表示发送相同的 HTTP 请求 10 次具有相同的效果效果和做一次一样。
TCP 可靠性:
如果在 TCP 流中丢失数据包,则会重新传输该数据包。但应用程序协议 (HTTP) 并不知道 TCP 必须重新传输数据包。
即使包含完整 HTTP 请求的单个数据包通过 TCP 重传 10 次,浏览器/服务器也只会看到一个 HTTP 请求。 TCP 重传的原因是由于数据包丢失,但应用程序协议(如 HTTP)不知道 TCP 必须重传。它们看起来是相同的请求,有或没有丢包
You seem to be confusing Idempotency at the HTTP-protocol level with byte-stream reliability at the TCP level.
HTTP Idempotency:
Idempotent (wikipedia) means that sending the same HTTP request 10 times has the same effect as doing it once.
TCP reliability:
If you lose a packet in a TCP stream, it will be retransmitted. But the application-protocol (HTTP) has no knowledge that TCP had to retransmit packets.
Even if an individual packet containing a complete HTTP request is retransmitted 10 times by TCP, the browser/server will only see one HTTP request. The reason TCP retransmits is because of packet loss, but application-protocols (like HTTP) have no knowledge that TCP had to retransmit. They seem the same request with or without packet loss