本文介绍的负载均衡是针对的客户端请求在多个Nginx进程之间的均衡。注意与客户端请求在多个后端服务器之间的均衡相区别。

负载均衡问题的产生

在nginx中,建立连接的时候,会设计负载均衡问题。在多个子进程争抢处理一个新连接事件时,一定只有一个worker子进程最终会成功建立连接,随后 它会一直处理这个连接直到连接关闭。那么,就有可能出现这样的情况:有的子进程建立并处理了大部分连接,而有的子进程只处理了少量连接。这对多核CPU架 构下的应用是很不利的。因为子进程之间应该是平等的,每个子进程应该尽量独占一个CPU核心。子进程间负载不均衡,必定会影响整个服务的性能。

如何解决负载均衡问题

与惊群问题的解决方法一样,只有打开了accept_mutex锁,才能实现子进程间的负载均衡。在ngx_event_accept方法建立新连接的过程中,初始化了一个全局变量ngx_accept_disabled。它就是负载均衡机制实现的关键阈值。其定义(/src/event/ngx_event.c):

ngx_int_t             ngx_accept_disabled;

初始化(sr/event/ngx_event_accept.c)是在函数ngx_event_accept中:
ngx_accept_disabled = ngx_cycle->connection_n / 8  - ngx_cycle->free_connection_n;
这样,在nginx启动的时候其实是个负值:-7/8 * ngx_cycle->connection_n。
ngx_process_events_and_timers 函数是worker子进程中服务器主循环每次循环都会调用的函数
依据这个值进行负载均衡的核心代码是在函数ngx_process_events_and_timers中(src/event/ngx.event.c):
         //负载均衡处理
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;
        } else {
            //调用ngx_trylock_accept_mutex方法,尝试获取accept锁
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return;
            }
解释一下:
当ngx_accept_disabled 为负数时,不会触发负载均衡操作,正常获取accept锁,试图处理新连接。
当ngx_accept_disabled 为正数时,会触发负载均衡操作。nginx此时不再处理新连接事件,取而代之的仅仅是把变量ngx_accept_disabled 减一,这表示既然经过一轮事件处理,那么负载肯定有所减小,所以要相应调整这个值。
即,当当前使用的连接超过总连接数的7/8的时候才会被触发,值越大,表示负载越重。每次调用process_events的时候只会将 ngx_accept_disabled  减一,直到ngx_accept_disabled 降到0,即使用的连接数降到总连接数的7/8。这样就减少了该worker进程处理新连接的机会,这样其他较空闲的worker进程就有机会去处理更多的新连接,以达到整个web服务器的均衡效果。
Nginx默认将accept_mutex配置项设置为accept_mutex_on。

参考:

http://www.cppblog.com/converse/archive/2009/12/08/102816.html

最新文章

  1. Ubuntu操作系统下软件的卸载
  2. ie8的兼容
  3. java中匿名类的注意细节
  4. 视频转gif
  5. struts2总结四:Action与Form表单的交互
  6. Tyvj 9.10 总结 (其实只是发一下心情)
  7. SQL SERVER(MSSQLSERVER) 服务无法启用 特定服务错误:126
  8. SQL Server CONVERT() 函数
  9. Git教程(2)官方命令文档及常用命令表
  10. Ubuntu下ssh免password登录安装
  11. HDU 1813 Escape from Tetris
  12. js打开新窗口,打开新窗口屏蔽工具栏和地址栏,窗口按规定大小显示
  13. Apex 单元测试辅助函数简介
  14. drawable内存管理
  15. mysql修改字段长度及pymysql.err.DataError: (1406, "Data too long for column 'name' at row 1")错误
  16. C# 线程 正确使用Thread.Join()停止方式
  17. (钉钉)第三方WEB网站扫码登录
  18. ASP.NET WebApi JObject 使用
  19. c# 上传图片流,php端(laravel框架)接收处理方法
  20. 【转】深入理解C++的动态绑定和静态绑定 & 不要重定义虚函数中的默认参数

热门文章

  1. Hystrix 断路器
  2. && (and)、||(or) 条件语句
  3. 部署 k8s Cluster(上)[转]
  4. install docker-ce for ubuntu
  5. Maven实战读书笔记(三):Maven依赖
  6. oracle 存储过程,存储函数,包,
  7. 漫谈Word2vec之skip-gram模型
  8. css控制超出部分自动省略...
  9. springmvc请求小例子
  10. tornado框架基础11-tornado异步