使用nginx做负载均衡的两大模块:

  • upstream 定义负载节点池。
  • location 模块 进行URL匹配。
  • proxy模块 发送请求给upstream定义的节点池。

upstream模块解读

nginx 的负载均衡功能依赖于 ngx_http_upstream_module模块,所支持的代理方式有 proxy_pass(一般用于反向代理),fastcgi_pass(一般用于和动态程序交互),memcached_pass,proxy_next_upstream,fastcgi_next_pass,memcached_next_pass 。

upstream 模块应该放于http{}标签内。

模块写法:

  1. upstream backend {
  2. ip_hash;
  3. server backend1.example.com weight=5;
  4. server backend2.example.com:8080;
  5. server backup1.example.com:8080 backup;
  6. server backup2.example.com:8080 backup;
  7. }

实例一:

  1. upstream dynamic {
  2. zone upstream_dynamic 64k;
  3. server backend1.example.com weight=5;
  4. server backend2.example.com:8080 fail_timeout=5s slow_start=30s;
  5. server 192.0.2.1 max_fails=3;
  6. server backend3.example.com resolve;
  7. server backup1.example.com:8080 backup;
  8. server backup2.example.com:8080 backup;
  9. }

语法解释:

nginx默认支持四种调度算法

  • 轮询(rr),每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器故障,故障系统自动清除,使用户访问不受影响。
  • 轮询权值(weight),weight值越大,分配到的访问几率越高,主要用于后端每个服务器性能不均的情况。
  • ip_hash,每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器,主要解决动态网站session共享的问题。
  • url_hash,按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率,nginx本身不支持,如果想使用需要安装nginx的hash软件包。
  • fair,这个算法可以依据页面大小和加载时间长短智能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求,相应时间短的优先分配,默认不支持,如果想使用需要安装upstream_fail模块。
  • least_conn 最少链接数,那个机器连接数少就分发。

server模块的写法

server IP 调度状态

server指令指定后端服务器IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。

  • down 表示当前的server暂时不参与负载均衡。
  • backup 预留的备份服务器,当其他所有的非backup服务器出现故障或者忙的时候,才会请求backup机器,因为这台集群的压力最小。
  • max_fails 允许请求失败的次数,默认是1,当超过最大次数时,返回proxy_next_upstream模块定义的错误。0表示禁止失败尝试,企业场景:2-3.京东1次,蓝汛10次,根据业务需求去配置。
  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。京东是3s,蓝汛是3s,根据业务需求配置。常规业务2-3秒合理。

例:如果max_fails是5,他就检测5次,如果五次都是502.那么,他就会根据fail_timeout 的值,等待10秒,再去检测。

server 如果接域名,需要内网有DNS服务器,或者在负载均衡器的hosts文件做域名解析。server后面还可以直接接IP或IP加端口。

长连接 keepalive

  1. upstream backend {
  2. server backend2.example.com:8080;
  3. server backup1.example.com:8080 backup;
  4. keepalive 100;
  5. }

通过该指令配置了每个worker进程与上游服务器可缓存的空闲连接的最大数量。

当超出这个数量时,最近最少使用的连接将被关闭。keepalive指令不限制worker进程与上游服务器的总连接。

  1. location / {
  2. # 支持keep-alive
  3. proxy_http_version 1.1;
  4. proxy_set_header Connection "";
  5. proxy_pass http://backup;
  6. }
  • 如果是http/1.0 需要配置发送"Connection: Keep-Alive" 请求头。
  • 上游服务器不要忘记开启长连接支持。

连接池配置建议

  • 总长连接数是"空闲连接池"+"释放连接池"的长连接总数。
  • 首先,长连接配置不会限制worker进程可以打开的总连接数(超了的作为短连接)。另外连接池一定要根据场景合理进行设置。
  1. 空闲连接池太小,连接不够用,需要不断建连接。
  2. 空闲连接池太大,空闲连接太多,还没使用就超时。
  3. 建议只对小报文开启长连接。

location 模块解读

location作用:基于一个指令设置URI。

基本语法:

  1. Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
  2. location @name { ... }
  3. Default:
  4. Context: server, location
  • = 精确匹配,如果找到匹配=号的内容,立即停止搜索,并立即处理请求(优先级最高)
  • ~ 区分大小写
  • ~* 不区分大小写
  • ^~ 只匹配字符串,不匹配正则表达式
  • @ 指定一个命名的location,一般用于内部重定义请求,location @name {…}

匹配是有优先级的,不是按照nginx的配置文件进行。

官方的例子:

  1. location = / {
  2. [ configuration A ]
  3. }
  4. location / {
  5. [ configuration B ]
  6. }
  7. location /documents/ {
  8. [ configuration C ]
  9. }
  10. location ^~ /images/ {
  11. [ configuration D ]
  12. }
  13. location ~* \.(gif|jpg|jpeg)$ {
  14. [ configuration E ]
  15. }

结论:

  • / 匹配A。
  • /index.html 匹配B
  • /documents/document.html 匹配C
  • /images/1.gif 匹配D
  • /documents/1.jpg 匹配的是E。

测试用的例子:

  1. location / {
  2. return 401;
  3. }
  4. location = / {
  5. return 402;
  6. }
  7. location /documents/ {
  8. return 403;
  9. }
  10. location ^~ /images/ {
  11. return 404;
  12. }
  13. location ~* \.(gif|jpg|jpeg)$ {
  14. return 500;
  15. }

测试结果(重点看):

  1. [root@lb01 conf]# curl -I -s -o /dev/null -w "%{http_code}\n" http://10.0.0.7/
  2. 402
  3. [root@lb01 conf]# curl -I -s -o /dev/null -w "%{http_code}\n" http://10.0.0.7/index.html
  4. 401
  5. [root@lb01 conf]# curl -I -s -o /dev/null -w "%{http_code}\n" http://10.0.0.7/documents/document.html
  6. 403
  7. [root@lb01 conf]# curl -I -s -o /dev/null -w "%{http_code}\n" http://10.0.0.7/images/1.gif
  8. 404
  9. [root@lb01 conf]# curl -I -s -o /dev/null -w "%{http_code}\n" http://10.0.0.7/dddd/1.gif
  10. 500

结果总结:

匹配的优先顺序,=>^~(匹配固定字符串,忽略正则)> 完全相等>~*>>/

工作中尽量将'='放在前面

proxy_pass 模块解读

proxy_pass 指令属于ngx_http_proxy_module 模块,此模块可以将请求转发到另一台服务器。

写法:

  1. proxy_pass http://localhost:8000/uri/;

实例一:

  1. upstream blog_real_servers {
  2. server 10.0.0.9:80 weight=5;
  3. server 10.0.0.10:80 weight=10;
  4. server 10.0.0.19:82 weight=15;
  5. }
  6. server {
  7. listen 80;
  8. server_name blog.etiantian.org;
  9. location / {
  10. proxy_pass http://blog_real_servers;
  11. proxy_set_header host $host;
  12. }
  13. }
  • proxy_set_header:当后端Web服务器上也配置有多个虚拟主机时,需要用该Header来区分反向代理哪个主机名,proxy_set_header host $host;
  • proxy_set_header X-Forwarded-For :如果后端Web服务器上的程序需要获取用户IP,从该Header头获取。proxy_set_header X-Forwarded-For $remote_addr;

配置后端服务器接收前端真实IP

配置如下:


  1. log_format commonlog '$remote_addr - $remote_user [$time_local] "$request" '
  2. '$status $body_bytes_sent "$http_referer" '
  3. '"$http_user_agent" "$http_x_forwarded_for"';

rs_apache节点的httpd.conf配置

  1. LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{U
  2. ser-Agent}i\"" combined修改日志记录
  3. apache
  4. LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b" common

proxy_pass相关的优化参数

  • client_max_body_size 10m; 允许客户端请求的最大的单个文件字节数。
  • client_body_buffer_size 128k; 缓冲区代理缓冲用户端请求的最大字节数 可以理解为先保存到本地再传给用户。
  • proxy_connect_timeout 600; 跟后端服务器连接的超时时间_发起握手等候响应超时时间。
  • proxy_read_timeout 600; 连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理。
  • proxy_send_timeout 600; 后端服务器回传数据时间,就是在规定时间之内后端服务器必须传完所有的数据。
  • proxy_buffer_size 8k; 代理请求缓存区,这个缓存区间会保存用户的头信息以供Nginx进行规则处理,一般只要设置能保存下头信息即可。
  • proxy_buffers 4 32k; 同上 告诉Nginx保存单个页面使用的空间大小,假设网页大小平均在32k以下的话。
  • proxy_busy_buffers_size 64k; 如果系统很忙的时候可以申请更大的proxy_buffers 官方推荐(proxy_buffers*2)。
  • proxy_max_temp_file_size 1024m; 当 proxy_buffers 放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M,它与 proxy_cache 没有关系。大于这个值,将从upstream服务器传回。设置为0禁用。
  • proxy_temp_file_write_size 64k; proxy缓存临时文件的大小 proxy_temp_path(可以在编译的时候)指定写到哪那个目录。

健康检查

Nginx提供了health_check语句来提供负载(upstream)时的键康检查机制(注意:此语句需要设置在location上下文中)。

支持的参数有:

  • interval=time:设置两次健康检查之间的间隔值,默认为5秒
  • fails=number:设置将服务器视为不健康的连续检查次数,默认为1次
  • passes=number:设置一个服务器被视为健康的连续检查次数,默认为1次
  • uri=uri:定义健康检查的请求URI,默认为”/“
  • match=name:指定匹配配置块的名字,用记测试响应是否通过健康检测。默认为测试返回状态码为2xx和3xx

一个简单的设置如下,将使用默认值:

  1. location / {
  2. proxy_pass http://backend;
  3. health_check;
  4. }

对就应用,我们可以专门定义一个API用于健康检查:/api/health_check,并只返回HTTP状态码为200。并设置两次检查之间的间隔值为1秒。这样,health_check语句的配置如下:

  1. health_check uri="/api/health_check" interval;

匹配match的方法

  1. http {
  2. server {
  3. ...
  4. location / {
  5. proxy_pass http://backend;
  6. health_check match=welcome;
  7. }
  8. }
  9. match welcome {
  10. status 200;
  11. header Content-Type = text/html;
  12. body ~ "Welcome to nginx!";
  13. }
  14. }

match 例子举例

  • status 200;: status 等于 200
  • status ! 500;: status 不是 500
  • status 200 204;: status 是 200 或 204
  • status ! 301 302;: status 不是301或302。
  • status 200-399;: status 在 200 到 399之间。
  • status ! 400-599;: status 不在 400 到 599之间。
  • status 301-303 307;: status 是 301, 302, 303, 或 307。
  • header Content-Type = text/html;: “Content-Type” 得值是 text/html。
  • header Content-Type != text/html;: “Content-Type” 不是 text/html。
  • header Connection ~ close;: “Connection” 包含 close。
  • header Connection !~ close;: “Connection” 不包含 close。
  • header Host;: 请求头包含 “Host”。
  • header ! X-Accel-Redirect;: 请求头不包含 “X-Accel-Redirect”。
  • body ~ "Welcome to nginx!";: body 包含 “Welcome to nginx!”。
  • body !~ "Welcome to nginx!";: body 不包含 “Welcome to nginx!”。

一个完整的nginx实例

  1. [root@lb01 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. #blog lb by oldboy at 201303
  12. upstream blog_real_servers {
  13. server 10.0.0.9:80 weight=1 max_fails=1 fail_timeout=10s;
  14. server 10.0.0.10:80 weight=1 max_fails=2 fail_timeout=20s;
  15. }
  16. server {
  17. listen 80;
  18. server_name blog.etiantian.org;
  19. location / {
  20. proxy_pass http://blog_real_servers;
  21. include proxy.conf;
  22. }
  23. }
  24. }
  1. [root@lb01 conf]# cat proxy.conf
  2. proxy_set_header Host $host;
  3. proxy_set_header X-Forwarded-For $remote_addr;
  4. proxy_connect_timeout 90;
  5. proxy_send_timeout 90;
  6. proxy_read_timeout 90;
  7. proxy_buffer_size 4k;
  8. proxy_buffers 4 32k;
  9. proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k;

扩展补充

只允许使用GET,HEAD,POST方法去请求

  1. ## Only allow these request methods ##
  2. if ($request_method !~ ^(GET|HEAD|POST)$ ) {
  3. return 444;
  4. }

实战

根据URI及location实现动静分离。

最终实现:

  1. /static/的URL都去访问10.0.0.9。
  2. /dynamic/的URL都去访问10.0.0.10。
  3. 图片这些静态文件去访问10.0.0.9。
  4. /upload/的URL都去访问10.0.0.10。

  1. [root@lb01 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. #blog lb by oldboy at 201303
  12. upstream static_pools {
  13. server 10.0.0.9:80;
  14. }
  15. upstream dynamic_pools {
  16. server 10.0.0.10:80;
  17. }
  18. upstream upload_pools {
  19. server 10.0.0.9:80;
  20. }
  21. server {
  22. listen 80;
  23. server_name blog.biglittleant.cn;
  24. location / {
  25. proxy_pass http://static_pools;
  26. include proxy.conf;
  27. }
  28. location /static/ {
  29. proxy_pass http://static_pools;
  30. include proxy.conf;
  31. }
  32. location ~* \.(gif|jpg|jpeg)$ {
  33. proxy_pass http://static_pools;
  34. include proxy.conf;
  35. }
  36. location /dynamic/ {
  37. proxy_pass http://dynamic_pools;
  38. include proxy.conf;
  39. }
  40. location /upload/ {
  41. proxy_pass http://upload_pools;
  42. include proxy.conf;
  43. }
  44. }
  45. }

实现苹果手机和安卓手机访问不同的地址

  1. server {
  2. listen 80;
  3. server_name blog.etiantian.org;
  4. location / {
  5. if ($http_user_agent ~* "android")
  6. {
  7. proxy_pass http://android_pools;
  8. }
  9. if ($http_user_agent ~* "iphone")
  10. {
  11. proxy_pass http://iphone_pools;
  12. }
  13. proxy_pass http://pc_pools;
  14. include extra/proxy.conf;
  15. }
  16. access_log off;
  17. }

参考文档

nginx-proxy_pass官网

死磕nginx系列--使用nginx做负载均衡的更多相关文章

  1. nginx 代理post请求做负载均衡

    项目中遇到nginx代理post请求nodejs服务.但是一直404.发现好像是nginx重定向的时候将post请求变成了get请求.上配置: # 负载均衡服务器配置 upstream pdf_ups ...

  2. Nginx系列(3)- 负载均衡

    负载均衡 Nginx提供的负载均衡策略有两种: 内置策略为轮询.加权轮询.ip hash 扩展策略,就天马行空了,只有你想不到的没有它做不到的 轮询  加权轮询(根据权重来) iphash对客户端请求 ...

  3. [Linux]nginx tomcat做负载均衡

    之前使用nginx做过web反向代理,没有做过负载均衡,今天有个同学须要做tomcat的负载均衡,我也研究下. 一共是2个机器,一个物理机(win7)上面部署2个tomcat,使用不同的port启动. ...

  4. 解决docker中使用nginx做负载均衡时并发过高时的一些问题

    # 解决docker中使用nginx做负载均衡时并发过高时的一些问题 1.问题产生原因: 由于通过nginx作为负载均衡服务,在访问并发数量达到一定量级时jmeter报错. nginx日志关键信息:a ...

  5. 在Linux上使用Nginx为Solr集群做负载均衡

    在Linux上使用Nginx为Solr集群做负载均衡 在Linux上搭建solr集群时需要用到负载均衡,但测试环境下没有F5 Big-IP负载均衡交换机可以用,于是先后试了weblogic的proxy ...

  6. 使用nginx做负载均衡的session共享问题

    查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享PHP服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不 ...

  7. nginx做负载均衡配置文件

    nginx做负载均衡是在反向代理的基础上做的,代码如下: ## Basic reverse proxy server ## ## Apache backend for www.baidu.com ## ...

  8. Nginx+tomcat 做负载均衡

    架构描述 前端一台nginx服务器做负载均衡器,后端放N台tomcat组成集群处理服务,通过nginx转发到后面(注:没做动静分离,静态动态全部都转给tomcat) 优点:实现了可弹性化的架构,在压力 ...

  9. Jenkins服务使用nginx代理服务器做负载均衡

    学习nginx代理服务器做负载均衡的使用 在本地安装Nginx 1.下载nginx http://nginx.org/en/download.html         下载稳定版本,以nginx/Wi ...

随机推荐

  1. EF 求和 GroupBy多个字段

    GroupBy根据多个字段分组使用方式: 一.使用扩展方法 query.GroupBy(q => new { q.Year, q.Month }) .Select(q => new { Y ...

  2. SQL Server无法打开物理文件,操作系统错误 5:"5(拒绝访问。)的解决办法

    在新装的系统中使用SQL Server附加以前的数据库的时候可能会遇到“无法打开物理文件,拒绝访问”的错误,如下图: 解决方法为使用windows验证登录,或者更改SQL Server内置账户类型为L ...

  3. 全局唯一订单号生成方法(参考snowflake)

    backgroud Snowflake is a network service for generating unique ID numbers at high scale with some si ...

  4. 221. 链表求和 II

    假定用一个链表表示两个数,其中每个节点仅包含一个数字.假设这两个数的数字顺序排列,请设计一种方法将两个数相加,并将其结果表现为链表的形式. 样例 样例 1: 输入t:6->1->7 2-& ...

  5. 月之数(hdu2502)数学题

    月之数 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  6. php扩展php-redis安装与使用

    一.redis的安装 1,安装redis版本 下载页面:https://redis.io/download 安装一个老版本3.2.11:http://download.redis.io/release ...

  7. Codeforces35E(扫描线)

    E. Parade time limit per test:2 seconds memory limit per test:64 megabytes input:input.txt output:ou ...

  8. POJ1611(KB2-B)

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 39211   Accepted: 18981 De ...

  9. Unix环境高级编程:文件 IO 原子性 与 状态 共享

    参考 UnixUnix环境高级编程 第三章 文件IO 偏移共享 单进程单文件描述符 在只有一个进程时,打开一个文件,对该文件描述符进行写入操作后,后续的写入操作会在原来偏移的基础上进行,这样就可以实现 ...

  10. Code Signal_练习题_Circle of Numbers

    Consider integer numbers from 0 to n - 1 written down along the circle in such a way that the distan ...