进程是具备必定独立功能的在计算机运行的程序的实体,进程开始是程序运行的基本单位,在支持线程的系统下,线程才是基本的运行单位,进程做为线程的容器。程序自己是指令,数据和数据结构的集合,进程才是真正运行的实例。一个程序可能会与多个进程存在关系,每一个进程均可以以同步或者异步的方式独立运行。现代计算机系统能够在同一段的时间内将多个程序进行加载,借由时分复用在一个处理器上表现出多个进程同时运行的感受——即宏观上的并行;微观上串行。使用多线程技术的操做系统,程序的平行线程,可在多 CPU 主机或网络上真正同时运行,变相提升了芯片的性能。
python
web服务器响应用户的请求,必须以某种方式工做在套接字上。通常状况下会采用如下3中方式:多进程方式,多线程方式,异步方式。
linux
1.客户端发起请求到服务器的对外网卡;
2.服务器网卡收到请求后转交给内核处理;
3.内核根据请求的对应套接字,将请求交给工做在用户空间的web服务器进程;
4.web服务器进程根据用户的请求,向内核申请系统调用,申请得到对应的资源(例如静态页面资源);
5.内核根据web服务器的请求发现它申请的是是一个磁盘文件,所以经过调用磁盘驱动程序链接磁盘;
6.内核调度磁盘,获取所须要的资源;
7.内核将资源存放在本身的缓冲区内,接下来通知web服务器进程来获取资源;
8.web服务器进程经过系统调用得到资源;
9.web服务器进程生成响应报文,经过系统调用发给内核来响应用户的请求;
10.内核将响应的报文发往网卡;
11.网卡将响应数据包发送给用户,响应结束。nginx
总结:
客户端向服务器端发送web请求的过程有两个I/O的过程,1.客户端请求的网络I/O;2.web服务器请求页面的I/O。
web
因为web服务器进程没法直接访问磁盘,而是要申请系统调用所以每次IO,都要经由两个阶段:
第一步:将数据从磁盘文件先加载至内核内存空间(缓冲区),等待数据准;
备完成,时间较长
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短。
具体能够参考下图:
根据数据传输阶段能够将I/O动做分为五类模式:
1.阻塞I/O
2.非阻塞I/O
3.I/O复用
4.信号驱动
5.异步I/Ovim
阻塞/非阻塞:关注调用者在等待结果返回以前所处的状态
阻塞:blocking,指IO操做须要完全完成后才返回到用户空间,调用结果返回以前,调用者被挂起;
非阻塞:nonblocking,指IO操做被调用后当即返回给用户一个状态值,无需等到IO操做完全完成,最终的调用结果返回以前,调用者不会被挂起。windows
同步/异步:关注的是消息通讯机制
同步:synchronous,调用者等待被调用者返回消息,才能继续执行
异步:asynchronous,被调用者经过状态、通知或回调机制主动通知调用者被调用者的运行状态centos
同步阻塞I/O模型是最为简单的I/O模型,用户线程在内核进行I/O操做时被阻塞;
用户线程经过系统调用read发起I/O读操做,由用户空间转到内核空间,内核等待数据包到达后,而后将接受到的数据拷贝到用户空间,进而完成read操做;
用户须要等待read将数据读取到buffer后,才能继续处理接收的数据。整个I/O请求的过程当中,用户线程是被阻塞的。致使了用户在发起I/O请求后到获取到数据之间的时间段内,没法作任何事情,这样对cpu是个严重的浪费。数组
用户线程发起I/O请求后,会当即返回一个响应,可是并未获取到任何数据,用户线程须要不断的发起I/O请求,直到数据正式到达,才可以真正读取到数据,继续执行接下来的操做。即这是一种“轮询”机制;
整个I/O请求的过程之中,虽然用户线程每次发出I/O请求后能够马上获得响应,可是为了等到数据,仍然须要不断的去轮询,重复请求,进而消耗了大量cpu资源;
同步非阻塞I/O是一种很是浪费cpu资源的方式,实际中不多会使用,而是会在其余I/O模型之中使用非阻塞I/O这个模型。缓存
多个链接公用一个等待机制,会阻塞进程,可是进程是阻塞在select或者poll上,并非阻塞在真正的I/O上。
用户首先将须要进行的I/O操做添加到select上,继续执行其余的工做(异步),同时等待着select系统调用返回,当数据到达时候,I/O被激活,select函数返回,用户线程正式发起read请求,读取数据而且继续运行。
从流程上看,使用了select函数进行I/O请求和同步阻塞模型没有大的区别,甚至还多了添加监视I/O,以及调用select函数等的额外附加操做,效率上相对低下,并且发生了两次的阻塞,可是,第一次阻塞在select上时候,select函数能够监控多个I/O是否已经有I/O操做准备就绪,便可达到在同一个线程内同时处理多个I/O请求的目的。而不一样于阻塞I/O,一次仅仅可以监控一个I/O。
虽然I/O多路复用容许同时处理多个I/O请求,可是每一个I/O请求的过程仍是阻塞的(在select函数上进行阻塞),平均时间甚至比同步阻塞I/O模式还长。若是用户线程仅仅是注册本身须要的I/O请求,而后去作本身的事情,等到数据到来后再进行处理,则能够提升cpu的利用率
I/O多路复用模型是最常使用的I/O模型,可是其异步程度有限,由于它使用了会阻塞线程的select系统调用,所以,I/O多路复用技术也只能被称为,异步阻塞I/O模型,并不是真正的异步I/O。服务器
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程,IO多路复用适用以下场合:
1.当客户端处理多个描述符时(通常是交互式输入和网络套接口),必须使用I/O复用
2.当一个客户端同时处理多个套接字时,此状况可能的但不多出现
3.当一个TCP服务器既要处理监听套接口,又要处理已链接套接口,通常也要用到I/O
复用
4.当一个服务器即要处理TCP,又要处理UDP,通常要使用I/O复用
5.当一个服务器要处理多个服务或多个协议,通常要使用I/O复用
信号驱动IO:signal-driven I/O
用户进程能够经过sigaction系统调用注册一个信号处理程序,而后主程序能够继续向下执行,当有IO操做准备就绪时,由内核通知触发一个SIGIO信号处理程序执行,而后将用户进程所须要的数据从内核空间拷贝到用户空间。
此模型的优点在于等待数据报到达期间进程不被阻塞。用户主程序能够继续执行,只要等待来自信号处理函数的通知。
该模型并不经常使用。
异步IO与信号驱动IO最主要的区别是信号驱动IO是由内核通知什么时候能够进行IO操做,而异步IO则是由内核告诉咱们IO操做什么时候完成了。具体来讲就是,信号驱动IO当内核通知触发信号处理程序时,信号处理程序还须要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后内核直接通知能够进行后续操做了
相比于IO多路复用模型,异步IO并不十分经常使用,很多高性能并发服务程序使用IO多路复用模型+多线程任务处理的架构基本能够知足需求。何况目前操做系统对异步IO的支持并不是特别完善,更多的是采用IO多路复用模型模拟异步IO的方式(IO事件触发时不直接通知用户线程,而是将数据读写完毕后放到用户指定
的缓冲区中)
I/O模型的实现主要依赖于如下几种方式:
Select:linux实现,对应I/O复用模型,BSD4.2最先实现
Poll: linux实现,对应I/O复用模型,System V Unix最先实现
Epoll: linux实现,对应I/O复用模型,具备信号驱动I/O模型的一部分特性
Kqueue: FreeBSD实现,对应I/O复用模型,具备信号驱动I/O的某些特性
/dev/poll: SUN的Solaris实现,对应I/O复用模型,具备信号驱动的I/O模型的一部分特性
Iocp: windows实现,对应异步I/O模型。
注意:
虽然Windows的Locp最为优秀,可是,目前不多有支持asynchronous I/O的系统,可是因为其系统自己的局限性,大型服务器仍是在Linux和UNIX下。并且正如上面所述,kqueue、epoll、/dev/poll 与 IOCP相比,就是多了一层从内核copy数据到应用层的阻塞,从而不能算做asynchronous I/O类。可是,这层小小的阻塞无足轻重。
Select:
POSIX所规定,目前几乎在全部的平台上支持,其良好跨平台支持也是
它的一个优势,本质上是经过设置或者检查存放fd标志位的数据结构来进行下一步处理
缺点:
1.单个进程可监视的fd数量被限制,即能监听端口的数量有限
cat /proc/sys/fs/file-max
2.对socket是线性扫描,即采用轮询的方法,效率较低
3.select 采起了内存拷贝方法来实现内核将 FD 消息通知给用户空间,这样一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大.
poll
本质上和select没有区别,它将用户传入的数组拷贝到内核空间,而后查询每一个fd对应的设备状态,其没有最大链接数的限制,缘由是它是基于链表来存储的,大量的fd的数组被总体复制于用户态和内核地址空间之间,而无论这样的复制是否是有意义
poll特色是“水平触发”,若是报告了fd后,没有被处理,那么下次poll时会再次报告该fd
边缘触发:只通知一次
epoll:
在Linux 2.6内核中提出的select和poll的加强版本
支持水平触发LT和边缘触发ET,最大的特色在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,而且只会通知一次。使用“事件”的就绪通知方式,经过epoll_ctl注册fd,一旦该fd就绪,内核就会采
用相似callback的回调机制来激活该fd,epoll_wait即可以收到通知
优势:
1.没有最大并发链接的限制:能打开的FD的上限远大于1024(1G的内存能监听约10万个端口)
2.效率提高:非轮询的方式,不会随着FD数目的增长而效率降低;只有活跃可用的FD才会调用callback函数,即epoll最大的优势就在于它只管理“活跃”的链接,而跟链接总数无关
3.内存拷贝,利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减小复制开销。
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
他将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特色是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
特性:
1.模块化的设计,有不错的拓展性;
2.高可靠性;
3.支持热部署:不停机更新配置文件,升级版本,更换日志文件;
4.较低的内存消耗:10000个keep-alive(长链接)链接模式下的非活动链接,仅仅占用2.5M的内存空间;
5.event-driven(事件驱动),aio(异步非阻塞I/O),mmap(一种内存映射文件的方法),sendfile(内核直接封装报文)
基本的功能:
1.静态资源的web服务器;
2.http协议的反向代理器;
3.pop3/imap4协议反向代理服务器(邮件)
4.FastCGI(LNMP),uWSGI(python)等协议;
5.模块化(非DSO);
master/worker结构
一个master进程:负责加载和分析配置文件,管理worker进程,平滑升级。
一个或者多个worker进程:负责处理并响应用户的请求。
缓存相关的进程:
cache loader:载入缓存的对象;
cache manager:管理缓存对象。
nginx是高度模块化的,可是其模块在早期是不支持DSO(动态装卸载)机制的;1.9.11版本以后才支持动态的装卸载;
分类:
核心模块:core module
标准模块:
http模块:ngxhttp
http core modules 默认功能
http optional modules 须要编译时候指定
mail模块 : ngxmail
stream模块: ngxstream*
第三方模块
这里能够得到官方rpm包,以后本地安装便可
http://nginx.org/packages/centos/7/x86_64/RPMS/
Fedora-EPEL源内有nginx的安装,nginx未被直接收录到base源中。
https://mirrors.aliyun.com/epel/7/x86_64/
1.安装编译环境
yum groupinstall "development tools" -y
2.安装编译时可能会须要的包
yum install pcre-devel openssl-devel zlib-devel -y
3.添加nginx系统帐号
useradd -r nginx
4.获取nginx源码包,解压并编译
#获取nginx源码包 wget http://nginx.org/download/nginx-1.14.0.tar.gz #解压 tar -xvf nginx-1.14.0.tar.gz cd nginx-1.14.0/ #编译 ./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio make &&make install
编译安装选项:
--prefix=/etc/nginx 安装路径
--sbin-path=/usr/sbin/nginx 指明nginx程序文件安装路径
--conf-path=/etc/nginx/nginx.conf 主配置文件安装位置
--error-log-path=/var/log/nginx/error.log 错误日志文件安装位置
--http-log-path=/var/log/nginx/access.log 访问日志文件安装位置
--pid-path=/var/run/nginx.pid 指明pid文件安装位置
--lock-path=/var/run/nginx.lock 锁文件安装位置
--http-client-body-temp-path=/var/cache/nginx/client_temp 客户端
body部分的临时文件存放路径,服务器容许客户端使用put方法提交大数据时,临时存放的磁盘路径
--http-proxy-temp-path=/var/cache/nginx/proxy_temp 做为代理服务器,服务器响应报文的临时文件存放路径
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 做为fastcgi代理服务器,服务器响应报文的临时文件存放路径
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 做为uwsgi代理服务器,服务器响应报文的临时文件存放路径
--http-scgi-temp-path=/var/cache/nginx/scgi_temp 做为scgi反代服务器,服务器响应报文的临时文件存放路径
--user=nginx 指明以那个身份运行worker进程,主控master进程通常由root运行
--group=nginx
--with-http_ssl_module 表示把指定模块编译进来
5.修改配置文件,添加环境变量
vim /etc/nginx/nginx.conf #修改运行用户为nginx user nginx; #添加环境变量 vim /etc/profile.d/nginx.sh PATH=/usr/local/nginx/sbin:$PATH source /etc/profile.d/nginx.sh
基本配置完成下面的配置是为了省事
6.编写centos7的systemd管理nginx的脚本
vim /usr/lib/systemd/system/nginx.service #如下是文件内容 [Unit] Description=the nginx web server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/bin/rm -f /run/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/bin/kill -s HUP $MAINPID KillSignal=SIGQUIT TimeoutStopSec=5 KillMode=process PrivateTmp=true [Install] WantedBy=multi-user.target #保存退出后添加systemd管理 systemctl daemon-reload #启动nginx systemctl strat nginx
nginx安装成功