Linux服务 Nginx(一)
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等.
http协议:80/TCP,HyperText Transfer Procotol
html:HyperText Mark Language
早期http协议只能以文本格式传输内容,直到http1.0引入MIME(Multipurpose Internet Mail Extensior)以后可以将多媒体信息以文本格式编码,然后传输到浏览器端再还原回来;
major/minor
text/plain
image/jpeg
URL:统一资源定位符;用于唯一确定一个资源的位置;
格式:scheme://server[:port]/path/to/source
http事物:request → response
request:
<method><URL><version>
<HEADERS>
<body>
response:
<version><status><reason phrase>
<HEADERS>
<body>
method:
GET,HEAD,PUT,POST,DELETE,TRACE,OPTIONS等;
status:
1xx:信息类,提供一些信息提示;
2xx:成功类,200(OK);
3xx:重定向类,301,302,304;
4xx:客户端错误类,403,404;
5xx:服务器端错误类,502;
HEADER:
通用首部
请求首部
响应首部
实体首部
Web页面:多个资源(资源引用);
pv:page view
uv:user view
认证:
基于IP认证;
基于用户认证;
basic,digest
资源映射:
DocumentRoot;
Alias:路径别名;
httpd:MPM(多路处理模块)
prefork:主进程生成多个子进程,每个子进程处理一个请求;
worker:主进程生成多个子进程,每个子进程生成多个线程,每个线程处理一个请求;
event:主进程生成多个子进程,每个子进程处理多个请求;
I/O类型:
I/O可以看作是一方(被调用方)提供服务,而另一方(调用方)需要调用(库调用,系统调用)其服务,而这个请求和响应的过程就是一个I/O过程;
同步(synchronous )和异步(asynchronous ):
关注的是消息通知机制;
同步:调用发出之后不会立即给出回应,但一旦返回,则给出的必是最终结果;
异步:调用发出之后,被调用方会立即返回消息,但返回的并非最终结果;被调用方通过状态或者通知机制等来通知调用方;
阻塞(block)和非阻塞(nonbolck):
关注的是调用方等待被调用方返回结果时的状态;
阻塞:被调用方返回结果之前,调用方会被挂起(不可中断睡眠状态),即什么都干不了;调用方只有在的到返回结果之后才能继续;
非阻塞:被调用方返回结果之前,调用方不会被挂起;
举个例子:一天早上起来你特别的饿,然后随便洗漱了一下,就出门吃早饭去了.正想着要吃什么呢!向四周一瞥,就看见一个面馆,然后你就决定吃面了!进门叫老板:老板来碗炸酱面,然后你就找一个座位坐下来了,看着老板的动作,一动不动(阻塞)的那种(强调:没有手机可看),老板默默(同步)的就开始做(种水稻,收粮,磨面,和面,擀面条,进锅,出锅,入盘),过了这么长时间,老板吼了一声:面好了,因为服务员还没上班,你只能屈尊自己去取面了,然后就狼吞虎咽了起来;
还有一天,好了其实这些前戏也没什么用,咱就直接住面馆得了.早上起来叫老板:老板,来碗面,老板说:好的(异步).然后就去走常规的做面流程去了,因为咱都住面馆里了,一定跟老板比较熟悉了,老板也不怕你跑了,不算账,你干等着也没意思,就看看这,再看看那,看见美女就出去(非阻塞)搭个讪,或者玩玩手机,翻翻博客,就这样过了一段时间,老板可下做好了(异步),吼了一声:面好了,都这么熟悉了就自己动手吧,去台子上取面,然后狼吞虎咽了起来;
I/O模型:
blocking IO:阻塞型IO
nonblocking IO:非阻塞型IO
IO multiplexing:复用型IO
singal driven IO:事件驱动型IO
asynchronous:异步IO
例如:一次read操作;
1.因为用户空间的进程是没有权限直接访问硬件的,所以有read的需求时,用户空间的进程首先会去请求内核,调用相应的函数(系统调用),剩下的操作交给内核.内核就会去硬盘中读取相应的数据,然后将数据复制到内核内存空间中,接着内核再将内核内存中的数据复制到应用进程内存空间中;其实真正执行I/O过程的就是从内核内存空间到应用进程内存空间这一步;
2.1阻塞型IO:
整个调用过程,在被调用方来看(内核),可以分为两个过程,就是数据从磁盘到内核,再由内核到应用进程的过程;当调用方(应用进程)发起调用请求之后,调用方会被挂起,等待内核处理数据,在没有的到结果之前什么都做不了,只能发呆;
2.2非阻塞型IO:
内核的工作过程同上,不同的就是应用程序发起调用请求后,不会被挂起,而是可以去做其他的事情,但是内核可不想老板一样会通知你面好了,所以应用程序会每隔一段时间就来看看(忙等待)内核是否以完成操作,如果没完成就在去干其他事;如果完成了(此处的完成指的是数据已从硬盘到内核了),应用进程还是会进入阻塞状态,等待数据由内核内存空间到自己的内存空间.就像面好了,但是你要自己去台子上端面一样;这种非阻塞IO其实并没有比阻塞IO在性能上有多大提升;
2.3复用型IO:
当调用方需要对内核发起调用时,这一次不是直接将请求交个内核,而是将请求交给了内核的代理人,他会帮内核记录有谁发起了调用,然后按照顺序转交给内核,让内核处理;举个例子:因为你总去这家面馆吃饭,老板整了大钱,一下子请了一个服务员(代理(select()调用,poll()调用))和两个大厨,从此老板就做了甩手掌柜了,这天你来吃面,新面孔,一个服务员拿个小本子向你走来,请你点面,你要了小碗炸酱面他用小本本记了下来,然后告诉大厨A去做炸酱面了,你转念一想小碗的可能不够吃,就将服务员叫来,又点了一个中碗的手擀面,服务员用小本本记了下来,然后就去告诉大厨B赶紧做手擀面了,然后你就可以一起吃两种面了;select()一般来讲只能支持1024的请求,超过这个数,性能就会下降,有可能就会拒绝服务了;其实这种IO模型也是阻塞的,只不过是阻塞到那个代理上了;但是代理(select())是可以继续接受其他请求的;
2.4事件驱动型IO:
当调用者发出请求之后,被调用者(内核)会立即告诉调用者(应用进程):我已经受到你的请求了,你不用在这等着,该干嘛干嘛去!操作完成以后我会告诉你;举个例子:继续吃面,你:老板,来碗面!老板:好的!,然后你就出去了,老板就开始做了,过一段时间面好了,老板掏出电话就给你call(主动通知)(此时只是数据刚由硬盘到内核内存加载完毕)过去了(鬼知道你们怎么留得电话!),说:面好了!来吃面.你收到以后屁颠屁颠的就回来了,去老板的台子上端面(由内核内存到应用进程内存(阻塞)),然后找个座位就狼吞虎咽了起来;从这个过程看,只是内核的第一阶段(硬盘到内核)解放了,可以接收多个请求进来,但是第二阶段(内核到应用进程)也就是真正的IO过程还是阻塞的,它要逐个复制;我们还要考虑一种情况,就是当第一个请求在进行内核的第二步时,第二个请求的数据也已经准备完成了,这个时候内核就要通知发起第二个请求的进程来取数据了,但是现在进程被阻塞在第一个请求上了,内核通知发出以后,要是不接收信号就会消失,这就得不偿失了;所以事件驱动型IO提供了两种通知机制:
水平触发:多次通知;
边缘触发:只通知一次;但是可以通过触发机制,主动请求获得通知;
2.5 异步IO:
异步IO就是调用方发来请求,内核受到以后,会将第一步和第二步都完成以后,再通知调用方,来取数据;就像老板做完面以后,还将面放到了桌子上,你过来直接吃就可以了;
Nginx使用的就是事件驱动型IO,并且还支持异步IO;
libevent:高性能网络库;
epoll();
Nginx特性:
1.模块化设计,较好的扩展性;
Nginx早期版本模块是不支持不支持动态装卸载的,也就是说模块只能直接编译成Nginx的组成部分,只要Nginx启动,模块的功能就会随着启动;但是Tengine支持模块的动态装卸载;
2.高可靠性;
Nginx会启动一个主控进程(master),然后由主控进程生成多个工作进程(worker);
master:负责读取加载配置文件,创建绑定和关闭套接字,以及启动和关闭子进程,无需重启程序,让新配置文件中的设置生效,完成平滑版本升级等;
worker:worker是有多种类型的,有的负责缓存加载,有的负责管理缓存,有的负责响应用户请求等等;
3.低内存消耗;
Nginx一个线程响应多个请求,所以对内存的消耗特别的低;
4.支持热部署;
不停机更新配置文件,进行日志文件滚动以及进程版本升级;
5.支持事件驱动IO,AIO(异步IO),mmap(内存映射机制);
Nginx基本功能:
静态资源的web服务器,能缓存打开的文件描述符,从而提高再次打开此文件的时间;
Nginx是一种支持http,smtp,pop3协议的反向代理服务器;
反向代理服务器:
web服务器的工作模式,是在web服务器和浏览器客户端直接进行的,web服务器本身处理请求和响应;这样就造成了web服务器直接面对众多的客户端,需要自己建立连接,维持连接,处理请求,这样会使web服务器压力过大,还容易受到互联网上的攻击;为了解决这些问题,我们可以在浏览器和web服务器之间放一台主机,它自己会对外生成自己是web服务器,所有的用户请求都会发给这台主机,所以这台主机也会监听在80端口,接受http请求,但是这台主机本身并不会提供任何数据,当它收到客户端发来的请求时,他会通过服务进程(代理进程)将其接到自己的用户空间,并解析用户请求,判断此客户端是否被允许访问,如果允许访问,这台主机就会对用户请求做再次封装,然后再发送给后端的web服务器;当web服务器返回响应报文后,它会将受到的响应报文再封装成浏览器客户端的识别的响应报文格式,然后发送给浏览器端;这台主机就是反响代理服务器;反向代理也可以是N级的,也就是说有的是不用直接连接web服务器的,而连接的是另一台反向代理服务器;http的请求方法中有一个叫做trace的,使用这个方法就可以探测客户端和web服务器之间有多少代理服务器;反向代理服务器一般只给部分网站提供反代服务;有反向就有正向,正向代理是将对任何对网站访问都提交给代理服务器,然后正向代理服务器将自己作为客户端,请求资源,最后将资源返回给客户端;
代理服务器起到的作用其实不光是代理和隔离客户端与web服务器,还能起到加速的功能,对于一些不常变化的数据,代理服务器可以将其以key-value的方式缓存一份在本地(key:URL,value:数据流),当有客户端来请求同样的资源时,如果缓存尚未失效,就可以直接将资源响应给客户端,就不用在去请求web服务器了;
支持负载均衡:
当一台后端服务器无法承受前面多台代理服务器的请求时,可以通过添加后端服务器的方法,来将代理服务器的请求均衡分配到不同后端服务器上,来达到负载均衡的目的;
支持FastCGI(fpm,LNMP);
支持模块化(非DSO机制),过滤器zip,SSI以及支持对图像大小进行处理;
支持SSL;
Nginx的扩展功能:
支持基于名称和IP的虚拟主机;
支持keepalive;
支持平滑升级;
支持定制访问日志,支持使用日志缓冲区提供日志存储功能;
支持URL重写;
支持路径别名;
支持基于IP及用户的访问控制;
支持速率限制,并发数限制;
Nginx的基本架构:
一个master生成多个worker;
事件驱动:Linux:epoll(边缘触发),BSD:kqueue;
复用器:select,poll,rt signal
支持sendfile,sendfile64;
sendfile可以实现将网络上发来的请求,让其不经过用户空间,而在内核空间直接返回响应,从而提高性能;
支持AIO,mmap(上面已经提过了);
Nginx的工作模式:非阻塞,事件驱动,由一个master进程生成多个worker进程,每个worker响应n个请求;
作为为恶霸服务器时总体能够支持的并发连接数=worker * n;
模块类型:http://nginx.org
Nginx自带:
核心模块;
Standard HTTP modules:标准的http协议模块;
Optional HTTP modules:可选的http协议模块;
Mail modules:邮件模块;
非自带:编译安装Nginx时,需要指定模块文件位置;
第三方模块;
安装方法:
使用epel源安装:
yum install nginx.x86_64
编译安装
安装依赖开发工具:
yum install pcre-devel 为了支持url重写;
groupadd -r nginx
useradd -g nginx -r nginx
tar xf nginx-1.15.8.tar.gz
cd nginx-1.15.8/
./configure –help
一般—with的是默认没有启用的,--without的是默认启用的;
./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --user=nginx --group=nginx --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_mp4_module --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi –http-uwsgi-temp-path=/var/tmp/nginx/uwsgi
--prefix=/usr/local/nginx 安装位置;
--conf-path=/etc/nginx/nginx.conf 配置文件位置; 如果放在/etc中需要定期备份,如果放在安装软件的目录中,软件更新升级的时候方便一点;
--user=nginx worker以哪个用户的身份运行;
--group=nginx 以哪个组的身份运行;
--error-log-path=/var/log/nginx/error.log 错误日志的存放位置;
--http-log-path=/var/log/nginx/access.log 访问日志的存放位置;
--pid-path=/var/run/nginx/nginx.pid pid文件位置;
--lock-path=/var/lock/nginx.lock 互斥锁;
--with-http_ssl_module 启用ssl模块;
--with-http_stub_status_module 启用状态页面;
--with-http_gzip_static_module 启用压缩静态内容的gzip模块;
--with-http_flv_module 支持流媒体;
--with-http_mp4_module 支持mp4功能;
--http-client-body-temp-path=/var/tmp/nginx/client 指定客户端body的临时存放路径;
--http-proxy-temp-path=/var/tmp/nginx/proxy 以下文件是跟临时文件有关的;
--http-fastcgi-temp-path=/var/tmp/nginx/fastcgi
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi
make ; make install
mkdir -pv /var/tmp/nginx/{clirnt,fastcgi,proxy,uwsgi}
/usr/local/nginx/sbin/nginx
netstat -nultp
配置文件:
main配置段:全局配置段;
event{}配置段:定义event模型工作特性;
http{}:定义http协议相关的配置;
配置指令:以分号结尾;
语法格式:directive value1 [value2 …]
支持使用变量:
内置变量:
模块提供的内建变量;
自定义变量:
set var_name value
主配置段的指令:
用于调试,定位问题;
正常运行必备的配置;
优化性能的配置;
事件相关的配置;
注:根据马哥视频做的学习笔记,如有错误,欢迎指正;侵删;