Pārlūkot izejas kodu

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

Add initial tests

Newlines

Remove unused variable

Co-authored-by: Richard Hansen <rhansen@rhansen.org>

Change comment value

Co-authored-by: Richard Hansen <rhansen@rhansen.org>

add missing services line

Co-authored-by: Richard Hansen <rhansen@rhansen.org>

Use deploy.replicas

Remove details about choosing a load balancing method

Feedback note

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>
Niek 2 gadi atpakaļ
vecāks
revīzija
7ca1da8358
4 mainītis faili ar 84 papildinājumiem un 0 dzēšanām
  1. 36 0
      README.md
  2. 5 0
      nginx.tmpl
  3. 16 0
      test/test_loadbalancing.py
  4. 27 0
      test/test_loadbalancing.yml

+ 36 - 0
README.md

@@ -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**

+ 5 - 0
nginx.tmpl

@@ -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 }}

+ 16 - 0
test/test_loadbalancing.py

@@ -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 - 0
test/test_loadbalancing.yml

@@ -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