Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for HTTP load balancing between the proxy and upstream server groups #2173

Merged
merged 2 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,42 @@ docker run -d -p 80:80 -p 443:443 \

You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html)

### Upstream (Backend) Server HTTP Load Balancing Support

> **Warning**
> This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2195](https://github.com/nginx-proxy/nginx-proxy/discussions/2195). Once we have collected enough feedback we will promote this feature to officially supported.

If you have multiple containers with the same `VIRTUAL_HOST` and `VIRTUAL_PATH` settings, nginx will spread the load across all of them. To change the load balancing algorithm from nginx's default (round-robin), set the `com.github.nginx-proxy.nginx-proxy.loadbalance` label on one or more of your application containers to the desired load balancing directive. See the [`ngx_http_upstream_module` documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html) for available directives.

> **Note**
> * Don't forget the terminating semicolon (`;`).
> * If you are using Docker Compose, remember to escape any dollar sign (`$`) characters (`$` becomes `$$`).

Docker Compose example:

```yaml
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
HTTPS_METHOD: nohttps
myapp:
image: jwilder/whoami
expose:
- "8000"
environment:
VIRTUAL_HOST: myapp.example
VIRTUAL_PORT: "8000"
labels:
com.github.nginx-proxy.nginx-proxy.loadbalance: "hash $$remote_addr;"
deploy:
replicas: 4
```

### Upstream (Backend) Server HTTP Keep-Alive Support

> **Warning**
Expand Down
5 changes: 5 additions & 0 deletions nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
{{- define "upstream" }}
upstream {{ .Upstream }} {
{{- $server_found := false }}
{{- $loadbalance := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.loadbalance")) }}
{{- if $loadbalance }}
# From the container's loadbalance label:
{{ $loadbalance }}
{{- end }}
{{- range $container := .Containers }}
# Container: {{ $container.Name }}
{{- $args := dict "globals" $.globals "container" $container }}
Expand Down
16 changes: 16 additions & 0 deletions test/test_loadbalancing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pytest
import re

def test_loadbalance_hash(docker_compose, nginxproxy):
conf = nginxproxy.get_conf().decode('ASCII')
r1 = nginxproxy.get("http://loadbalance-enabled.nginx-proxy.tld")
r2 = nginxproxy.get("http://loadbalance-enabled.nginx-proxy.tld")
assert re.search(r"hash \$remote_addr\;", conf)
assert r1.status_code == 200
assert r2.text == r1.text

def test_loadbalance_roundrobin(docker_compose, nginxproxy):
r1 = nginxproxy.get("http://loadbalance-disabled.nginx-proxy.tld")
r2 = nginxproxy.get("http://loadbalance-disabled.nginx-proxy.tld")
assert r1.status_code == 200
assert r2.text != r1.text
27 changes: 27 additions & 0 deletions test/test_loadbalancing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
services:
loadbalance-hash:
image: web
expose:
- "81"
environment:
WEB_PORTS: 81
VIRTUAL_HOST: loadbalance-enabled.nginx-proxy.tld
labels:
com.github.nginx-proxy.nginx-proxy.loadbalance: "hash $$remote_addr;"
deploy:
replicas: 2

loadbalance-roundrobin:
image: web
expose:
- "82"
environment:
WEB_PORTS: 82
VIRTUAL_HOST: loadbalance-disabled.nginx-proxy.tld
deploy:
replicas: 2

sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro