关于nginx架构探究(3)
Nginx 模块综述
Nginx 所有的代码都是以模块的新式组织的,包括核心模块和功能模块。Nginx加载模块的时候不想Apache一样动态加载,它是直接被编译到二进制执行文件中,所以,如果想要加载新的模块,需要我们重新编译Nginx源码。比如:
./configure --with-http_flv_module
执行上述编译选项后,就可以生成http_flv功能模块了。根据模块的功能性质,Nginx的模块大致可以分为以下四类:
. handlers:协同完成客户端请求的处理、产生响应数据,比如ngx_http_rewrite_module模块,用于处理客户端请求的地址重写,ngx_http_static_module模块负责处理客户端的静态页面请求,ngx_http_log_module模块,负责记录请求访问日志。
. filters:对handlers产生的响应数据作各种过滤处理,比如模块ngx_http_not_modified_filter_module,对响应数据进行过滤检测,如果通过时间戳判断出前后响应没有变化,就响应304,让客户端使用本地缓存。
. upstream:如果存在后端真实服务器,Nginx可以利用upstream模块充当反向代理(例如和uwsgi 一起搭建flask框架web程序),对客户端发起的请求值负责转发。
. load-balance:在Nginx充当中间代理角色时,由于后端真实服务器往往多余一个,对于某一次客户端的请求,如何选择对应的后端真实服务器来进行处理,实现负载均衡算法。
- Handler 模块
对于客户端http请求的处理,Nginx为了获得更强的控制能力,Nginx将整个过程细分为多个阶段,每个阶段可以有多个回调函数来处理,这样以来,当我们在处理Handlers模块是,必须把模块功能处理函数挂在正确的阶段点上。例如:http请求的整个过程一共被分为11个阶段,每个阶段对应的处理功能都比较单一,这样能尽量让Nginx模块代码更为内聚。如下图所示为http请求对应的11个阶段:
序号0表示的阶段是指当Nginx成功接收到一个客户端请求后(accept返回FD之后),针对该请求所做的第一个实际工作就是读取客户端发过来的请求头内容。并调用相应的回调函数进行解析。
序号1表示的阶段和3阶段都属于地址重写阶段,前者用于server上下文的重写、后者location上下文的重写,先做server的定位,然后调用3阶段的回调函数作location的定位。
序号2表示的阶段不执行任何回调函数,因为它的任务主要是查找Location的位置,位置找到后,进入3阶段读取配置值,重写地址。
序号4主要是作安全检查的,即查看是否做了过多的内部跳转(比如地址重写、redirect等),我们不能让对一个请求的处理在Nginx内部跳转多次,这样非常消耗性能。Nginx规定跳转次数最大值为10。
序号5、6、7主要是做访问权限检查工作,如果当前请求没有访问权限,那么直接返回状态403,序号10是日志模块处理的阶段。
阶段-回调函数对应表如下所示:
- Filter 模块
对于http请求处理handlers产生的响应内容,在输出到客户端之前需要作过滤处理,这些过滤处理对于完成功能的增强实现与性能的提升是非常有必要的。由于响应数据包括响应头和响应体,所以与此相对应,Filter模块必须提供处理header、body的响应函数, 所有的header过滤模块和body过滤模块各自形成自己的过滤链。如果头过滤失败,响应体过滤可以不必进行。
- Upstream模块
Upstream模块与具体的协议无关,其除了支持HTTP外,还支持包括FASTCGI、UWSGI等在内的多种协议。在Nginx配置文件中location设置了upstream,即表示对该location的请求需要后端真实服务器来处理。upstream模块的优先级最高,所以一旦进入upstream模块之后,再调用其他模块,获取配置参数如server、location,不过这一动作由upstream中的回调函数完成。对于任何一个Upstream模块而言,最核心的实现是7个回调函数。交互过程如下所示:
其中create_request的功能是根据Nginx与后端服务器通信协议,将客户端的HTTP请求信息转化为对应的发送到后端的真实请求,这也就是为什么后端获取变量的方式都是:request.Form,request.json等。process_headers的功能是根据Nginx与后端服务器通信协议,将后端服务其返回的头信息转换为HTTP响应头。input_filter_init以及input_filter则是处理后端服务其返回的响应体。
- Load-balance模块
Load-balance模块是一个辅助模块,与前面介绍的模块不一样,它主要为Upstream模块服务,目标单一,即如何从后台服务器中选择一台合适的服务其来处理当前请求。要实现Load-balance模块,需要实现如下的4个回调函数:
ngx_http_upstream_init_round_robin:解析配置文件过程中被调用,根据upstream里的各个配置变量作初始准备工作,配置文件解析完接不在被调用
ngx_http_upstream_init_round_robin_peer():在每次Nginx准备转发客户端请求到后端服务器前都会调用该函数,该函数为选择合适的后端服务器作初始准备工作。
ngx_http_upstream_get_round_robin_peer():该函数实现具体的调度逻辑,加权选择当前权值最高的后端服务器
ngx_http_upstream_free_round_robin_peer():跟新相关数值,如权重,负载。
Nginx默认采用round-robin加权算法,如果选择其他算法,比如IP_hash算法,需要在upstream中配置说明。加权轮询调度算法思路如下:
假设有一组服务器S = {S0, S1, …, Sn-},W(Si)表示服务器Si的权值,一个
指示变量i表示上一次选择的服务器,指示变量cw表示当前调度的权值,max(S)
表示集合S中所有服务器的最大权值,gcd(S)表示集合S中所有服务器权值的最大
公约数。变量i初始化为-,cw初始化为零。 while (true) {
i = (i + ) mod n;
if (i == ) {
cw = cw - gcd(S);
if (cw <= ) {
cw = max(S);
if (cw == )
return NULL;
}
}
if (W(Si) >= cw)
return Si;
}
IP_hash算法流程如下:
int hash = ;
for(int i = ; i < ; i++) {
hash = (hash * + rand_num[i]) % ; //hash运算
}
hash = hash % peer_number;//peer_number是后端server数目
result[hash]++; //统计hash值命中
关于nginx架构探究(3)的更多相关文章
- 关于nginx架构探究(1)
nginx的架构主要是有一个主监控进程:master;三个工作进程:worker:还有Cache的两个进程.back-end-server是后端服务器,主要是处理后台逻辑.nginx作为代理服务器需要 ...
- 关于nginx架构探究(4)
事件管理机制 Nginx是以事件驱动的,也就是说Nginx内部流程的向前推进基本都是靠各种事件的触发来驱动,否则Nginx将一直阻塞在函数epoll_wait()或suspend函数,Nginx事件一 ...
- 关于nginx架构探究(2)
nginx 数据结构 1.Hash table nginx 对虚拟主机的管理使用到了HASH数据结构,假设配置文件里有如下的配置. Server{ listen 192.168.0.1 server_ ...
- Nginx学习笔记(一) Nginx架构
Nginx架构 Nginx全程是什么? Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. ...
- Nginx架构的企业级应用
Nginx架构的企业级应用 ==================================================== 实现HA高可用集群 实现LB负载均衡集群 Nginx实现反向代理 ...
- [转载] 深入 nginx 架构
原文: http://www.cnbeta.com/articles/402709.htm 了解 nginx 架构帮助我们学习如何开发高性能 web 服务. 为了更好地理解设计,你需要了解NGINX是 ...
- nginx架构与基础概念
1 Nginx架构 Nginx 高性能,与其架构有关. Nginx架构: nginx运行时,在unix系统中以daemon形式在后台运行,后台进程包含一个master进程和多个worker ...
- Nginx从入门到放弃-第5章 Nginx架构篇
5-1 Nginx常见问题_架构篇介绍 5-2 Nginx常见问题_多个server中虚拟主机读取的优先级 5-3 Nginx常见问题_多个location匹配的优先级1 5-4 Nginx常见问题_ ...
- 转:初探nginx架构(一)
来源:http://tengine.taobao.org/book/chapter_02.html 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢? ...
随机推荐
- Java学习日记-7 抽象类和接口
一.抽象类 abstract修饰:类和类中的方法 抽象方法:abstract type name(parameter-list);(abstract不能修饰static方法和构造函数) 引用:抽象类有 ...
- SRM 584 DIV1
A 简单的差分约束模型 , 因为d是定值 , 所以也可以按最短路理解 , trick是不能把圈算进去. #define maxn 55 class Egalitarianism { public: i ...
- finally与return
finally关键字:和try块使用,一般做资源释放操作,比如关闭流.关闭数据库连接,释放锁. return:用于返回值. finally块可保证一定执行,当逻辑处理有返回值时,会首先执行finall ...
- 跟我一起学PCL打印语言(一)
引言 本人从事打印机开发和打印驱动开发的相关工作,深感资料特别是中文资料的匮乏和不成系统,对新入门的从事该行业的人来说,门槛很高.在这里一方面是将开发中遇到的相关知识点整理出来,另一方面也能够促进自己 ...
- [转] 为什么医疗咨询服务公司Evolent Health仅用4年就华丽上市?
让医疗主体,即医院和医生担任保险角色,完全控制保费,实现医疗机构的利益最大化.美国公司EvolentHealth帮助所有医院实现这一梦想. 不觉间,已步入2015的下半年.当国内还在讨论商业保险何时能 ...
- Trie 字典树
字典树是哈希树的变种, 它采用公用前缀的方式来提高效率, 刚开始以为公用前缀, 空间会节省, 后来想想, 空间也不是节省, 因为每一个都有26个指针(这里假设都是小写字母的话), 不过他的时间复杂度是 ...
- 手势识别 GestureDetector ScaleGestureDetector
识别器GestureDetector基本介绍 当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等.一般情况下,我们可以通过View或Activity的onTouch ...
- 原生js-拉勾网首页效果
拉勾网首页公司广告位的悬浮划过效果着实很吸引我.如下(不会做动图!--,感兴趣的可以去拉勾看看): 此处最吸引我的地方在于将鼠标划过上面一排公司列表时,感觉像是绿色的区块跟着你的鼠标移动一样,颇有动感 ...
- SpringBoot入门系列:第一篇 Hello World
跟随SpringBoot的文档(http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-d ...
- jQuery mini ui 2
1.<a class="mini-button" iconCls="icon-add" onclick="addRow()" plai ...