proxied request hang when DNS server down

Ruslan Ermilov ru at nginx.com
Wed Aug 20 07:58:44 UTC 2014


On Tue, Aug 19, 2014 at 01:43:06PM +0800, ywsample wrote:
> http {
>     resolver 127.0.0.1;
>     resolver_timeout 1s;
>     server {
>         listen 8000;
>         location /test {
>             proxy_pass http://$arg_host:8080;
>         }
>     }
>     server {
>         listen 8080;
>         .......
>     }
> }
> ps: other configure is normal
> 
> I have recently discoverd that when DNS server down, the first proxy
> request return 504 and than the follow proxy request may hang forever.
> I use two curl simulate concurrent requests
> 
> I found than the first request timeout in 1 second and exit, also it delete
> the timeout timer. because another request waiting dns response, so nginx
> retry send dns query, but dns never response(because it down), it lead to
> the follow request hang and also no timer relate to it;
> 
> PS:base on nginx-1.7.4

Please try the attached patch.  If you would like an attribution
in a commit log, please tell me your real name.
-------------- next part --------------
# HG changeset patch
# User Ruslan Ermilov <ru at nginx.com>
# Date 1408448606 -14400
#      Tue Aug 19 15:43:26 2014 +0400
# Node ID f70b61673e6d536831527f3a27d0b32753180374
# Parent  18daf56f477c7f264243937cdca2e35797d9afb9
Resolver: notify all waiting requests on timeout.

If a "resolver_timeout" occurs, only the first waiting request
was notified.  Other requests may hang forever.

diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -664,7 +664,7 @@ ngx_resolve_name_locked(ngx_resolver_t *
         }
 
         ctx->event->handler = ngx_resolver_timeout_handler;
-        ctx->event->data = ctx;
+        ctx->event->data = rn;
         ctx->event->log = r->log;
         ctx->ident = -1;
 
@@ -857,7 +857,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
     }
 
     ctx->event->handler = ngx_resolver_timeout_handler;
-    ctx->event->data = ctx;
+    ctx->event->data = rn;
     ctx->event->log = r->log;
     ctx->ident = -1;
 
@@ -2790,13 +2790,20 @@ done:
 static void
 ngx_resolver_timeout_handler(ngx_event_t *ev)
 {
-    ngx_resolver_ctx_t  *ctx;
-
-    ctx = ev->data;
-
-    ctx->state = NGX_RESOLVE_TIMEDOUT;
-
-    ctx->handler(ctx);
+    ngx_resolver_ctx_t   *ctx, *next;
+    ngx_resolver_node_t  *rn;
+
+    rn = ev->data;
+    ctx = rn->waiting;
+
+    do {
+        ctx->state = NGX_RESOLVE_TIMEDOUT;
+        next = ctx->next;
+
+        ctx->handler(ctx);
+
+        ctx = next;
+    } while (ctx);
 }
 
 


More information about the nginx mailing list