I have one tomcat instance serving requests and I have nginx as reverse-proxy for this tomcat instance.

When I update my Java Application, it took around 10 seconds. But those 10 seconds site is down and nginx returns HTTP 503 page.

What I would like for nginx to do is: pause all incoming connections until backend is up. Then start to serve them. Ideally do some intelligent check, e.g. "/" returns HTTP 200. In my opinion it's better for user to wait 10 seconds than see HTTP 503 page.

I don't want clustering for that. I use in-app caches and my web application is far from high loaded. Clustering would introduce a lot of problems I don't want to spend time on.

I use the following directive to connect to tomcat:

proxy_pass  ;
  • For me, simplest way would be use two upstreams and upgrade them sequentially – Alexey Ten Mar 13 '15 at 8:35

If you are using fastcgi to communicate with the application, then set the fastcgi_read_timeout, fastcgi_connect_timeout and fastcgi_send_timeout to the desired value who is acceptable to nginx "hold" the client and wait for the application response. (i.e. 60 seconds)

The browser will remain blank until the application response, will wait up to 60 seconds to throw 503 (service unavaliable) or 504 (gateway timeout), but the socket/port on the application must be listening even with high load or the nginx can receive a "connection refused" from the backend and throw 503 to the client. If your application is crashing and removing the socket or closing the listening port I'm not 100% sure if these tuning will help you, but is good to have them configured.

If you are talking with the application via proxy, the the names of the right variables are proxy_read_timeout, proxy_connect_timeout and proxy_send_timeout.

Maybe you only need the read and connect ones.

| improve this answer | |
  • 1
    I guess it will not help. While server is down OS will close any connection to unlistened port, so there will be nothing to wait – Alexey Ten Mar 13 '15 at 6:04
  • I'm not too familiarized with tomcat, but I think who you can do a graceful "restart" after the deploy. Please, correct me if I'm wrong. – fgbreel Mar 13 '15 at 6:11
  • If there was graceful restart (like nginx's reload) there would be no problem with downtime. – Alexey Ten Mar 13 '15 at 6:28
  • The closest you can can get from a graceful restart is tomcat's context reloading, see my answer. – Xavier Lucas Mar 15 '15 at 13:29

The best way to do this depends on the nature of the content delivered by tomcat.

  • If the content generated by tomcat can't be cached on nginx's side, increase proxy_connect_timeout and proxy_read_timeout to 10s and use context reloading instead of restarting tomcat (set reloadable=true in your context file or use JMX/Tomcat manager calls to force webapp reloading e.g. http://[hostname]:[port]/manager/reload?path=[/path/to/your/webapp]).

  • If the content generated by tomcat can be cached on nginx's side, then you can take the previous procedure but set timeouts to some reasonable values. Then throw more things into your configuration : use proxy_cache_use_stale, proxy_cache_lock and proxy_cache_lock_timeout together to serve a stale page to your visitor while you allow one request at a time to try to update the cache, avoiding higher reponse times on app redeployment.

You may also look for the third party module upstream_check_module (or use a fork like tengine that implements this natively) for smarter healtcheck.

If you can afford it, you can also use the commercial edition of nginx called nginx plus that implements this natively (and allows smarter conditions for http checks) with health_check and match directives.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.