1

Is it possible to configure NGINX loadbalancer in least_conn mode to make exception for certain paths?

I want to configure loadbalancer in such way that all requests required for single login operation are sent to the same backend application instance.

I have frontend app accessing duplicated backend app via nginx load balancer. All apps are deployed on Tomcat 8.5 and backend instances have configured session replication between Tomcats.

My problem is that when user is authenticated using OAuth-2.0 authorization_code grant method, frontend app gets authorization code but due to conneting to backend through load balancer it tries to obtain token using this code from another machine resulting in InvalidGrantException.

Using ip_hash mode or it's variations isn't solution for this problem as it is unstable when application is accessed through VPN.

1 Answers1

1

Yes you can achieve what you want by declaring two locations and treat them differently. See example below and check this question where it explains how the priority works.

http {
  upstream myapp1 {
    least_conn;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
  }

  server {
    listen 80;

    location / {
        proxy_pass http://myapp1;
    }

    location /my-special-path/ {
        proxy_pass http://srv1.example.com;
    }
  }
}

Above is a solution mainly based in your first statement that you want routing based on certain paths. If your problem is more complicated i.e these paths are dynamically created etc you can share an example to be easier to understand your specific situation.

UPDATE

Based on comment. I would really suggest to go troubleshoot your backend in order to be synced. That being said if you really want a solution for the exact problem from your nginx I would do the following:

  1. On every response I would add a specific header which specific backend answered this request. add_header X-Upstream $upstream_addr;
  2. On this specific path I would serve the request based on the value of that header. proxy_pass http://$http_x_upstream;

So the config would look like this:

http {
  ...

  server {
  ...
    location / {
        add_header  X-Upstream  $upstream_addr always;
        proxy_pass http://myapp1;
    }

    location /authorize/ {
        add_header  X-Upstream  $upstream_addr always;
        proxy_pass http://$http_x_upstream;
    }
  }
}

NOTE: Security. If you go down this path be careful that you are routing your requests based on a value that your client can manipulate. So be sure that you are at least validating this value. Check this answer for validating headers with nginx.

zochamx
  • 850
  • 8
  • 17
  • Thank you for you answer. What I precisely want is to pass two consecutive requests for certain path always to the same machine. There are always two requests for /authorize path when user logs in. The problem is that this second request uses Oauth 2.0 authorization_code that needs to be passed to the same machine to obtain token. I don't know why, but even though the session between backend apps is replicated the code is valid only on the instance that issued it. – Karol Piaśnik Aug 13 '19 at 07:24
  • I updated the answer based on your comment, I think now it suits better your use case. – zochamx Aug 13 '19 at 08:31
  • This answer was most helpful, although it wasn't sufficient. I will post an answer later if I can. – Karol Piaśnik Aug 23 '19 at 08:54