当前位置:K88软件开发文章中心网站服务器框架nginx → 文章内容

Nginx 负载均衡模块

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-23 14:29:00

由 小路依依 创建, 最后一次修改 2016-08-12 负载均衡模块负载均衡模块用于从upstream指令定义的后端主机列表中选取一台主机。Nginx 先使用负载均衡模块找到一台主机,再使用 upstream 模块实现与这台主机的交互。为了方便介绍负载均衡模块,做到言之有物,以下选取 Nginx 内置的 ip hash 模块作为实际例子进行分析。配置要了解负载均衡模块的开发方法,首先需要了解负载均衡模块的使用方法。因为负载均衡模块与之前书中提到的模块差别比较大,所以我们从配置入手比较容易理解。在配置文件中,我们如果需要使用 ip hash 的负载均衡算法。我们需要写一个类似下面的配置: upstream test { ip_hash; server 192.168.0.1; server 192.168.0.2; }从配置我们可以看出负载均衡模块的使用场景:核心指令ip_hash只能在 upstream {}中使用。这条指令用于通知 Nginx 使用 ip hash 负载均衡算法。如果没加这条指令,Nginx 会使用默认的 round robin 负载均衡模块。请各位读者对比 handler 模块的配置,是不是有共同点?upstream {}中的指令可能出现在server指令前,可能出现在server指令后,也可能出现在两条server指令之间。各位读者可能会有疑问,有什么差别么?那么请各位读者尝试下面这个配置: upstream test { server 192.168.0.1 weight=5; ip_hash; server 192.168.0.2 weight=7; }神奇的事情出现了: nginx: [emerg] invalid parameter "weight=7" in nginx.conf:103 configuration file nginx.conf test failed可见 ip_hash 指令的确能影响到配置的解析。指令配置决定指令系统,现在就来看 ip_hash 的指令定义: static ngx_command_t ngx_http_upstream_ip_hash_commands[] = { { ngx_string("ip_hash"), NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS, ngx_http_upstream_ip_hash, 0, 0, NULL }, ngx_null_command };没有特别的东西,除了指令属性是 NGX_HTTP_UPS_CONF。这个属性表示该指令的适用范围是 upstream{}。钩子以从前面的章节得到的经验,大家应该知道这里就是模块的切入点了。负载均衡模块的钩子代码都是有规律的,这里通过 ip_hash 模块来分析这个规律。 static char * ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_upstream_srv_conf_t *uscf; uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash; uscf->flags = NGX_HTTP_UPSTREAM_CREATE |NGX_HTTP_UPSTREAM_MAX_FAILS |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT |NGX_HTTP_UPSTREAM_DOWN; return NGX_CONF_OK; }这段代码中有两点值得我们注意。一个是 uscf->flags 的设置,另一个是设置 init_upstream 回调。设置 uscf->flagsNGX_HTTP_UPSTREAM_CREATE:创建标志,如果含有创建标志的话,Nginx 会检查重复创建,以及必要参数是否填写;NGX_HTTP_UPSTREAM_MAX_FAILS:可以在 server 中使用 max_fails 属性;NGX_HTTP_UPSTREAM_FAIL_TIMEOUT:可以在 server 中使用 fail_timeout 属性;NGX_HTTP_UPSTREAM_DOWN:可以在 server 中使用 down 属性;NGX_HTTP_UPSTREAM_WEIGHT:可以在 server 中使用 weight 属性;NGX_HTTP_UPSTREAM_BACKUP:可以在 server 中使用 backup 属性。聪明的读者如果联想到刚刚遇到的那个神奇的配置错误,可以得出一个结论:在负载均衡模块的指令处理函数中可以设置并修改 upstream{} 中server指令支持的属性。这是一个很重要的性质,因为不同的负载均衡模块对各种属性的支持情况都是不一样的,那么就需要在解析配置文件的时候检测出是否使用了不支持的负载均衡属性并给出错误提示,这对于提升系统维护性是很有意义的。但是,这种机制也存在缺陷,正如前面的例子所示,没有机制能够追加检查在更新支持属性之前已经配置了不支持属性的server指令。设置 init_upstream 回调Nginx 初始化 upstream 时,会在 ngx_http_upstream_init_main_conf 函数中调用设置的回调函数初始化负载均衡模块。这里不太好理解的是 uscf 的具体位置。通过下面的示意图,说明 upstream 负载均衡模块的配置的内存布局。从图上可以看出,MAIN_CONF 中 ngx_upstream_module 模块的配置项中有一个指针数组 upstreams,数组中的每个元素对应就是配置文件中每一个 upstream{}的信息。更具体的将会在后面的原理篇讨论。初始化配置init_upstream 回调函数执行时需要初始化负载均衡模块的配置,还要设置一个新钩子,这个钩子函数会在 Nginx 处理每个请求时作为初始化函数调用,关于这个新钩子函数的功能,后面会有详细的描述。这里,我们先分析 IP hash 模块初始化配置的代码: ngx_http_upstream_init_round_robin(cf, us); us->peer.init = ngx_http_upstream_init_ip_hash_peer;这段代码非常简单:IP hash 模块首先调用另一个负载均衡模块 Round Robin 的初始化函数,然后再设置自己的处理请求阶段初始化钩子。实际上几个负载均衡模块可以组成一条链表,每次都是从链首的模块开始进行处理。如果模块决定不处理,可以将处理权交给链表中的下一个模块。这里,IP hash 模块指定 Round Robin 模块作为自己的后继负载均衡模块,所以在自己的初始化配置函数中也对 Round Robin 模块进行初始化。初始化请求Nginx 收到一个请求以后,如果发现需要访问 upstream,就会执行对应的 peer.init 函数。这是在初始化配置时设置的回调函数。这个函数最重要的作用是构造一张表,当前请求可以使用的 upstream 服务器被依次添加到这张表中。之所以需要这张表,最重要的原因是如果 upstream 服务器出现异常,不能提供服务时,可以从这张表中取得其他服务器进行重试操作。此外,这张表也可以用于负载均衡的计算。之所以构造这张表的行为放在这里而不是在前面初始化配置的阶段,是因为upstream需要为每一个请求提

[1] [2]  下一页


Nginx 负载均衡模块