Nginx平台构架
深入理解Nginx模块发开与架构解析读书笔记。
nginx在启动后,在unix系统中会以daemon的方式(能够手动关闭 nginx.conf daemon off)在后台执行,后台进程包括一个master进程和多个worker进程。master进程主要用来管理worker进程,包括:接收来自外界的信号,向各worker进程发送信号,监控worker进程的执行状态。当worker进程退出后(异常情况下),会自己主动又一次启动新的worker进程。而主要的网络事件,则是放在worker进程中来处理了。
多个worker进程之间是对等的,他们同等竞争来自client的请求。各进程互相之间是独立的。一个请求,仅仅可能在一个worker进程中处理。一个worker进程。不可能处理其它进程的请求。worker进程的个数是能够设置的。一般我们会设置与机器cpu核数一致。这里面的原因与nginx的进程模型以及事件处理模型是分不开的。nginx的进程模型,能够由下图来表示。
在nginx启动后。假设我们要操作nginx,从上文中我们能够看到,master来管理worker进程,所以我们仅仅须要与master进程通信即可了。master进程会接收来自外界发来的信号,再依据信号做不同的事情。比方,./nginx -s reload。就是来重新启动nginx,./nginx -s stop,就是来停止nginx的执行。怎样做到的呢?我们还是拿reload来说。我们看到,执行命令时,我们是启动一个新的nginx进程。而新的nginx进程在解析到reload參数后,就知道我们的目的是控制nginx来又一次载入配置文件了。它会向master进程发送信号。
首先master进程在接到信号后。会先又一次载入配置文件,然后再启动新的worker进程,并向全部老的worker进程发送信号,告诉他们能够光荣退休了。新的worker在启动后,就開始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的全部未处理完的请求处理完毕后。再退出。
worker进程之间是平等的,每一个进程。处理请求的机会也是一样的。
当我们提供80port的http服务时,一个连接请求过来。每一个进程都有可能处理这个连接,怎么做到的呢?首先。每一个worker进程都是从master进程fork过来。在master进程里面,先建立好须要listen的socket(listenfd)之后,然后再fork出多个worker进程。
全部worker进程的listenfd会在新连接到来时变得可读。为保证仅仅有一个进程处理该连接,全部worker进程在注冊listenfd读事件前抢accept_mutex,抢到相互排斥锁的那个进程注冊listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就開始读取请求。解析请求,处理请求,产生数据后。再返回给client,最后才断开连接,这样一个完整的请求就是这种了。我们能够看到,一个请求,全然由worker进程来处理,并且仅仅在一个worker进程中处理。
异步非堵塞特性:我们先回到原点,看看一个请求的完整过程。
首先。请求过来。要建立连接,然后再接收数据,接收数据后,再发送数据。详细到系统底层,就是读写事件,而当读写事件没有准备好时,必定不可操作,假设不用非堵塞的方式来调用。那就得堵塞调用(事件没有准备好,那就仅仅能等)。堵塞调用会进入内核等待。cpu就会让出去给别人用了,对单线程的worker来说,显然不合适,当网络事件越多时,大家都在等待呢。cpu空暇下来没人用,cpu利用率自然上不去了。更别谈高并发了。好吧。你说加进程数,这跟apache的线程模型有什么差别。注意。别添加无谓的上下文切换。所以,在nginx里面。最忌讳堵塞的系统调用了。不要堵塞,那就非堵塞喽。非堵塞就是,事件没有准备好,立即返回EAGAIN(所请求资源临时不可用,稍后再訪问可能可用)。
你过一会,再来检查一下事件。直到事件准备好了为止。在这期间。你就能够先去做其它事情,然后再来看看事件好了没。
尽管不堵塞了,但你得不时地过来检查一下事件的状态。你能够做很多其它的事情了,但带来的开销也是不小的。所以。才会有了异步非堵塞的事件处理机制。详细到系统调用就是像select/poll/epoll/kqueue这种系统调用。它们提供了一种机制,让你能够同一时候监控多个事件,调用他们是堵塞的,但能够设置超时时间,在超时时间之内,假设有事件准备好了,就返回。这种机制正好攻克了我们上面的两个问题,拿epoll为例(在后面的样例中,我们多以epoll为样例,以代表这一类函数),当事件没准备好时。放到epoll里面。事件准备好了。我们就去读写。当读写返回EAGAIN时,我们将它再次添加到epoll里面。这样,仅仅要有事件准备好了。我们就去处理它,仅仅有当全部事件都没准备好时,才在epoll里面等着。这样。我们就能够并发处理大量的并发了。当然。这里的并发请求,是指未处理完的请求,线程仅仅有一个,所以同一时候能处理的请求当然仅仅有一个了,仅仅是在请求间进行不断地切换而已,切换也是由于异步事件未准备好,而主动让出的。这里的切换是没有不论什么代价。你能够理解为循环处理多个准备好的事件,其实就是这种。与多线程相比。这种事件处理方式是有非常大的优势的。不须要创建线程,每一个请求占用的内存也非常少,没有上下文切换。事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换)。很多其它的并发数,仅仅是会占用很多其它的内存而已。
本文作者之前有对连接数进行过測试,在24G内存的机器上,处理的并发请求数达到过200万。如今的网络server基本都採用这种方式,这也是nginx性能高效的主要原因。
推荐设置worker的个数为cpu的核数。在这里就非常easy理解了。很多其它的worker数,仅仅会导致进程来竞争cpu资源。
nginx为了更好的利用多核特性,提供了cpu亲缘性的绑定选项,我们能够将某一个进程绑定在某一个核上,这样就不会由于进程的切换带来cache的失效。
首先,信号的处理。对nginx来说,有一些特定的信号。代表着特定的意义。信号会中断掉程序当前的执行。在改变状态后,继续执行。假设是系统调用。则可能会导致系统调用的失败,须要重入。关于信号的处理,大家能够学习一些专业书籍,这里不多说。
对于nginx来说,假设nginx正在等待事件(epoll_wait时)。假设程序收到信号,在信号处理函数处理完后,epoll_wait会返回错误。然后程序可再次进入epoll_wait调用。
另外,再来看看定时器。由于epoll_wait等函数在调用的时候是能够设置一个超时时间的,所以nginx借助这个超时时间来实现定时器。
nginx里面的定时器事件是放在一颗维护定时器的红黑树里面,每次在进入epoll_wait前,先从该红黑树里面拿到全部定时器事件的最小时间,在计算出epoll_wait的超时时间后进入epoll_wait。
所以,当没有事件产生,也没有中断信号时,epoll_wait会超时。也就是说。定时器事件到了。
这时,nginx会检查全部的超时事件,将他们的状态设置为超时,然后再去处理网络事件。由此能够看出。当我们写nginx代码时,在处理网络事件的回调函数时,通常做的第一个事情就是推断超时。然后再去处理网络事件。
我们能够用一段伪代码来总结一下nginx的事件处理模型:
while (true) {
for t in run_tasks:
t.handler();
update_time(&now);
timeout = ETERNITY;
for t in wait_tasks: /* sorted already */
if (t.time <= now) {
t.timeout_handler();
} else {
timeout = t.time - now;
break;
}
nevents = poll_function(events, timeout);
for i in nevents:
task t;
if (events[i].type == READ) {
t.handler = read_handler;
} else { /* events[i].type == WRITE */
t.handler = write_handler;
}
run_tasks_add(t);
}
Nginx环境搭建。
cat /etc/issue
RHEL Server release 6.6
Uname -r
Kernel 版本号:2.6.32
cd nginx-x.x.x/
./configure –prefix =/home/renwh/nginx --without-http_rewrite_module --without-http_gzip_module
Make
Make install
cd /home/renwh/nginx/bin
./nginx
(servise iptables stop)
浏览器直接訪问该机ip地址。能够看到nginx确认界面,则开启成功。
默认port:80
Nginx平台构架的更多相关文章
- Nginx平台构架 分类: Nginx 2015-07-13 10:55 205人阅读 评论(0) 收藏
深入理解Nginx模块发开与架构解析读书笔记. nginx在启动后,在unix系统中会以daemon的方式(可以手动关闭 nginx.conf daemon off)在后台运行,后台进程包含一个mas ...
- nginx平台初探(100%)
http://tengine.taobao.org/book/chapter_02.html 初探nginx架构(100%)¶ 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么 ...
- nginx -- nginx平台初探(100%)
初探nginx架构(100%) 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来初识一下nginx框架吧. nginx在启动后,在un ...
- nginx平台初识(二) 浏览器 HTTP 协议缓存机制详解
1.缓存的分类 缓存分为服务端侧(server side,比如 Nginx.Apache)和客户端侧(client side,比如 web browser). 服务端缓存又分为 代理服务器缓存 和 反 ...
- nginx平台初识(一)
众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来初识一下nginx框架吧. nginx在启动后,在unix系统中会以daemon的方式 ...
- Nginx开发从入门到精通 nginx平台初探
初探nginx架构(100%) 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来初识一下nginx框架吧. nginx在启动后,在un ...
- windows 平台 php_Imagick 拓展遇到的那些坑!
我的php环境是使用了phpstudy 下载地址:http://www.phpstudy.net/a.php/211.html 最终并未解决问题 持续更新~ 1.首先到官网上 http://www.i ...
- nginx源码学习_源码结构
nginx的优秀除了体现在程序结构以及代码风格上,nginx的源码组织也同样简洁明了,目录结构层次结构清晰,值得我们去学习.nginx的源码目录与nginx的模块化以及功能的划分是紧密结合,这也使得我 ...
- nginx架构
nginx平台初探(100%)
随机推荐
- Tinyhttpd精读解析
首先,本人刚刚开始开源代码精读,写的不对的地方,大家轻拍,一起进步.本文是对Tinyhttpd的一次精读,大家每天都在用着http服务,很多人也一直活跃在上层,使用IIS.Apache等,大家是否想看 ...
- C#实现的Redis扩展项目(二次封装)
Redis在当下的互联网项目当中的普及率我想都不用多说了,本文要介绍的這个项目是基于我对Redis理解程度的基础上写的一个公共类库项目,希望对各位童鞋有所帮助,也欢迎各位对我都内容提出更好的意见. 由 ...
- IE6中 PNG 背景透明的最佳解决方案
为什么要使用 PNG 图片? 简 单来说,使用 PNG 格式比起 GIF 来表现色彩更丰富,特别是表现渐变以及背景透明的渐变要比GIF格式出色很多.目前,最新的浏览器基本上都支持PNG格式.唯独有万恶 ...
- C#中消息的工作流程
C#中的消息被Application类从应用程序消息队列中取出,然后分发到消息对应的窗体,窗体对象的第一个响应函数是对象中的protected override void WndProc(ref Sy ...
- protobuf/android 交叉编译笔记
protobuf 交叉编译笔记 目标是使用 android ndk 的工具链编译出 android armeabi-v7a 可用的 protobuf 库. 交叉编译环境配置 windows 平台 下载 ...
- 读lodash源码之从slice看稀疏数组与密集数组
卑鄙是卑鄙者的通行证,高尚是高尚者的墓志铭. --北岛<回答> 看北岛就是从这两句诗开始的,高尚者已死,只剩卑鄙者在世间横行. 本文为读 lodash 源码的第一篇,后续文章会更新到这个仓 ...
- border-sizing属性
box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box. content-box,border和padding不计算入widt ...
- 解决微信公众平台IP白名单
微信公众平台,作为自媒体的旗舰级产品,越来越多的人已经投入它的怀抱.正如它的广告词所说:再小的个体,也有品牌 好吧,闲话不多说,今天要说的是它的IP白名单机制. 我们现在安装的大部分的电信的家庭级别的 ...
- Dom模型
1.dom之对象分类 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- Mysql--数据的操作
1.插入数据 1.1 插入完整数据记录 语法1: 例子: 语法2: 例子: 1.2 插入数据记录一部分 语法: 例子: 1.3 插入多条数据记录 1.插入多条完整的数据 语法: 例子: 插入多条部 ...