关于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究竟是怎么样的呢? ...
随机推荐
- Android Memory Leak
线程也是造成内存泄露的一个重要的源头.线程产生内存泄露的主要原因在于线程生命周期的不可控.1.看一下下面是否存在问题 public class ThreadActivity extends Activ ...
- throw new DataException("检查服务器是否存在失败:" + ex);
try { } catch (Exception ex) { LogHelper.Error(" ...
- Javascript 操作select控件大全(新增、修改、删除、选中、清空、判断存在等)
1判断select选项中 是否存在Value="paraValue"的Item 2向select选项中 加入一个Item 3从select选项中 删除一个Item 4删除selec ...
- bzoj1823 [JSOI2010]满汉全席(2-SAT)
1823: [JSOI2010]满汉全席 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1246 Solved: 598[Submit][Status ...
- css实现小三角效果
<!DOCTYPE html><html><head><meta charset="UTF-8"> <title>新闻标 ...
- ehcache报错ERROR n.s.e.store.disk.DiskStorageFactory - Disk Write的解决办法
23:53:44 ERROR n.s.e.store.disk.DiskStorageFactory - Disk Write of com.koal.**.**.**.**.**.***Impl$$ ...
- HDU 1166 敌兵布阵(线段树)
题目地址:pid=1166">HDU 1166 听说胡浩版的线段树挺有名的. 于是就拜訪了一下他的博客.详情戳这里.于是就全然仿照着胡浩大牛的风格写的代码. 至于原理.鹏鹏学长已经讲的 ...
- 【C++深入探索】Copy-and-swap idiom详解和实现安全自我赋值
分类: C/C++2012-08-30 21:40 2017人阅读 评论(2) 收藏 举报 任何管理某资源的类比如智能指针需要遵循一个规则(The Rule of Three): 如果你需要显式地声明 ...
- hdu3368之DFS
Reversi Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Su ...
- yii cgridview 如何显示图片
发布的新闻或介绍里有图片,图片存的是Url地址,通过yii的cgridview,默认是数据库里存的啥就显示啥,如何把url地址转为图片?直接上代码 <?php $data = $model-&g ...