x86类型的CPU把指令分红了四类:环0-环3,最内层为核心指令即内核指令,其余指令在环3上,历史缘由环1,2没有使用。html
分类:阻塞型、非阻塞型、复用型、信号驱动型、异步。nginx
同步/异步:web
关注消息通知机制:正则表达式
消息通知:
同步:等待对方返回消息;算法
异步:被调用者经过状态、通知或回调机制通知调用者有关被调用者的运行状态。express
阻塞/非阻塞:vim
关注调用者在等待结果返回以前所处的状态:浏览器
阻塞:blocking,调用结果返回以前,调用者被挂起;缓存
非阻塞:nonblocking,调用结果返回以前,调用者不被挂起。性能优化
一次文件I/O请求,都会由两阶段组成:
第一步:等待数据,即数据从磁盘到内核内存;
第二步:复制数据,即数据从内核内存到进程内存。
已上的I/O分类就是给予上述两步来划分的:
阻塞型:已上两步均被阻塞;
非阻塞型:第一步是非阻塞的,第二步是阻塞的;
复用型:一个进程能监视多路I/O,此时须要一个特殊的内核函数(I/O复用器)去监视iI/O;
信号驱动型:属于异步I/O,第一步再也不阻塞,调用后再也不等待结果,继续执行其余任务;
异步:属于异步I/O,不管第一步和第二步均不参与,由内核去完成。
复用型I/O调用:
Linux:
select:1024(一个进程最多监视1024个I/O,屡次测试的结果,是由BSD发明)
poll():没有限制,是由UNIX
信号驱动型(event-driven):
epoll(Linux):由 libevent包来实现
Kqueue(BSD):
/dev/poll(Solaris)
多处理模块(MPM),用来绑定到网络端口上,接受请求, 以及调度子进程处理请求。在更高伸缩性的站点能够选择使用线程的 MPM,即 worker
或 event
; 须要可靠性或者与旧软件兼容的站点可使用 prefork
。
prefork模型:进程模型,二级结构,主进程master负责生成子进程,每一个子进程负责响应一个请求;
worker模型:线程模型,三级结构,主进程master负责生成子进程,每一个子进程负责生成多个线程,每一个线程响应一个请求;
event模型:二级结构,主进程master负责生成子进程,每一个子进程响应多个请求(相似线程模型)。
nginx有三种功能:web服务(静态的web资源服务器),web反向代理,邮件反向代理
一个master进程:
负责加载和分配配置文件、管理worker进程、平滑升级
一个或者多个worker进程:
处理并响应用户请求
缓存相关的进程:
cache loader: 载入缓存对象
cache manager: 管理缓存对象
特性:异步,事件驱动和非阻塞
并发请求处理:经过kevent/epoll/select,/dev/poll实现,此处须要注意epoll和select,优先使用epoll;
文件I/O: 高级I/O、sendfile、异步、mmap
Nginx高度模块化机制,但其模块早期不支持DSO机制,近期支持模块动态装载和卸载。
模块分类:核心模块和标准模块、第三方模块。
3.2.1 核心模块(core module)
3.2.2 标准模块
HTTP modules:
standard HTTP modules:
Optional HTTP modules(可选的http模块) :
Mail modules
Stream modules(流模块):实现传输层代理(属于四层代理)
3.2.2 第三方模块
配置指令:
4.1 性能优化相关的配置
worker_processes number | auto
一般对应cpu核心数;
worker_cpu_affinity auto | cpumask
将进程绑定在cpu上;
worker_priority number | cpumask
指定worker进程的nice值,设定worker进程的优先级[-20,20];
worker_rlimit_nofile_number
worker进程所可以打开的文件数量上限;
sendfile系统调用在两个文件描述符之间直接传递数据(彻底在内核中操做),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操做效率很高,被称之为零拷贝。可是只适用于静态资源服务器,对于反向代理则无用。
原理解释 read/write 在传统的文件传输方式(read、write/send方式),具体流程细节以下: 调用read函数,文件数据拷贝到内核缓冲区 read函数返回,数据从内核缓冲区拷贝到用户缓冲区 调用write/send函数,将数据从用户缓冲区拷贝到内核socket缓冲区 数据从内核socket缓冲区拷贝到协议引擎中 在这个过程中,文件数据其实是通过了四次拷贝操做: 硬盘—>内核缓冲区—>用户缓冲区—>内核socket缓冲区—>协议引擎 sendfile sendfile系统调用则提供了一种减小拷贝次数,提高文件传输性能的方法。 sendfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,以后数据被拷贝到内核socket缓冲区中 DMA引擎将数据从内核socket缓冲区拷贝到协议引擎中 这里没有用户态和内核态之间的切换,也没有内核缓冲区和用户缓冲区之间的拷贝,大大提高了传输性能。 这个过程数据经历的拷贝操做以下: 硬盘—>内核缓冲区—>内核socket缓冲区—>协议引擎 带有DMA收集拷贝功能的sendfile 对于带有DMA收集拷贝功能的sendfile系统调用,还能够再减小一次内核缓冲区之间的拷贝。具体流程以下: sendfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,以后,将带有文件位置和长度信息的缓冲区描述符添加到内核socket缓冲区中 DMA引擎会将数据直接从内核缓冲区拷贝到协议引擎中 这个过程数据经历的拷贝操做以下: 硬盘—>内核缓冲区—>协议引擎
4.2 定义客户端请求的相关配置
keepalive_timeout
keepalive_timeout timeout [header_timeout];
设定保持链接超时时长,0表示禁止长链接,默认为75s,能够调整短点。
keepalive_requests
keepalive_requests number;
在一次长链接上所容许请求的资源的最大数量,默认为100
keepalive_disable
keepalive_disable none | browser ...
对哪一种浏览器禁用长链接
send_timeout
send_timeout time;
向客户端发送响应报文的超时时长,此处是指两次写操做之间的间隔时长,而非整个响应过程的传输时长
client_body_buffer_size
client_body_buffer_size size;
用于接收每一个客户端请求报文的body部分的缓冲区大小;默认为16k;超出此大小时,其将被暂存到磁盘上的由client_body_temp_path指令所定义的位置。注意,这里是接收,不是下发数据,上传文件到该网站,才看获得效果
client_body_temp_path
client_body_temp_path path [level1 [level2 [level3]]];
设定用于存储客户端请求报文的body部分的临时存储路径及子目录结构和数量
这里指定的路径下存放文件,目录名为16进制的数字,是通过hash运算后,利用hash的值的最后几位数,依次分层,如三层目录进行存放文件
例子
client_body_temp_path /var/tmp/client_body 1 2 2
1 1级目录占1位16进制,即2^4=16个目录0-f
2 2级目录占2位16进制,即2^8=256个目录00-ff
2 3级目录占2位16进制,即2^8=256个目录00-ff
4.3 对客户端进行限制的相关配置
.1九、limit_rate
limit_rate rate;
限制响应给客户端的传输速率,单位是bytes/second,默认值0表示无限制
.20、limit_except
limit_except method ... { ... },仅用于location
限制客户端使用除了指定的请求方法以外的其它方法
method:GET, HEAD, POST, PUT, DELETE,MKCOL, COPY, MOVE,OPTIONS, PROPFIND,PROPPATCH, LOCK, UNLOCK, PATCH
location { limit_except GET { allow 192.168.1.0/24; deny all; } }
除了GET和HEAD 以外其它方法仅容许192.168.1.0/24网段主机使用
4.4 文件操做优化的配置
aio
对于大文件采用aio,节省cpu,而对于小文件,采用sendfile,减小拷贝;而且对于大文件aio采用directio,避免挤占文件系统缓存,让文件系统缓存更多的小文件。
aio on | off | threads[=pool];是否启用aio功能,默认是on
directio
directio size | off;通常是异步
是否同步(直接)写磁盘,而非写缓存,在Linux主机启用O_DIRECT标记,则文件大于等于给定大小时使用,例如directio 4m
open_file_cache
open_file_cache off;
open_file_cache max=N [inactive=time];
nginx能够缓存如下三种信息:缓存的是元数据,不是数据自己
(1) 文件元数据:文件的描述符、文件大小和最近一次的修改时间
(2) 打开的目录结构
(3) 没有找到的或者没有权限访问的文件的相关信息
max=N:可缓存的缓存项上限;达到上限后会使用LRU算法实现管理
inactive=time:缓存项的非活动时长,在此处指定的时长内未被命中的或命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即为非活动项,将被删除
inactive=time 为10分钟;open_file_cache_min_uses为3,表示在10分钟内访问低于3次表示非活动的,该文件就不会被缓存,会被清空
open_file_cache_errors
open_file_cache_errors on | off;
是否缓存查找时发生错误的文件一类的信息,默认值为off
open_file_cache_min_uses
open_file_cache_min_uses number;
open_file_cache指令的inactive参数指定的时长内,至少被命中此处指定的次数方可被归类为活动项,默认值为1
open_file_cache_valid
open_file_cache_valid time;
缓存项有效性的检查频率,默认值为60s
4.5 Nginx 之 实现https
要利用nginx软件实现https的页面,用到ngx_http_ssl_module模块
一、ssl
ssl on | off;
为指定虚拟机启用HTTPS protocol,建议用listen指令代替
二、ssl_certificate
ssl_certificate file;
当前虚拟主机使用PEM格式的证书文件
建立自签名的证书文件
cd /etc/pki/tls/certs/
make nginx6.crt
将生成的私钥文件解密
将这两个文件复制到配置文件里指定的路径便可
在客户的上查看生成的证书信息,命令以下
openssl s_client -connect www.e.com:443
三、ssl_certificate_key
ssl_certificate_key file;
当前虚拟主机上与其证书匹配的私钥文件
四、ssl_protocols
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
支持ssl协议版本,默认为后三个,主流版本是[TLSv1.2]
五、ssl_session_cache
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
builtin[:size]:使用OpenSSL内建缓存,为每worker进程私有,开启多大的空间来做为缓存空间
[shared:name:size]:在各worker之间使用一个共享的缓存,这样会提升缓存的命中率,提升性能。
六、ssl_session_timeout
ssl_session_timeout time;
客户端链接能够复用sslsession cache中缓存的ssl参数的有效时长,默认5m
示例:
vim /etc/nginx/conf.d/https.conf server{ listen 443 ssl; server_name www.e.com; root /app/website5; ssl_certificate /etc/nginx/ssl/nginx5.crt; ssl_certificate_key/etc/nginx/ssl/nginx5.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; } server{ listen 443 ssl; server_name www.f.com; root /app/website6; ssl_certificate /etc/nginx/ssl/nginx6.crt; ssl_certificate_key/etc/nginx/ssl/nginx6.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; }
4.6 ngx_http_rewrite_module模块:
将用户请求的URI基于PCRE regex所描述的模式进行检查,然后完成重定向替换
当旧的业务和新的业务不同,网站改名了,如网站名原来是www.dianping.com/zz后面更名为www.dianping.com/zhengzhou
一、rewrite
rewrite regex replacement [flag]
将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URI
注意:若是在同一级配置块中存在多个rewrite规则,那么会自上而下逐个检查;被某条件规则替换完成后,会从新一轮的替换检查
隐含有循环机制,但不超过10次;若是超过,提示500响应码,[flag]所表示的标志位用于控制此循环机制
若是replacement是以http://或https://开头,则替换结果会直接以重向返回给客户端
.[flag]:有如下几个关键字
last:重写完成后中止对当前URI在当前location中后续的其它重写操做,然后对新的URI启动新一轮重写检查;提早重启新一轮循环
break:重写完成后中止对当前URI在当前location中后续的其它重写操做,然后直接跳转至重写规则配置块以后的其它配置;结束循环,建议在location中使用
last 和break是在服务器内部操做的,客户端不知道,客户端访问的url不会发生变化。可是服务器端会返回替换过的新的内容。
redirect和permanent是服务器端给客户端发一个301或者302的请求,客户端须要从新发起请求,所以最终客户端看到的浏览器是url和原始的url是不同的,url会被转换,如将fj改为成fujian,那么当用户访问的是http://172.18.50.73/fj/ 最终返回结果的时候,浏览器上的url会变动改成http://172.18.50.73/fujian/
redirect:临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端从新发起请求;不能以http://或https://开头,使用相对路径,状态码:302
permanent:重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端从新发起请求,状态码:301
例子
如下是正则表达式,$1表示前面的(.*).写在server段或者location段里,如下四个选项只需四选一。
测试
curl -L http://172.18.50.73/fj/
或者直接在浏览器里输入http://172.18.50.73/fj/查看结果
二、return
return 返回一个具体的地址
return code [text];
return code URL;
中止处理并将指定的代码返回给客户端。非标准代码444关闭链接而不发送响应头。
从版本0.8.42开始,能够指定重定向URL(代码301,302,303,307和308)或响应正文文本(对于其余代码)。响应正文文本和重定向网址能够包含变量。做为特殊状况,重定向URL能够指定为此服务器本地的URI,在这种状况下,根据请求方案($ scheme)和server_name_in_redirect和port_in_redirect指令造成完整的重定向URL。
此外,能够将用于代码302的临时重定向的URL指定为惟一的参数。这样的参数应以“http://”,“https://”或“$ scheme”字符串开头。 URL能够包含变量。
测试,能正常返回text,
return URL;
中止处理,并返回给客户端指定的响应码。可是实际测试都是屡次循环重定向,致使url不能打开,用curl命令测试,出现了报错:curl: (47) Maximum(50) redirects followed致使实验不成功
三、rewrite_log
rewrite_log on | off;
是否开启重写日志, 发送至error_log(notice level)
四、set
set $variable value;
用户自定义变量,注意:变量定义和调用都要以$开头
五、if
if (condition) { ... }
引入新的上下文,条件知足时,执行配置块中的配置指令;server,location
condition:比较操做符:
== 相同
!= 不一样
~:模式匹配,区分字符大小写
~*:模式匹配,不区分字符大小写
!~:模式不匹配,区分字符大小写
!~*:模式不匹配,不区分字符大小写
文件及目录存在性判断:
-e, !-e 存在(包括文件,目录,软连接)
-f, !-f 文件
-d, !-d 目录
-x, !-x 执行
4.7 ngx_http_referer_module模块
referer是指从哪儿跳转,该字段能够用来防止盗链。
好比网页内有代码<a href=http://172.18.50.73/m.txt>test referer </a>那么再网页上test referer就会有连接到资源http://172.18.50.73/m.txt上,点击该连接,log就会有对应的referer在code以后,如这里是http://172.18.50.73/a.html,若是没有referer,则code后的字段显示“-”
.一、valid_referers none|blocked|server_names|string...;
定义referer首部的合法可用值,不能匹配的将是非法值
none:请求报文首部没有referer首部
blocked:请求报文有referer首部,但无有效值
server_names:参数,其能够有值做为主机名或主机名模式
arbitrary_string:任意字符串,但可以使用*做通配符
regular expression:被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.magedu\.com
.示例:
#定义有效的referers
#定义若是出现无效的referer将返回code 403