Nginx的负载均衡 - 整体架构

Nginx版本:1.9.1

我的博客:http://www.cnblogs.com/yyjie

什么是负载均衡

我们知道单台服务器的性能是有上限的,当流量很大时,就需要使用多台服务器来共同提供服务,这就是所谓的集群。

负载均衡服务器,就是用来把经过它的流量,按照某种方法,分配到集群中的各台服务器上。这样一来不仅可以承担

更大的流量、降低服务的延迟,还可以避免单点故障造成服务不可用。一般的反向代理服务器,都具备负载均衡的功能。

负载均衡功能可以由硬件来提供,比如以前的F5设备。也可以由软件来提供,LVS可以提供四层的负载均衡(利用IP和端口),

Haproxy和Nginx可以提供七层的负载均衡(利用应用层信息)。

来看一个最简单的Nginx负载均衡配置。

[html] view plain copy

  1. http {
  2. upstream cluster {
  3. server srv1;
  4. server srv2;
  5. server srv3;
  6. }
  7. server {
  8. listen 80;
  9. location / {
  10. proxy_pass http://cluster;
  11. }
  12. }
  13. }

通过上述配置,Nginx会作为HTTP反向代理,把访问本机的HTTP请求,均分到后端集群的3台服务器上。

此时使用的HTTP反向代理模块是ngx_http_proxy_module。

一般在upstream配置块中要指明使用的负载均衡算法,比如hash、ip_hash、least_conn。

这里没有指定,所以使用了默认的HTTP负载均衡算法 - 加权轮询。

负载均衡流程图

在描述负载均衡模块的具体实现前,先来看下它的大致流程:

负载均衡模块 

Nginx目前提供的负载均衡模块:

ngx_http_upstream_round_robin,加权轮询,可均分请求,是默认的HTTP负载均衡算法,集成在框架中。

ngx_http_upstream_ip_hash_module,IP哈希,可保持会话。

ngx_http_upstream_least_conn_module,最少连接数,可均分连接。

ngx_http_upstream_hash_module,一致性哈希,可减少缓存数据的失效。

以上负载均衡模块的实现,基本上都遵循一套相似的流程。

1. 指令的解析函数

比如least_conn、ip_hash、hash指令的解析函数。

这些函数在解析配置文件时调用,主要用于:

检查指令参数的合法性

指定peer.init_upstream函数指针的值,此函数用于初始化upstream块。

2. 初始化upstream块

在执行完指令的解析函数后,紧接着会调用所有HTTP模块的init main conf函数。

在执行ngx_http_upstream_module的init main conf函数时,会调用所有upstream块的初始化函数,

即在第一步中指定的peer.init_upstream,主要用于:

创建和初始化后端集群,保存该upstream块的数据

指定peer.init,此函数用于初始化请求的负载均衡数据

来看下ngx_http_upstream_module。

[java] view plain copy

  1. ngx_http_module_t ngx_http_upstream_module_ctx = {
  2. ...
  3. ngx_http_upstream_init_main_conf, /* init main configuration */
  4. ...
  5. };

[java] view plain copy

  1. static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
  2. {
  3. ...
  4. /* 数组的元素类型是ngx_http_upstream_srv_conf_t */
  5. for (i = 0; i < umcf->upstreams.nelts; i++) {
  6. /* 如果没有指定upstream块的初始化函数,默认使用round robin的 */
  7. init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream :
  8. ngx_http_upstream_init_round_robin;
  9. if (init(cf, uscfp[i] != NGX_OK) {
  10. return NGX_CONF_ERROR;
  11. }
  12. }
  13. ...
  14. }

3. 初始化请求的负载均衡数据块

当收到一个请求后,一般使用的反向代理模块(upstream模块)为ngx_http_proxy_module,

其NGX_HTTP_CONTENT_PHASE阶段的处理函数为ngx_http_proxy_handler,在初始化upstream机制的

函数ngx_http_upstream_init_request中,调用在第二步中指定的peer.init,主要用于:

创建和初始化该请求的负载均衡数据块

指定r->upstream->peer.get,用于从集群中选取一台后端服务器(这是我们最为关心的)

指定r->upstream->peer.free,当不用该后端时,进行数据的更新(不管成功或失败都调用)

请求的负载均衡数据块中,一般会有一个成员指向对应upstream块的数据,除此之外还会有自己独有的成员。

"The peer initialization function is called once per request. 
It sets up a data structure that the module will use as it tries to find an appropriate
backend server to service that request; this structure is persistent across backend re-tries,
so it‘s a convenient place to keep track of the number of connection failures, or a computed
hash value. By convention, this struct is called ngx_http_upstream_<module_name>_peer_data_t."

4. 选取一台后端服务器

一般upstream块中会有多台后端,那么对于本次请求,要选定哪一台后端呢?

这时候第三步中r->upstream->peer.get指向的函数就派上用场了:

采用特定的算法,比如加权轮询或一致性哈希,从集群中选出一台后端,处理本次请求。

选定后端的地址保存在pc->sockaddr,pc为主动连接。

函数的返回值:

NGX_DONE:选定一个后端,和该后端的连接已经建立。之后会直接发送请求。

NGX_OK:选定一个后端,和该后端的连接尚未建立。之后会和后端建立连接。

NGX_BUSY:所有的后端(包括备份集群)都不可用。之后会给客户端发送502(Bad Gateway)。

5. 释放一台后端服务器

当不再使用一台后端时,需要进行收尾处理,比如统计失败的次数。

这时候会调用第三步中r->upstream->peer.free指向的函数。

函数参数state的取值:

0,请求被成功处理

NGX_PEER_FAILED,连接失败

NGX_PEER_NEXT,连接失败,或者连接成功但后端未能成功处理请求

一个请求允许尝试的后端数为pc->tries,在第三步中指定。当state为后两个值时:

如果pc->tries不为0,需要重新选取一个后端,继续尝试,此后会重复调用r->upstream->peer.get。

如果pc->tries为0,便不再尝试,给客户端返回502错误码(Bad Gateway)。

在upstream模块的回调

负载均衡模块的功能是从后端集群中选取一台后端服务器,而具体的反向代理功能是由upstream模块实现的,

比如和后端服务器建立连接、向后端服务器发送请求、处理后端服务器的响应等。

我们来看下负载均衡模块提供的几个钩子函数,是在upstream模块的什么地方回调的。

Nginx的HTTP反向代理模块为ngx_http_proxy_module,其NGX_HTTP_CONTENT_PHASE阶段的处理函数为

ngx_http_proxy_handler,每个请求的upstream机制是从这里开始的。

[java] view plain copy

  1. ngx_http_proxy_handler
  2. ngx_http_upstream_create /* 创建请求的upstream实例 */
  3. ngx_http_upstream_init /* 启动upstream机制 */
  4. ngx_htp_upstream_init_request /* 负载均衡模块的入口 */
  5. uscf->peer.init(r, uscf) /* 第三步,初始化请求的负载均衡数据块 */
  6. ...
  7. ngx_http_upstream_connect /* 可能会被ngx_http_upstream_next重复调用 */
  8. ngx_event_connect_peer(&u->peer); /* 连接后端 */
  9. pc->get(pc, pc->data); /* 第四步,从集群中选取一台后端 */
  10. ...
  11. /* 和后端建连成功后 */
  12. c = u->peer.connection;
  13. c->data = r;
  14. c->write->handler = ngx_http_upstream_handler; /* 注册的连接的读事件处理函数 */
  15. c->read->handler = ngx_http_upstream_handler; /* 注册的连接的写事件处理函数 */
  16. u->write_event_handler = ngx_http_upstream_send_request_handler; /* 写事件的真正处理函数 */
  17. u->read_event_handler = ngx_http_upstream_process_header; /* 读事件的真正处理函数 */

选定后端之后,在和后端通信的过程中如果发生了错误,会调用ngx_http_upstream_next来继续尝试其它的后端。

[java] view plain copy

  1. ngx_http_upstream_next
  2. if (u->peer.sockaddr) {
  3. if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403 ||
  4. ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404)
  5. state = NGX_PEER_NEXT;
  6. else
  7. state = NGX_PEER_FAILED;
  8. /* 第五步,释放后端服务器 */
  9. u->peer.free(&u->peer, u->peer.data, state);
  10. u->peer.sockaddr = NULL;
  11. }

Reference

时间: 2024-10-12 04:44:48

Nginx的负载均衡 - 整体架构的相关文章

【高可用架构】用Nginx实现负载均衡(三)

前言 在上一篇,已经用Envoy工具统一发布了Deploy项目代码.本篇我们来看看如何用nginx实现负载均衡 负载均衡器IP 192.168.10.11 [高可用架构]系列链接:待部署的架构介绍 演示 配置应用服务器 首先,需要将上一篇部署的两台应用服务器,都能够单独访问 配置192.168.10.12.192.168.10.18上nginx的config # vi /etc/nginx/config.d/dev.deploy.goods.conf server { listen 80; se

Linux下利用nginx实现负载均衡

linux下利用nginx实现负载均衡 前提条件: 1,安装好jdk 2,安装好tomcat和nginx(可以参考我前两篇文章) 满足前提条件后,要用nginx实现负载均衡,主要是靠配置nginx的配置文件. 我们要实现的架构图如下: 1.分别部署3个tomcat,端口分别为8080,8081,8082 drwxr-xr-x 9 root root 4096 Mar 11 13:41 tomcat8-8080drwxr-xr-x 9 root root 4096 Mar 11 17:27 tom

企业级web负载均衡完美架构

转载:揭秘企业级web负载均衡完美架构(图) 2010-07-06 15:16 抚琴煮酒 51CTO.com 字号:T | T 相信很多朋友对企业级的负载均衡高可用实例非常感兴趣,此篇文章根据成熟的线上环境而写,旨在帮助大家迅速架构一个企业级的负载均衡高可用的web环境. AD:WOT2014课程推荐:实战MSA:用开源软件搭建微服务系统 [51CTO.com独家特稿]相信很多朋友对企业级的负载均衡高可用实例非常感兴趣,此篇文章根据成熟的线上环境而写,旨在帮助大家迅速架构一个企业级的负载均衡高可

linux+asp.net core+nginx四层负载均衡

Linux Disibutaion:Ubuntu 16.04.1 LTS Web Server:Nginx.Kestrel 关于如何在linux中部署asp.net core我这里不再详细介绍,可以参考ASP.Net Core 运行在Linux(Ubuntu) 这里我需要三台VM:nginxvm01:做负载均衡服务器nginxvm02:服务节点1nginxvm03:服务节点2 大致服务架构如下图: 配置负载均衡节点(nginxvm01): sudo apt-get install -y ngin

利用Nginx构建负载均衡服务器

大家都知道,一个域名对应一个IP地址,而一个WebSite则对应一个IP地址上对应端口服务的应用程序(或位置).而大型网站的并发访问量非常大,这些网站是如何在一台Web服务器上实现负载均衡的呢? 相信很多人会有与我同样的疑惑,但实际上成熟的解决方案已经大规模投入使用.而常用的则是反向代理方法. 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理

[转载] nginx的负载均衡

原文:http://www.srhang.me/blog/2014/08/27/nginx-loabbalance/ Nginx负载均衡 一.特点 1.1 应用情况 Nginx做为一个强大的Web服务器软件,具有高性能.高并发性和低内存占用的特点.此外,其也能够提供强大的反向代理功能.俄罗斯大约有超过20%的虚拟主机采用Nginx作为反向代理服务器,在国内也有腾讯.新浪.网易等多家网站在使用Nginx作为反向代理服务器.据Netcraft统计,世界上最繁忙的网站中有11.48%使用Nginx作为

Nginx的负载均衡的那点事 (转)

本节就聊聊采用Nginx负载均衡之后碰到的问题: Session问题 文件上传下载 通常解决服务器负载问题,都会通过多服务器分载来解决.常见的解决方案有: 网站入口通过分站链接负载(天空软件站,华军软件园等) DNS轮询 F5物理设备 Nginx等轻量级架构 那我们看看Nginx是如何实现负载均衡的,Nginx的upstream目前支持以下几种方式的分配 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. 2.weight 指定轮询几率,wei

Nginx + Tomcat 负载均衡群集 【内附源码包】

前言: 1·在之前都学习 Linux 的一些服务和搭建,都很熟悉 !这篇文章主要讲Nginx.Tomcat与 Nginx + Tomcat 负载均衡群集.2·在各种网站服务器软件中,除了 Apache HTTP Server 外,还有一款轻量级的 HTTP 服务器软件--Nginx,它是由俄罗斯 Lgor Sysoev(伊戈尔·赛索耶夫)开发. Nginx 的优点: 1·稳定性2·系统资源消耗低3·高并发链接的处理能力 (30000~50000 个并发请求),核心优点!4·反向代理服务器5·安装

Centos7搭建nginx+tomcat负载均衡

Nginx简介 Nginx是一种服务器软件,也是一种高性能的http和反向代理服务器,同时还是一个代理邮件服务器.也就是说,我们在Nginx上可以发布网站,可以实现负载均衡(提高应答效率,避免服务器崩溃),还可以作为邮件服务器实现收发邮件等功能.而最常见的就是使用Nginx实现负载均衡. Nginx与其他服务器的性能比较 Tomcat服务器面向Java语言,是重量级的服务器,而Nginx是轻量级的服务器.Apache服务器稳定.开源.跨平台,但是Apache服务器不支持高并发,Nginx能支持处