upstream 429 and non-idempotent request
mdounin at mdounin.ru
Tue Jun 13 16:30:47 UTC 2017
On Thu, Jun 08, 2017 at 09:55:05AM -0700, Frank Liu wrote:
> I fully understand the rationale of not retrying non-idempotent requests if
> they are already sent, but in case of 429 (maybe other cases as well), I
> don't see an issue of retrying even if request is sent. It would be better
> if we can selectively do something like "proxy_next_upstream
> non-idempotent-http_429;" or whatever http code that we know safe.
The problem is that we don't really know if the code is safe or
In general, non-idempotent requests are not retried as we
don't know if the request was processed or not. The situation is
obvious when we got a network error after sending a request: as
the error might happen after the request was already processed, it
is wise to refrain from retrying it.
But what happen when we got a valid http error instead? For
example, 502 in most cases means that there was a network error
somewhere else. So, this basically means that 502 cannot be
retried as well. And the other 5xx error codes are more or less
identical: we never know what really happened, and can't retry.
With 4xx errors it seems safe to assume that the request was not
processed, and hence retrying is possible. But, for example, if
error_page is used on the backend server, 404 might be returned
if a network error happens and a corresponding error page cannot
be found. Similarly, 429 might be returned if limit_req rejects a
request to the error page.
We've considered adding a logic to always retry non-idempotent
requests in case of 4xx errors when non-idempotence handing was
introduced. But decided to keep things simple and safe, and never
retry non-idempotent requests. On the other hand, introducing
configuration options to fine tune if non-idempotent requests
should be retried for each proxy_next_upstream case seems to be
In general, current implementation assumes the following two
- non-idempotent requests are not retried;
- there is a duplicate request protection in the application, so
non-dempotent requests can be retried with "proxy_next_upstream
This seems to be enough for most, if not all, use cases. If
something more complex is really needed, it can be configured
using error_page and additional error processing logic.
More information about the nginx