NGINX Load Balancing - HTTP Load Balancer

时间:2022-02-14 14:47:06

This chapter describes how to use NGINX and NGINX Plus as a load balancer.

Overview

Load balancing across multiple application instances is a commonly used technique for optimizing resource utilization, maximizing throughput, reducing latency, and ensuring fault‑tolerant configurations.

Watch the NGINX Plus for Load Balancing and Scaling webinar on demand for a deep dive on techniques that NGINX users employ to build large‑scale, highly available web services.

NGINX and NGINX Plus can be used in different deployment scenarios as a very efficient HTTP load balancer.

Proxying HTTP Traffic to a Group of Servers

To start using NGINX Plus or NGINX to load balance HTTP traffic to a group of servers, first you need to define the group with the upstream directive. The directive is placed in the http context.

Servers in the group are configured using the server directive (not to be confused with the server block that defines a virtual server running on NGINX). For example, the following configuration defines a group named backend and consists of three server configurations (which may resolve in more than three actual servers):

http {
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com;
server 192.0.0.1 backup;
}
}

To pass requests to a server group, the name of the group is specified in the proxy_pass directive (or the fastcgi_passmemcached_passscgi_pass, or uwsgi_passdirectives for those protocols.) In the next example, a virtual server running on NGINX passes all requests to the backend upstream group defined in the previous example:

server {
location / {
proxy_pass http://backend;
}
}

The following example combines the two snippets above and shows how to proxy HTTP requests to the backend server group. The group consists of three servers, two of them running instances of the same application while the third is a backup server. Because no load‑balancing algorithm is specified in the upstream block, NGINX uses the default algorithm, Round Robin:

http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
} server {
location / {
proxy_pass http://backend;
}
}
}

Choosing a Load-Balancing Method

Open source NGINX supports four load‑balancing methods, and NGINX Plus adds a fifth method:

  1. Round Robin – Requests are distributed evenly across the servers, with server weights taken into consideration. This method is used by default (there is no directive for enabling it):

    upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    }
  2. Least Connections – A request is sent to the server with the least number of active connections, again with server weights taken into consideration:

    upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
    }
  3. IP Hash – The server to which a request is sent is determined from the client IP address. In this case, either the first three octets of the IPv4 address or the whole IPv6 address are used to calculate the hash value. The method guarantees that requests from the same address get to the same server unless it is not available.

    upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    }

    If one of the servers needs to be temporarily removed from the load‑balancing rotation, it can be marked with the down parameter in order to preserve the current hashing of client IP addresses. Requests that were to be processed by this server are automatically sent to the next server in the group:

    upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    }
  4. Generic Hash – The server to which a request is sent is determined from a user‑defined key which can be a text string, variable, or a combination. For example, the key may be a paired source IP address and port, or a URI as in this example:

    upstream backend {
    hash $request_uri consistent;
    server backend1.example.com;
    server backend2.example.com;
    }

    The optional consistent parameter to the hash directive enables ketama consistent‑hash load balancing. Requests are evenly distributed across all upstream servers based on the user‑defined hashed key value. If an upstream server is added to or removed from an upstream group, only a few keys are remapped which minimizes cache misses in the case of load‑balancing cache servers or other applications that accumulate state.

  5. Least Time (NGINX Plus only) – For each request, NGINX Plus selects the server with the lowest average latency and the lowest number of active connections, where the lowest average latency is calculated based on which of the following parameters to the least_time directive is included:

    • header – Time to receive the first byte from the server
    • last_byte – Time to receive the full response from the server
    upstream backend {
    least_time header;
    server backend1.example.com;
    server backend2.example.com;
    }

Note: When configuring any method other than Round Robin, put the corresponding directive (haship_hashleast_conn, or least_time) above the list of server directives in the upstream block.

Server Weights

By default, NGINX distributes requests among the servers in the group according to their weights using the Round Robin method. The weight parameter to the server directive sets the weight of a server; the default is 1:

upstream backend {
server backend1.example.com weight=5;
server backend2.example.com;
server 192.0.0.1 backup;
}

In the example, backend1.example.com has weight 5; the other two servers have the default weight (1), but the one with IP address 192.0.0.1 is marked as a backup server and does not receive requests unless both of the other servers are unavailable. With this configuration of weights, out of every six requests, five are sent to backend1.example.com and one to backend2.example.com.

Server Slow-Start

The server slow‑start feature prevents a recently recovered server from being overwhelmed by connections, which may time out and cause the server to be marked as failed again.

In NGINX Plus, slow‑start allows an upstream server to gradually recover its weight from zero to its nominal value after it has been recovered or became available. This can be done with the slow_start parameter to the server directive:

upstream backend {
server backend1.example.com slow_start=30s;
server backend2.example.com;
server 192.0.0.1 backup;
}

The time value (here, 30 seconds) sets the time during which NGINX Plus ramps up the number of connections to the server to the full value.

Note that if there is only a single server in a group, the max_failsfail_timeout, and slow_start parameters to the server directive are ignored and the server is never considered unavailable.

Enabling Session Persistence

Session persistence means that NGINX Plus identifies user sessions and routes all requests in a given session to the same upstream server.

NGINX Plus supports three session persistence methods. The methods are set with the sticky directive. (For session persistence with NGINX OSS, use the hash or ip_hashdirective as described above.)

  • Sticky cookie – NGINX Plus adds a session cookie to the first response from the upstream group and identifies the server that sent the response. The client’s next request contains the cookie value and NGINX Plus route the request to the upstream server that responded to the first request:

    upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    sticky cookie srv_id expires=1h domain=.example.com path=/;
    }

    In the example, the srv_id parameter sets the name of the cookie. The optional expires parameter sets the time for the browser to keep the cookie (here, 1 hour). The optional domain parameter defines the domain for which the cookie is set, and the optional path parameter defines the path for which the cookie is set. This is the simplest session persistence method.

  • Sticky route – NGINX Plus assigns a “route” to the client when it receives the first request. All subsequent requests are compared to the route parameter of the serverdirective to identify the server to which the request is proxied. The route information is taken from either a cookie or the request URI.

    upstream backend {
    server backend1.example.com route=a;
    server backend2.example.com route=b;
    sticky route $route_cookie $route_uri;
    }
  • Cookie learn method – NGINX Plus first finds session identifiers by inspecting requests and responses. Then NGINX Plus “learns” which upstream server corresponds to which session identifier. Generally, these identifiers are passed in a HTTP cookie. If a request contains a session identifier already “learned”, NGINX Plus forwards the request to the corresponding server:

    upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    sticky learn
    create=$upstream_cookie_examplecookie
    lookup=$cookie_examplecookie
    zone=client_sessions:1m
    timeout=1h;
    }

    In the example, one of the upstream servers creates a session by setting the cookie EXAMPLECOOKIE in the response.

    The mandatory create parameter specifies a variable that indicates how a new session is created. In the example, new sessions are created from the cookie EXAMPLECOOKIEsent by the upstream server.

    The mandatory lookup parameter specifies how to search for existing sessions. In our example, existing sessions are searched in the cookie EXAMPLECOOKIE sent by the client.

    The mandatory zone parameter specifies a shared memory zone where all information about sticky sessions is kept. In our example, the zone is named client_sessions and is 1 megabyte in size.

    This is a more sophisticated session persistence method than the previous two as it does not require keeping any cookies on the client side: all info is kept server‑side in the shared memory zone.

Limiting the Number of Connections

With NGINX Plus, it is possible to limit the number of connections to an upstream server by specifying the maximum number with the max_conns parameter.

If the max_conns limit has been reached, the request is placed in a queue for further processing, provided that the queue directive is also included to set the maximum number of requests that can be simultaneously in the queue:

upstream backend {
server backend1.example.com max_conns=3;
server backend2.example.com;
queue 100 timeout=70;
}

If the queue is filled up with requests or the upstream server cannot be selected during the timeout specified by the optional timeout parameter, the client receives an error.

Note that the max_conns limit is ignored if there are idle keepalive connections opened in other worker processes. As a result, the total number of connections to the server might exceed the max_conns value in a configuration where the memory is shared with multiple worker processes.

Passive Health Checks

When NGINX considers a server unavailable, it temporarily stops sending requests to the server until it is considered active again. The following parameters to the server directive configure the conditions under which NGINX considers a server unavailable:

  • max_fails – Sets the number of consecutive failed attempts after which NGINX marks the server as unavailable.
  • fail_timeout – Sets the time during which the number of failed attempts specified by the max_fails parameter must happen for the server to be considered unavailable, and also the length of time that NGINX considers the server unavailable after it is marked so.

The default values are 1 attempt and 10 seconds. So if a server does not accept or does not respond to a (that is, one) request, NGINX immediately considers the server unavailable for 10 seconds. The following example shows how to set these parameters:

upstream backend {
server backend1.example.com;
server backend2.example.com max_fails=3 fail_timeout=30s;
server backend3.example.com max_fails=2;
}

Active Health Checks

Next are some more sophisticated features for tracking server availability in NGINX Plus.

Periodically sending special requests to each server and checking for a response that satisfies certain conditions can monitor the availability of servers.

To enable this type of health monitoring in your nginx.conf file, include the health_check directive in the the location that passes requests to an upstream group. In addition, the upstream group must include the zone directive to define a shared‑memory zone where information about health status is stored:

http {
upstream backend {
zone backend 64k;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
server {
location / {
proxy_pass http://backend;
health_check;
}
}
}

This configuration defines the upstream group backend and a virtual server with a single location that passes all requests (represented by /) to backend.

The zone directive defines a memory zone that is shared among worker processes and is used to store the configuration of the server group. This enables the worker processes to use the same set of counters to keep track of responses from the upstream servers. The zone directive is also required for dynamic configuration of the upstream group.

The health_check directive without any parameters configures health monitoring with the default settings: every 5 seconds NGINX Plus sends a request for / to each server in the backend group. If any communication error or timeout occurs (or a proxied server responds with a status code other than 2_xx_ or 3_xx_) the health check fails for that server. Any server that fails a health check is considered unhealthy, and NGINX Plus stops sending client requests to it until it once again passes a health check.

The default behavior can be overridden using the parameters to the health_check directive. Here, the interval parameter reduces the duration between health checks to 5 seconds. The fails=3 parameter means a server is considered unhealthy after 3 consecutive failed health checks instead of the default 1. With the passes parameter, a server needs to pass 2 consecutive checks (rather than 1) to be considered healthy again.

To define the URI to request (here, /some/path) instead of the default /, include the uri parameter. The URI is appended to the server’s domain name or IP address as specified by the server directive in the upstream block. For example, for the first server in the backend group configured above, the health check is a request for http://backend1.example.com/some/path.

location / {
proxy_pass http://backend;
health_check interval=5 fails=3 passes=2 uri=/some/path;
}

Finally, you can set custom conditions that a response must satisfy for NGINX Plus to consider the server healthy. The conditions are specified in the match block, which is then referenced by the health_check directive’s match parameter.

http {
# ...
match server_ok {
status 200-399;
body !~ "maintenance mode";
} server {
# ...
location / {
proxy_pass http://backend;
health_check match=server_ok;
}
}
}

Here the health check is passed if the status code in the response is in the range from 200 to 399, and the response body does not match the specified regular expression.

The match directive enables NGINX Plus to check the status, header fields, and the body of a response. Using this directive it is possible to verify whether the status code is in a specified range, the response includes a header, or the header or body matches a regular expression (in any combination). The match directive can contain one status condition, one body condition, and multiple header conditions. For the health check to succeed, the response must satisfy all of the conditions specified in the match block.

For example, the following match block requires that responses have status code 200, include the Content-Type header with the exact value text/html, and contain the text “Welcome to nginx!” in the body:

match welcome {
status 200;
header Content-Type = text/html;
body ~ "Welcome to nginx!";
}

In the following example of using the exclamation point (!), the block matches responses where the status code is anything other than 301302303, and 307, and Refresh is not among the headers.

match not_redirect {
status ! 301-303 307;
header ! Refresh;
}

Health checks can also be enabled for the non‑HTTP protocols that NGINX Plus proxies: FastCGImemcachedSCGI, and uwsgi.

Sharing Data with Multiple Worker Processes

If an upstream block does not include the zone directive, each worker process keeps its own copy of the server group configuration and maintains its own set of related counters. The counters include the current number of connections to each server in the group and the number of failed attempts to pass a request to a server. As a result, the server group configuration cannot be modified dynamically.

When the zone directive is included in an upstream block, the configuration of the upstream group is kept in a memory area shared among all worker processes. This scenario is dynamically configurable, because the worker processes access the same copy of the group configuration and utilize the same related counters.

The zone directive is mandatory for active health checks and dynamic reconfiguration of the upstream group. However, other features of upstream groups can benefit from the use of this directive as well.

For example, if the configuration of a group is not shared, each worker process maintains its own counter for failed attempts to pass a request to a server (set by the max_failsparameter). In this case, each request gets to only one worker process. When the worker process that is selected to process a request fails to transmit the request to a server, other worker processes don’t know anything about it. While some worker process can consider a server unavailable, others might still send requests to this server. For a server to be definitively considered unavailable, the number of failed attempts during the timeframe set by the fail_timeout parameter must equal max_fails multiplied by the number of worker processes. On the other hand, the zone directive guarantees the expected behavior.

Similarly, the Least Connections load‑balancing method might not work as expected without the zone directive, at least under low load. This method passes a request to the server with the smallest number of active connections. If the configuration of the group is not shared, each worker process uses its own counter for the number of connections and might send a request to the same server that another worker process just sent a request to. However, you can increase the number of requests to reduce this effect. Under high load requests are distributed among worker processes evenly, and the Least Connections method works as expected.

Setting the Zone Size

It is not possible to recommend an ideal memory‑zone size, because usage patterns vary widely. The required amount of memory is determined by which features (such as session persistencehealth checks, or DNS re‑resolving) are enabled and how the upstream servers are identified.

As an example, with the sticky_route session persistence method and a single health check enabled, a 256‑KB zone can accommodate information about the indicated number of upstream servers:

  • 128 servers (each defined as an IP‑address:port pair)
  • 88 servers (each defined as hostname:port pair where the hostname resolves to a single IP address)
  • 12 servers (each defined as hostname:port pair where the hostname resolves to multiple IP addresses)

Configuring HTTP Load Balancing Using DNS

The configuration of a server group can be modified at runtime using DNS.

For servers in an upstream group that are identified with a domain name in the server directive, NGINX Plus can monitor changes to the list of IP addresses in the corresponding DNS record, and automatically apply the changes to load balancing for the upstream group, without requiring a restart. This can be done by including the resolver directive in the http block along with the resolve parameter to the server directive:

http {
resolver 10.0.0.1 valid=300s ipv6=off;
resolver_timeout 10s;
server {
location / {
proxy_pass http://backend;
}
}
upstream backend {
zone backend 32k;
least_conn;
# ...
server backend1.example.com resolve;
server backend2.example.com resolve;
}
}

In the example, the resolve parameter to the server directive tells NGINX Plus to periodically re‑resolve the backend1.example.com and backend2.example.com domain names into IP addresses.

The resolver directive defines the IP address of the DNS server to which NGINX Plus sends requests (here, 10.0.0.1). By default, NGINX Plus re‑resolves DNS records at the frequency specified by time‑to‑live (TTL) in the record, but you can override the TTL value with the valid parameter; in the example it is 300 seconds, or 5 minutes.

The optional ipv6=off parameter means only IPv4 addresses are used for load balancing, though resolving of both IPv4 and IPv6 addresses is supported by default.

If a domain name resolves to several IP addresses, the addresses are saved to the upstream configuration and load balanced. In our example, the servers are load balanced according to the Least Connections load‑balancing method. If the list of IP addresses for a server has changed, NGINX Plus immediately starts load balancing across the new set of addresses.

Load Balancing of Microsoft Exchange Servers

In NGINX Plus R7 and later, NGINX Plus can proxy Microsoft Exchange traffic to a server or a group of servers and load balance it.

To set up load balancing of Microsoft Exchange servers:

  1. In a location block, configure proxying to the upstream group of Microsoft Exchange servers with the proxy_pass directive:

    location / {
    proxy_pass https://exchange;
    # ...
    }
  2. In order for Microsoft Exchange connections to pass to the upstream servers, in the location block set the proxy_http_version directive value to 1.1, and the proxy_set_header directive to Connection "", just like for a keepalive connection:

    location / {
    # ...
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    # ...
    }
  3. In the http block, configure a upstream group of Microsoft Exchange servers with an upstream block named the same as the upstream group specified with the proxy_passdirective in Step 1. Then specify the ntlm directive to allow the servers in the group to accept requests with NTLM authentication:

    http {
    # ...
    upstream exchange {
    zone exchange 64k;
    ntlm;
    # ...
    }
    }
  4. Add Microsoft Exchange servers to the upstream group and optionally specify a load‑balancing method:

    http {
    # ...
    upstream exchange {
    zone exchange 64k;
    ntlm;
    server exchange1.example.com;
    server exchange2.example.com;
    # ...
    }
    }

Complete NTLM Example

http {
# ...
upstream exchange {
zone exchange 64k;
ntlm;
server exchange1.example.com;
server exchange2.example.com;
} server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/company.com.crt;
ssl_certificate_key /etc/nginx/ssl/company.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; location / {
proxy_pass https://exchange;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}

For more information about configuring Microsoft Exchange and NGINX Plus, see the Load Balancing Microsoft Exchange Servers with NGINX Plus deployment guide.

Dynamic Configuration Using the NGINX Plus API

With NGINX Plus, the configuration of an upstream server group can be modified dynamically using the NGINX Plus API. A configuration command can be used to view all servers or a particular server in a group, modify parameter for a particular server, and add or remove servers. For more information and instructions, see Configuring Dynamic Load Balancing with the NGINX Plus API.

NGINX Load Balancing - HTTP Load Balancer的更多相关文章

  1. Load Balancing with NGINX 负载均衡算法

    Using nginx as HTTP load balancer Using nginx as HTTP load balancer http://nginx.org/en/docs/http/lo ...

  2. How Network Load Balancing Technology Works--reference

    http://technet.microsoft.com/en-us/library/cc756878(v=ws.10).aspx In this section Network Load Balan ...

  3. Network Load Balancing Technical Overview--reference

    http://technet.microsoft.com/en-us/library/bb742455.aspx Abstract Network Load Balancing, a clusteri ...

  4. NGINX Load Balancing – TCP and UDP Load Balancer

    This chapter describes how to use NGINX Plus and open source NGINX to proxy and load balance TCP and ...

  5. NGINX Docs | Load Balancing Apache Tomcat Servers with NGINX Open Source and NGINX Plus

    NGINX Docs | Load Balancing Apache Tomcat Servers with NGINX Open Source and NGINX Plushttps://docs. ...

  6. 【高可用HA】Nginx (1) —— Mac下配置Nginx Http负载均衡(Load Balancer)之101实例

    [高可用HA]Nginx (1) -- Mac下配置Nginx Http负载均衡(Load Balancer)之101实例 nginx版本: nginx-1.9.8 参考来源: nginx.org [ ...

  7. 负载均衡(Load Balancing)学习笔记(一)

    概述 在分布式系统中,负载均衡(Load Balancing)是一种将任务分派到多个服务端进程的方法.例如,将一个HTTP请求派发到实际的Web服务器中执行的过程就涉及负载均衡的实现.一个HTTP请求 ...

  8. 【架构】How To Use HAProxy to Set Up MySQL Load Balancing

    How To Use HAProxy to Set Up MySQL Load Balancing Dec  2, 2013 MySQL, Scaling, Server Optimization U ...

  9. Scalable MySQL Cluster with Master-Slave Replication, ProxySQL Load Balancing and Orchestrator

    MySQL is one of the most popular open-source relational databases, used by lots of projects around t ...

随机推荐

  1. 分享一个基于HTML5实现的视频播放器

    什么是hivideo? 最近一段时间在使用PhoneGap开发一个App应用,App需要播放视频,本想直接使用html5的video,但使用它在全屏播放时不支持横屏播放,只能放弃.最终决定还是自己封装 ...

  2. 使SWT/JFace支持跨平台

    由于SWT的实现机制,在不同平台下,必须引用不同swt*.jar. 由于这个瓶颈,我们要为不同的平台编译不同的版本.但是这是可以避免的.这将是本文要讨论的内容. 我一共google到了3种soluti ...

  3. ASP.NET POST XML JSON数据,发送与接收

    接收端通过Request.InputStream读取:byte[] byts = new byte[Request.InputStream.Length];Request.InputStream.Re ...

  4. angular的directive笔记

    原贴地址 1,tansclude: 是指令能够能够把外部定义的内容传回指令模板内部(通过在内部标签使用ng-transclude).这个外部指定的内容是根据外部的作用域控制的,跟指令的作用域无关.这个 ...

  5. HTML之正则表达式

    匹配国内电话号码:d{3}-d{8}|d{4}-d{7} 评注:匹配形式如 0511-4405222 或 021-87888822 匹配腾讯QQ号:[1-9][0-9]{4,} 评注:腾讯QQ号从10 ...

  6. mybatis的搭建和注入spring的方式

    mybatis实际上是一个更多关注sql语句的框架,他的出现是想让开发者更简单的去操作数据库. 与hibernate相比较,hibernate更多的是去sql化,虽然hibernate也可以本地sql ...

  7. Flask学习 一 基本结构

    -from flask import Flask +from flask import Flask,render_template -from flask import request -from f ...

  8. DOS 命令 os系统(windows)

    一.cd 相关操作 1."cd .. "or "cd ..\" --返回上一级 2.cd E:\Python -- 进入目录 二.dir --drectory ...

  9. Java图片合并

    /** * 纵向合并图片,ossObject.getObjectContent()返回InputStream对象 */ private BufferedImage mergeImage(List&lt ...

  10. 使用vim打造自己的python编辑器

    基础配置 vim的配置是在用户主目录下的 ~/.vimrc 文件中完成的,如果没有的话,需要自己新建一下: cd ~ touch .vimrc 首先做些简单的配置: set nocompatible ...