实现nginx负载均衡
nginx有2钟均衡模式
一种是根据每个工作的进程的压力调整获取监听接口
nginx 反向代理的形式 就是对所有的请求实际的处理转发到后台服务器
nginx 提供了一种第三方模块编译 必须将源代码放入一个目录下,同时在本目录中编写一个文件通知nginx如何编译模块。这个文件名字必须是config.
(
在configure脚本执行时加入参数--add-module=PATH(新模块源代码以及config文件存放目录),就可以在执行政策编译安装流程时完成Nginx编译工作)
nginx 为用户配置了强大的配置项解析机制 同时支持命令 可以在不重启服务器的情况下使配置生效
配置文件中有很多块配置项。块配置项是由一个块配置项名和一对大括号组成。例如上面代码段中的http、server、event等等。也可以在块配置项名之后后大括号之前加上参数。
块配置项可以嵌套。内层块直接继承外层块。例如上例中server块里的任意配置都是基于http块里的已有配置的。当内外层中的配置发生冲突时,究竟是以内层块还是外层块的配置为准取决于解析这个配置项的模块。
nginx 配置http
配置流程大致分4个步骤。1.创建数据结构这样用于对存储在配置项里面的参数相对应
2.在nginx.conf中设置回调方法和限制的条件.3.使用自己设置的回调方法或者用nginx自己内置的14钟回调方法。4.去查看配置项 防止不同级配置块出现的同名字的去合并掉.
nginx中有2个重要的数据结构 ,ngx_http_module_t以及ngx_command_t,是HTTP模块时不可或缺的部分.因为配置流程的4个步骤考它们结合起来.
http框架在解析nginx.conf的时候只要遇到http{} server{} location{} 配置块会马上分配一个新的结构体。在nginx中通过 ngx_http_module_t中的8个回调方法来管理自己自定义的存储配置结构体.
http框架定义了三个级别的配置main、srv、loc,分别表示直接出现在http{}、server{}、location{}、块内的配置。当nginx.conf中出现http{}时,http框架会接管配置文件中http{}块内的配置项解析。当遇到http{}配置块时,http框架会调用所有的http模块可能实现的create_main_conf、create_srv_conf、create_loc_conf方法生成存储main级别的配置参数的结构体;在遇到server{}配置块时,会再次调用所有的http模块可能实现的create_srv_conf、create_loc_conf方法生成存储srv级别的配置参数的结构体;在遇到location{}配置块时,会再次调用所有的http模块可能实现的create_loc_conf方法生成存储loc级别的配置参数的结构体。实现三个回调方法的意义是不同的。在一个模块中,http块内只会调用一次create_main_conf,但是create_loc_conf可能会被调用很多次,也就是有许多由create_loc_conf生成的结构体.
在nginx中有个非常的结构体ngx_http_request_s
贯穿于htpp请求处理的整个过程中.
HTTP基础功能:__
- 处理静态文件,索引文件以及自动索引;
- 反向代理加速(无缓存),简单的负载均衡和容错;
- FastCGI,简单的负载均衡和容错;
- 模块化的结构。过滤器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI过滤器中,到同一个 proxy 或者 FastCGI 的多个子请求并发处理;
- SSL 和 TLS SNI 支持;
- 基于IP 和名称的虚拟主机服务;
- Memcached 的 GET 接口;
- 支持 keep-alive 和管道连接;
- 灵活简单的配置;
- 重新配置和在线升级而无须中断客户的工作进程;
- 可定制的访问日志,日志写入缓存,以及快捷的日志回卷;
- 4xx-5xx 错误代码重定向;
- 基于 PCRE 的 rewrite 重写模块;
- 基于客户端 IP 地址和 HTTP 基本认证的访问控制;
- PUT, DELETE, 和 MKCOL 方法;
- 支持 FLV (Flash 视频);
- 带宽限制;
在nginx中,建立连接的时候,会设计负载均衡的问题。在多个子进程抢着处理一个新连接事件时候,只会有一个worker子进程最终会成功的建立连接,并且这个子进程会一直处理到连接关闭。但是这个就可能出现一种情况:有的子进程建立了大部分的连接并且处理,而有的只是处理了少量的连接,这对处理器一般是ADM多核架构下的应用不平等,因为子进程之间应该是平等的,每个子进程应该最好是独占一个cpu的核心,因为子进程之间负载不均衡 会影响整个服务器的性能。
举个例子:
万某有10个苹果 要发给10个小朋友 那么是这10个小朋友过来给万某伸手要 (建立一个连接然后) 并且拿走 还告诉万某(处理进程 并且告知结果) 快。还是万某让其中3个小朋友来处理这10个苹果在发给剩下的7个苹果 (按照cpu来说 就是 3个小朋友分到了10份的任务,其他7个闲着在,那么分的速度也就打了折扣) 这就会影响服务器的性能。
怎么解决负载均衡的问题
这里首先就要解决 惊群的问题(thundering herd)的产生,在每个建立连接的时候,nginx处于发挥多核cpu架构性能的考虑,使用了多个worker子进程监听相同端口的设计,这样多个子进程在accept建立的时候发现有新的连接会去争抢,这就是“惊群”问题,子进程的数量越多越明显。必然会造成系统性能的下降。正常的情况下,有多少个cpu核心就配置多少个worker子进程。假如现在没有操作连入服务器,又
恰好所有的子进程都休眠且等待新连接的系统调用(如epoll_wait),这时有一个用户向服务器发起了连接,内核在收到TCP的SYN包时,会激活所有的休眠worker子进程。最终只有最先开始执行accept的子进程可以成功建立新连接,而其他worker子进程都将accept失败。这些accept失败的子进程被内核唤醒是不必要的,他们被唤醒会的执行很可能是多余的,那么这一时刻他们占用了本不需要占用的资源,引发了不必要的进程切换,增加了系统开销。nginx作为一个GDDQSDC的web服务器,早已经解决了这一问题,虽然解决的不是很完善。nginx规定了同一时刻只有唯一一个worker子进程监听web端口。这样其他的子进程就不会被唤醒。
参考资料
《深入理解Nginx》
《深入剖析Nginx》
Nginx中文文档
http://www.nginx.cn/doc/