陶辉Nginx核心100讲笔记


csdn的图片显示有问题,为了更好的阅读体验,请移步nginx-blog

一、初始Nginx

1.1 nginx应用场景

![image.png](https://img-blog.csdnimg.cn/img_convert/5a930a077c0e7f4a8d17fe69e4350e9c.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=586&id=LL1zE&margin=[object Object]&name=image.png&originHeight=1172&originWidth=2112&originalType=binary&ratio=1&rotation=0&showTitle=false&size=928999&status=done&style=none&taskId=uddb9f030-3d60-4932-8c4c-cced0a440f1&title=&width=1056)

1.2 Nginx优点

![A82E994B-DDE1-4C48-A3B1-4CC72150E101.png](https://img-blog.csdnimg.cn/img_convert/8fcb61262648556243573ef2cebdcfcc.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=511&id=u59c349bd&margin=[object Object]&name=A82E994B-DDE1-4C48-A3B1-4CC72150E101.png&originHeight=1022&originWidth=1938&originalType=binary&ratio=1&rotation=0&showTitle=false&size=973178&status=done&style=none&taskId=udfc4d868-cc8d-4074-9e67-588b458f05f&title=&width=969)

1.3 Nginx组成

![image.png](https://img-blog.csdnimg.cn/img_convert/988d8f4f89b21b29a6f917d1ec6385b2.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=413&id=u4baf27df&margin=[object Object]&name=image.png&originHeight=826&originWidth=1516&originalType=binary&ratio=1&rotation=0&showTitle=false&size=690551&status=done&style=none&taskId=u093b0ccd-1ef0-476e-8b8f-a703c56616d&title=&width=758)

1.4 Nginx配置语法

![image.png](https://img-blog.csdnimg.cn/img_convert/9ecab8688370426e90478d09afdef67e.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=415&id=u546695db&margin=[object Object]&name=image.png&originHeight=830&originWidth=1480&originalType=binary&ratio=1&rotation=0&showTitle=false&size=815741&status=done&style=none&taskId=u2c247769-0483-4af3-a4c5-377f3d3f97e&title=&width=740)

![image.png](https://img-blog.csdnimg.cn/img_convert/2d721ec44ea250782afc3890899d74a8.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=438&id=ueaec73dd&margin=[object Object]&name=image.png&originHeight=876&originWidth=1380&originalType=binary&ratio=1&rotation=0&showTitle=false&size=328505&status=done&style=none&taskId=u790be97a-4b0b-4db9-a113-d50a1b57b6c&title=&width=690)![image.png](https://img-blog.csdnimg.cn/img_convert/ba61ca6096aa5c88c817e024645b4705.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=434&id=uc3b7e24a&margin=[object Object]&name=image.png&originHeight=868&originWidth=1548&originalType=binary&ratio=1&rotation=0&showTitle=false&size=473105&status=done&style=none&taskId=u7ab99a62-6fc6-40aa-bcf5-ac954f839af&title=&width=774)

![image.png](https://img-blog.csdnimg.cn/img_convert/09875d39f3d851c309b29b91eb6b05c3.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=426&id=ufad33ad3&margin=[object Object]&name=image.png&originHeight=852&originWidth=1460&originalType=binary&ratio=1&rotation=0&showTitle=false&size=423949&status=done&style=none&taskId=ue31bfd4f-7edb-48e8-bee3-31d0eadd078&title=&width=730)

1.5 Nginx 命令行

![image.png](https://img-blog.csdnimg.cn/img_convert/09e3250a79debfec4cd89096ae285712.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=432&id=ufa43ac01&margin=[object Object]&name=image.png&originHeight=864&originWidth=1456&originalType=binary&ratio=1&rotation=0&showTitle=false&size=646525&status=done&style=none&taskId=ua093ced4-fbab-4ecb-b65f-e2afac5a6ab&title=&width=728)

1.6 日志

web日志分析工具:goaccess

1.7 SSl安全协议

![image.png](https://img-blog.csdnimg.cn/img_convert/765e71d44e2b05963f0da598491c8bec.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=433&id=u167fc52b&margin=[object Object]&name=image.png&originHeight=866&originWidth=1512&originalType=binary&ratio=1&rotation=0&showTitle=false&size=771135&status=done&style=none&taskId=ueb77d876-4757-4a44-929f-609bbe79b3b&title=&width=756)

![image.png](https://img-blog.csdnimg.cn/img_convert/9194fd240c0abcc046ff29bc20fba349.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=428&id=uc42cac93&margin=[object Object]&name=image.png&originHeight=856&originWidth=1486&originalType=binary&ratio=1&rotation=0&showTitle=false&size=651764&status=done&style=none&taskId=u66318642-6518-4f37-881c-daa3d2ee47b&title=&width=743)

1.7.1 对称加密

![image.png](https://img-blog.csdnimg.cn/img_convert/7c1b704a6ed8c85e613c15786dacc07a.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=418&id=u555e3556&margin=[object Object]&name=image.png&originHeight=836&originWidth=1326&originalType=binary&ratio=1&rotation=0&showTitle=false&size=194153&status=done&style=none&taskId=u171d1452-7cc7-4148-819a-3072fd184a3&title=&width=663)

基于异或算法,明文可以转为密文,密文也可以转为明文,而且性能好,只需要一次便历过程。

1.7.2 非对称加密

![image.png](https://img-blog.csdnimg.cn/img_convert/fd3fbb5fbb960452435c45b3cc29224d.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=355&id=u8daa4a38&margin=[object Object]&name=image.png&originHeight=710&originWidth=1590&originalType=binary&ratio=1&rotation=0&showTitle=false&size=341051&status=done&style=none&taskId=u9747b1f9-8adb-4fff-904d-31432c7860a&title=&width=795)
自己发出去的文本用私钥加密,接收方使用公钥加密;反之,接收方回复消息使用公钥加密,自己使用私钥解密。

![image.png](https://img-blog.csdnimg.cn/img_convert/39d03fffcf3a084561b1c6156a12bcb1.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=450&id=u88a77c62&margin=[object Object]&name=image.png&originHeight=900&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=529082&status=done&style=none&taskId=ue0ecf4c4-4058-4ead-8437-50c04108c19&title=&width=767)

在Nginx上可以设置为:

ssl_verify_client on;#以便 OCSP 验证工作
ssl_ocsp on;#启用客户端证书链的 OCSP 验证
resolver 192.0.2.1;#解析器应指定为解析 OCSP 响应器主机名

![image.png](https://img-blog.csdnimg.cn/img_convert/69e078c9d8fdb1af94f76bdd54a26491.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=424&id=u08d2c9e7&margin=[object Object]&name=image.png&originHeight=848&originWidth=1510&originalType=binary&ratio=1&rotation=0&showTitle=false&size=644753&status=done&style=none&taskId=u3637df4c-3da2-4c23-8cc1-93edeb8830b&title=&width=755)

浏览器获取到证书后如何生效,需要验证证书链:

![image.png](https://img-blog.csdnimg.cn/img_convert/2c002bc589a99d0a9f8e65007aa060de.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=403&id=u7bd89cd0&margin=[object Object]&name=image.png&originHeight=806&originWidth=1596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=706121&status=done&style=none&taskId=u25b277c3-4a01-4f3a-aa71-ab14d0bed78&title=&width=798)
说明:
站点证书由三部分构成(根证书、二级证书、主证书),操作系统的根证书很难修改,大部分浏览器(除firebox)使用的是操作系统的证书库。所以浏览器在验证证书是否有效时,除了验证nginx发过来的两个证书(二级证书和主站点证书)是否过期外,还要要在根证书是否有效且被认证。

1.7.3 TLS的通信过程

![image.png](https://img-blog.csdnimg.cn/img_convert/f339ad9338f8dc16768cc927f20e99cd.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=445&id=ufb99ad14&margin=[object Object]&name=image.png&originHeight=890&originWidth=1614&originalType=binary&ratio=1&rotation=0&showTitle=false&size=717638&status=done&style=none&taskId=u72971e82-41b9-420d-b364-d9cf4dc558a&title=&width=807)

第一步:浏览器向服务器发送clinet hello消息,告诉服务器我支持哪些加密算法;
第二步:服务器把最偏向的加密算法发送给客户端,发送server hello消息,告诉服务器最终选择哪个安全套件;
第三步:服务器向客户端发送证书链;
第四步:客户端验证服务器相关证书;
第五步:服务器发送server hello done,且在第五步前向客户的发送加密算法的公共参数;
第六步:浏览器根据公共参数生成自己的私钥,再把公钥发送给服务器;
第七步:服务器生成自己的一对公钥和私钥,用自己的私钥和客户端发来的私钥,生成双方加密的密钥。
第八步:浏览器根据服务器发来的公钥和自己生成的私钥也会生成双方加密的密钥,通过非对称加密,二者生成的密钥是相同的。
第九步:服务器使用生成的密钥加密发送的消息,传给浏览器。

Nginx对加密算法的优化:

对于小文件,Nginx需要优化非对称加密算法,适当弱化密码强度;
对于大文件,需要考虑优化对称加密算法(AES)。

1.7.4 使用免费SSL证书把Http网站改造为Https网站
[root]:yum install python2-certbot-nginx
[root]:certbot --nginx --nginx-server-root=conf目录 -d 需要安装证书的server name

1.8 基于openResty使用lua实现简单服务

1.8.1 下载

openresty.org–>下载–>源码发布–下载–>解压

1.8.2 分析目录结构

![image.png](https://img-blog.csdnimg.cn/img_convert/8e64c04ec1fa6875e0165ab5bc5a2f3d.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=216&id=u1ff86b65&margin=[object Object]&name=image.png&originHeight=432&originWidth=1130&originalType=binary&ratio=1&rotation=0&showTitle=false&size=497671&status=done&style=none&taskId=u7369271d-1f04-43a0-9dcf-43f18a49c33&title=&width=565)

1.8.3 编译

编译一个基本的openresty .configure
make&make install

1.8.4 添加lua代码

![image.png](https://img-blog.csdnimg.cn/img_convert/8ff7fd74b248eb71038c46e939aab14f.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=295&id=u2936c073&margin=[object Object]&name=image.png&originHeight=590&originWidth=1524&originalType=binary&ratio=1&rotation=0&showTitle=false&size=230878&status=done&style=none&taskId=uba1fba36-a7c0-4dda-9ee6-9a7020d9543&title=&width=762)

1.8.5 运行

二、Nginx架构基础

![image.png](https://img-blog.csdnimg.cn/img_convert/92991b0bb602363177d3d0211bc1591f.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=438&id=ud746df97&margin=[object Object]&name=image.png&originHeight=876&originWidth=1600&originalType=binary&ratio=1&rotation=0&showTitle=false&size=816530&status=done&style=none&taskId=ua40d20a8-ec6a-4ac8-b50b-dac5dec87ec&title=&width=800)

2.1 Nginx的进程结构

![image.png](https://img-blog.csdnimg.cn/img_convert/132a2632c10ec0bc69bcf6e24f431b67.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=427&id=u487ab640&margin=[object Object]&name=image.png&originHeight=854&originWidth=1412&originalType=binary&ratio=1&rotation=0&showTitle=false&size=560212&status=done&style=none&taskId=u3bf290f2-ccfd-458a-94da-318e85a25e4&title=&width=706)
Nginx包含master进程和子进程,子进程又分为两大类,Cache相关进程和worker进程,子进程间的通信是通过共享内存来解决的。
master进程:用来管理worker进程,负责监控worker进程正常工作,是否需要重新加载配置文件等。
缓存:是多个worker进程共享的,同时也会被cache manager(缓存的关联)和cache loader(缓存的载入)进程使用。cache manager和cache loader进程使用是用于后端发来的动态请求做缓存的来使用的。
为了保证Nginx的高可用性,nginx被设计为多进程的模式,因为多线程不同线程会共享一块内存空间,线程间相互影响,如果一个第三方模块导致地址越界等问题会使得整个Nginx全部挂掉。

2.2 使用信号管理Nginx父子进程

![image.png](https://img-blog.csdnimg.cn/img_convert/76a9a9f2f5fadfbd23b014247897b9cf.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=420&id=u1019b4de&margin=[object Object]&name=image.png&originHeight=840&originWidth=1520&originalType=binary&ratio=1&rotation=0&showTitle=false&size=556853&status=done&style=none&taskId=u1a9a6968-3180-4cb3-9b6f-c758e22b7be&title=&width=760)

2.3 reload流程

![image.png](https://img-blog.csdnimg.cn/img_convert/13350fb3a5e7a3daa389954c93f8d6d7.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=480&id=ua44596f6&margin=[object Object]&name=image.png&originHeight=960&originWidth=1794&originalType=binary&ratio=1&rotation=0&showTitle=false&size=965935&status=done&style=none&taskId=u8e0ac1bc-328a-46e5-b34d-a6332fcd8a0&title=&width=897)

![image.png](https://img-blog.csdnimg.cn/img_convert/47fc12acc8a8782671c24e68ac3d7614.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=494&id=ue50573a9&margin=[object Object]&name=image.png&originHeight=988&originWidth=1800&originalType=binary&ratio=1&rotation=0&showTitle=false&size=579088&status=done&style=none&taskId=ua1f257c9-6f0c-4c10-886d-298b0cd6a84&title=&width=900)

2.4 热升级流程

![image.png](https://img-blog.csdnimg.cn/img_convert/bfa2d518a1a0c01c52530a5a8cec6b41.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=393&id=u5e6dc846&margin=[object Object]&name=image.png&originHeight=786&originWidth=1450&originalType=binary&ratio=1&rotation=0&showTitle=false&size=703236&status=done&style=none&taskId=u2436f5c7-22ff-44a9-b7c7-dff30a2e78d&title=&width=725)
![image.png](https://img-blog.csdnimg.cn/img_convert/43b1b71f4c35dc3d73724868c7e7b5ec.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=399&id=u06a3e15a&margin=[object Object]&name=image.png&originHeight=798&originWidth=1512&originalType=binary&ratio=1&rotation=0&showTitle=false&size=442930&status=done&style=none&taskId=u6576c8e6-74a3-4490-b5e9-24029966232&title=&width=756)

2.5 优化的关闭worker进程

优化的关闭只针对Http请求,对于websocket,TCP,UDP,Nginx无法得知worker是否在处理请求。

![image.png](https://img-blog.csdnimg.cn/img_convert/066e2fb4943863f6fa2bf51a410b9b7c.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u267339ed&margin=[object Object]&name=image.png&originHeight=792&originWidth=1426&originalType=binary&ratio=1&rotation=0&showTitle=false&size=504452&status=done&style=none&taskId=ubc2ac892-79a0-4e7d-ba7b-80c350f4624&title=&width=713)

2.6 网络收发和Nginx事件间的对应关系

Nginx是一个事件驱动的框架,事件是指网络事件,一个网络连接对应两个事件(读事件和写事件)

2.6.1 网络传输

![image.png](https://img-blog.csdnimg.cn/img_convert/9280954645b4f9265cbc81fbcac07fcb.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=674&id=u0565fcd0&margin=[object Object]&name=image.png&originHeight=1348&originWidth=2472&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1078525&status=done&style=none&taskId=u633d97ba-b09e-4edb-94b3-01ebc78ba71&title=&width=1236)

2.6.2 TCP流和报文

![image.png](https://img-blog.csdnimg.cn/img_convert/d29b4aafc136d5d2757bb3ba373b6e59.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=672&id=u5ede5806&margin=[object Object]&name=image.png&originHeight=1344&originWidth=2434&originalType=binary&ratio=1&rotation=0&showTitle=false&size=971254&status=done&style=none&taskId=u834386c2-d0e9-410e-85a1-edc29a53265&title=&width=1217)

![image.png](https://img-blog.csdnimg.cn/img_convert/08c76618ae8f5ccfd5ec683262cfd5dd.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=657&id=ue85904c3&margin=[object Object]&name=image.png&originHeight=1314&originWidth=2394&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1049871&status=done&style=none&taskId=uaea3a798-39f8-4825-9bcb-400c221f76b&title=&width=1197)

2.7 Nginx事件循环

![image.png](https://img-blog.csdnimg.cn/img_convert/1d96a2afb5dd2a97bdcc69b15f9b7d94.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=659&id=u1e9fce32&margin=[object Object]&name=image.png&originHeight=1318&originWidth=2266&originalType=binary&ratio=1&rotation=0&showTitle=false&size=570999&status=done&style=none&taskId=u6cc79520-a8d8-41a7-9be6-5c635283aa3&title=&width=1133)

2.7.1 epool优劣已经原理

上图nginx等待服务器内核的事件队列使用epool来处理的。

![image.png](https://img-blog.csdnimg.cn/img_convert/9474b53f85db98bf69f54525559ffae8.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=677&id=uf37f6e9b&margin=[object Object]&name=image.png&originHeight=1354&originWidth=2398&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1073766&status=done&style=none&taskId=udcf0d437-d241-47e1-b3bc-2995e6b7fb1&title=&width=1199)

2.8 Nginx的请求切换

![image.png](https://img-blog.csdnimg.cn/img_convert/0de6f4b958800851f83c494f6ac2ad96.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=673&id=u30e09ba8&margin=[object Object]&name=image.png&originHeight=1346&originWidth=2418&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1149441&status=done&style=none&taskId=u6a575f63-c9a8-4d8e-87d2-dc1be5c0ebc&title=&width=1209)

nginx是用户态直接切换的,除非操作系统分给worker的时间分片到期了,否则一直工作,所以将worker的优先级调为-19,可以使得操作系统给worker分配更多的时间分片,提高Nginx性能。

2.9 同步和异步、阻塞和非阻塞的区别

阻塞和非阻塞是线程在访问某个资源时,数据是否准备就绪的一种处理方式。

阻塞方法:操作系统或者底层C库提供的方法或者是一个系统调用,这个方法可能是我的进程进入sleep状态(当前条件不满足,操作系统把我的进程切换到另外一个进程)。
非阻塞方法:我们调用该方法永远不会在我们时间分片未用完时,切换到另外一个进程。

同步和异步是用户态的调用方式而言。

同步:调用方法时,需要等待返回结果。
异步:调用方法后,无需等待返回结果,被调用方法处理完成后后主动通知给调用方。(支付回调)

2.9.1 阻塞调用:

![image.png](https://img-blog.csdnimg.cn/img_convert/5ce9869660cf411fea86265e2e5259a0.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=635&id=mmbW1&margin=[object Object]&name=image.png&originHeight=1270&originWidth=2308&originalType=binary&ratio=1&rotation=0&showTitle=false&size=756496&status=done&style=none&taskId=ufef84591-1516-49f2-bdb2-77410e81f32&title=&width=1154)

2.9.2 非阻塞调用:

![image.png](https://img-blog.csdnimg.cn/img_convert/c4ac4d3b176088f38c291a011f86417c.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=668&id=ue53dda1d&margin=[object Object]&name=image.png&originHeight=1336&originWidth=2320&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1003491&status=done&style=none&taskId=uc340540a-9101-4d2d-b070-8579213e891&title=&width=1160)

2.9.3 非阻塞调用下的同步和异步:

![image.png](https://img-blog.csdnimg.cn/img_convert/9b0d811d24cdf1061d68c45fd0cdd533.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=670&id=u34e4073a&margin=[object Object]&name=image.png&originHeight=1340&originWidth=2498&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1394172&status=done&style=none&taskId=u5d50ab4e-b982-4007-8151-ab0a6cb8a63&title=&width=1249)
openResty使得我们可以通过写同步的的方法,实际上以异步的来执行。

2.10 Nginx模块

![image.png](https://img-blog.csdnimg.cn/img_convert/e28a283a8cdeee392c2e3164fe55f244.png#clientId=u4080493f-2439-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=682&id=u8e0d1bec&margin=[object Object]&name=image.png&originHeight=1364&originWidth=2400&originalType=binary&ratio=1&rotation=0&showTitle=false&size=951445&status=done&style=none&taskId=u1e94db26-886a-48c5-9d00-3bb89d8d66e&title=&width=1200)

2.10.1 Nginx模块分类

![image.png](https://img-blog.csdnimg.cn/img_convert/da7ede8968243725eef8515bce8704eb.png#clientId=ue2063783-0659-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=504&id=uceec0e31&margin=[object Object]&name=image.png&originHeight=1008&originWidth=2000&originalType=binary&ratio=1&rotation=0&showTitle=false&size=765616&status=done&style=none&taskId=u78964cdd-88b3-461b-bb13-9d9927ab610&title=&width=1000)

2.11 Nginx连接池


image.png
说明:
每一个连接对应2个事件(读事件和写事件),如上图是通过数组序号来配合使用的。消耗的内存如下:
一个connection(232)+2个event(96*2) = 424字节。设置的连接数越多,消耗的内存就越大。

image.png

2.12 Nginx内存池

image.png

2.12.1 connection_pool_size:
  • Default:connection_pool_size:256|512

内存池配置512字节,并不意味着只能分配512字节,当内存超过预分配内存大小时,是可以继续分配的。提前分配内存空间,减小分配的资源消耗。

2.12.2 request_pool_size:
  • Default:request_pool_size:4k

请求池大小,默认4K。

2.12.3 为什么请求内存池大于远远大于连接内存池?


因为连接需要存储的上下文信息很少,只需要帮助后面的请求读取最初一部分字节就行;对于请求而言,需要保存大量上下文信息,比如:url和header。其对性能的影响比较小,极端场景下,url特别长,可以修改配置,增大请求内存池预分配的空间大小;通常情况下,url和header都很小,可以考虑降低请求内存池的预分配空间大小,最大化Nginx的并发量。

内存池对减小内存碎片和第三方模块开发是很有意义的。

2.13 Nginx进程间通信方式

image.png

2.13.1 哪些官方模块使用了共享内存呢?

image.png

  • Nginx_http_lua_api是OpenResty的核心模块:

image.png

在如上代码中,同时使用了rbtree和链表:

lua_shared_dict dogs 10m;//使用红黑树来保存每一个key-value,每一个节点是它的key,节点值就是value。
//当内存大于10m时,使用lru方式淘汰,最先设置了key-value就会被淘汰,这就说明每个key-value连在了一起形成了一张链表。

2.13.2 Slab内存分配管理

如何把一整块内存切割成小块分配给每个红黑树节点使用的?Slab内存管理
image.png

Slab会把共享内存切割很多页面(4K),每个页面被切分为不同的slot(不同的slot分配内存空间不同128|256|512,乘2方式向上增长)。

Bestfit:比如30字节的内存,会被分配到32字节的slot。

2.13.3 查看slot使用状态

image.png

2.13.4 在OpenResty上使用tengine的slab_stat模块查看共享内存分配情况

编译安装(在编译安装OpenResty时,使用add-module把tengine的slab_stat模块安装进来):
image.png
案例:
image.png

2.14 Nginx数据容器

nginx的数据容器包括:数组、链表、队列、哈希表、红黑树、基数树

Nginx数组(nginx_array_T):

多块连续内存,每块连续内存中可以存放许多元素。

链表:

nginx_list_T

队列:

nginx_queue_T

哈希表

nginx_hash_elt_T

image.png

哈希表每个元素占用连续的内存。value是指针,指向用户数据,len长度,name就是hash的key。

image.png

Hash表应用于静态不变的内容。

Max size:控制了最大的hash表Bucket的个数,并不是实际最大hash表bucket的个数。

Bucket size:每个bucket的大小,向上对齐(cache line)。比如64位操作系统,操作系统每次读取64个字节,但bucket size配置60,这个时候实际是Nginx会设置为64,与操作系统对齐。,bucket size配置尽量不要超过64字节,以免占用内存过高。

红黑树

image.png

红黑树本身是一个二叉树,包含左节点和右节点。其次是一个查找二叉树,左节点比右节点小。可能会退化成一个链表,如右图。

  • 红黑树优点:

image.png

  • 使用红黑树的模块:

image.png

2.15 动态模块

image.png

使用案例:

(1)查看哪些模块支持动态模块:./configure —help | more
image.png
(2)把一个模块动态编译到nginx
image.png
(3)打开动态模块配置

load_module module/nginx_http_image_filter_module.so
image_filter resize 15 10;

2.16 配置指令

image.png

2.16.1 什么是指令的context?

该条配置指令能处于的配置块。

image.png

上图表明:log_format能在http模块上配置;access_log能在http,server…等模块配置。

image.png

一个配置存在多个配置块是是可以合并的。值指令可以合并;动作类指令不可以合并。判断依据:看该条配置的生效阶段。

值指令向上覆盖:

image.png

http模块指令合并规则:

image.png

三、详解HTTP模块

3.1 Listen指令

image.png

3.2 接收请求的事件模块

image.png
image.png

3.3 正则表达式:

image.png

3.4 如何找到处理请求的server指令块

3.4.1 server_name
  • 指令说明:

image.png

  • server_name多域名:

例如:

server{
		server_name [aa.com](http://aa.com) [bb.com](http://bb.com); #其中aa.com是主域名
		server_name_in_redirect off;
		redirect 302 /redirect;
}

如上配置:如果访问bb.com,会直接跳转到bb.com/redirect

如果配置:

server{
		server_name [aa.com](http://aa.com) [bb.com](http://bb.com); #其中aa.com是主域名
		server_name_in_redirect on;
		redirect 302 /redirect;
}

如上配置:如果访问bb.com,会302到aa.com/redirect

image.png

  • server_name匹配顺序:

image.png

3.5 HTTP请求11个阶段

image.png

HTTP请求11个阶段的执行顺序:
image.png
上图说明:

(1)每一个阶段会有多个模块得到执行。

(2)limit_req和limit_conn都在preaccess阶段得到执行,但是如果limit_req阻止了本次请求,就会直接返回,limit_conn就得不到执行。

(3)access阶段的access执行通过后,后续auth_basic和auth_request两个阶段不会执行,直接跳到precontent阶段,同理content阶段也是如此。

3.5.1 postread阶段

(1)realip模块

把realip模块编译进Nginx模块?

image.png

三个指令:

image.png

set_real_ip_from:设置可信赖的ip(如本机IP或者机器某台机器IP),找到用户真实ip

real_ip_header:ip值从哪个参数中取(X-Real_Ip |X-Forwarded-For)

real_ip_recursive:环回地址,取 X-Forwarded-For最后一个地址如果和客户端地址一样就pass掉,取上一个地址。

(2)如何拿到真实的用户IP地址?
image.png
说明:当网络请求过程中,存在很多反向代理服务器时,Nginx会把用户真实的ip写在X-Real_IP中,而每经过一层反向代理,会吧上一层IP追加在X-Forwarded-For中。

拿到真实用户IP后如何使用?
image.png

3.5.2 rewrite阶段

(1)rewrite模块return指令

image.png

error_page:收到某个特定的返回码时,重定向某个url或者给用户返回特定内容。

image.png

return示例:

image.png

server与location块下的return指令关系?

server块的return先于location块的return执行。

return与error_page指令的关系?

访问不存在的资源,执行error_page指令;如果执行了return指令,error_page得不到执行。

(2) rewrite指令

image.png

案例:

image.png

问题1:rewrite指令优先级高于return

问题2:依次返回“test3”、“test3”、”third!”

问题3:不携带break,就往下执行到return 200 ‘second’模块

image.png

问题:依次返回301、302、302、301

rewrite日志记录:rewrite_log:on就可以开启了

(3)if指令
image.pngimage.pngimage.png

3.5.3 find_config阶段

(1)location指令

image.png

匹配规则:

image.pngimage.png

匹配结果:

/Test1:5,6;

/Test1/:1,3,5;

/Test1/Test2:2,4,5

/Test1/Test2/:4,5

/test1/Test2:2

匹配顺序

image.png

同上问题,返回什么?

/Test1:exact match!

/Test1/:stop regular expressions match!

/Test1/Test2:lonest regular expressions match!

/Test1/Test2/:lonest regular expressions match!

/test1/Test2:lonest regular expressions match!

3.5.4 preaccess阶段

(1)limit_conn指令

image.png

key一般为用户的IP地址(remote_addr变量)。
image.pngimage.png

$binary_remote_addr 关键字,这里是限制同一客户端ip地址;

限制连接数:

要限制连接,必须先有一个容器对连接进行计数,在http段加入如下代码:

“zone=” 给它一个名字,可以随便叫,这个名字要跟下面的 limit_conn 一致

$binary_remote_addr = 用二进制来储存客户端的地址,1m 可以储存 32000 个并发会话

上图配置说明:现在某个ip的并发数为1,超过1就返回500,记warn级别日志,网站返回速率为50字节/s

image.png

(1)limit_req指令

image.png

image.png
image.png
leaky bucket算法:
image.png

limit_req_zone:$binary_remote_addr zone=one:10m rate=2r/m;
location / {
	limit_req zone=one burst=3 nodely;
}

第一段配置参数:

  • $binary_remote_addr :表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地
  • zone=one:10m:表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息
  • rate=2r/s:表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,即每秒只处理一个请求,还可以有比如30r/m的,即限制每2秒访问一次,即每2秒才处理一个请求。

第二段配置参数:

  • zone=one :设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应
  • burst=5:重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报503的错误然后返回。
  • nodelay:
  • 如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过**(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况**。(这里的rate的单位是:r/s)
  • 如果没有设置,则所有请求会依次等待排队

说明:limit_conn模块优先级大于limit_req。

3.5.5 access阶段
  • access模块(对用户ip校验)

判断请求是否可以继续向下访问。
image.pngimage.png

  • auth_basic模块(对用户用户名+密码验证)

image.png

示例:

image.png
image.png

  • auth_request模块(用于做统一用户鉴权系统)

image.png

  • satisfy指令

image.png

satisfy all:access的3和指令均放行这个请求,这个请求才向下执行,任何一个拒绝,400或500返回。

   anny:access的3和指令有一个指令放行这个请求,这个请求就向下执行。

image.png

  1. 不会。
  2. 有影响。
  3. 可以
  4. 可以
  5. 没有机会输入

3.5.6 precontent阶段
  • try_file指令

image.png

  • mirror模块(做流量拷贝)

image.pngimage.png

3.5.7 content阶段
  • static模块

(1)root和alias指令
image.pngimage.png

/root :404

/root/1.txt :—>html/first/root/1.txt 也是404

/alias:—>html/index.html 200

/alias/1.txt:—>html/first/1.txt 200

(2)3个nginx变量
image.pngimage.pngimage.png
(3)static模块对url不以斜杠结尾却访问目录的的做法
image.pngimage.png

  • index模块和autoindex模块

image.pngimage.pngimage.png

  • concat模块(合并小文件,提升网络性能)

image.pngimage.png

3.5.8 log阶段

image.pngimage.pngimage.pngimage.png

3.5.9 HTTP过滤模块

image.pngimage.png

  • sub模块

image.pngimage.png

示例:

image.png

  • addition模块

image.pngimage.png

3.6 HTTP的变量

image.png

3.6.1 HTTP请求相关变量

image.pngimage.pngimage.pngimage.pngimage.png

3.6.2 TCP连接相关的变量

image.png
image.png

3.6.3 请求中产生的变量

image.pngimage.png

3.6.4 方式HTTP响应时相关的变量

image.png

3.6.5 系统变量

image.png

3.7 referer模块

image.pngimage.png

valid_referers指令

image.pngimage.png

结果:403,valid,valid,valid,403,valid,403,valid

3.8 map模块

image.pngimage.pngimage.pngimage.png

3.9 split_clients模块

image.pngimage.png

3.10 geo模块

image.pngimage.pngimage.png

3.11 geoip模块

image.pngimage.pngimage.pngimage.png

3.12 keepalive

image.pngimage.png


四、反向代理和负载均衡

4.1 基本介绍

4.1.1 负载均衡

image.png

一个服务的扩展方向:

A:水平扩展,加机器;

B:纵向扩展:把业务复杂的服务,拆分为业务小的服务,上层nginx通过location把请求分发到不同的服务中去;

C:Z轴扩展:基于用户的信息进行扩展。例如根据请求ip或者其他信息,把请求分发到特定的服务中去;

4.1.2 反向代理

image.png

4.1.3 缓存

image.png

时间缓存:Nginx从下游服务拿到信息后,一边发给客户端,一边把返回内容缓存在nginx中;

空间缓存:上游服务请求nginx,nginx可以预请求下游服务,把数据缓存到nginx中;

4.2 负载均衡策略

4.2.1 upstream与server指令

image.pngimage.png

  • 加权Round-Robin负载均衡算法:

image.png

  • 对下游服务使用keepalive长链接:

image.png

  • upstream_keepalive指令:

image.png

keepalive:nginx和下游服务最多保持多少个空闲的http连接

keepalive_request:一个tcp最多跑多少个请求

keepalive_timeout:一个tcp连接空闲多少秒后关闭

  • resolver指令

image.png

官方解释下就是:反向代理的场景,upstream后端用域名时,配置resolver以便于nginx能够解析该域名。

当proxy_pass 后面接变量时,而且设置了resolver,会把变量的负载值通过resolver来解析,其他情况通过本地dns服务,etc或host 来解释域名。

https://www.jianshu.com/p/5caa48664da5

4.3 负载均衡哈希算法

4.3.1 upstream_ip_hash模块

image.png

4.3.2 upstream_hash模块

image.png

4.3.3 演示
upstream iphashtest { 
	ip_hash;
	hash user_$arg_username;#使用username作为hash算法的关键字
	server 127.0.0.1:8011;
	server 127.0.0.1:8012;
}

4.4 一致性hash算法

使用hash算法,下游服务器异常会导致大量请求的路由策略失效。一致性hash算法能有效解决该问题。

image.pngimage.png

把0-232围成一个环,4个服务均有的分布在环上,0-230请求第一个服务,以此类推;

扩容后:

image.png

扩容后只会改变node2—node4前半段的hash点。

4.4.1 使用方法

image.png

4.5 最小连接数算法

4.5.1 upstream_least_conn模块

image.png

4.6 怎么跨worker生效:upstream_zone模块

image.png

如上所有算法均可以使用upstream_zone来使得所有worker生效。

4.7 upstream模块间的顺序

image.png

4.8 http upstream提供的变量

image.pngimage.png

4.9 反向代理

4.9.1 http反向代理proxy处理请求的流程

image.png

4.9.2 proxy模块

image.pngimage.png

  • 案例

image.png

http://proxyups/addurl会被换为:http://proxyups/a

4.9.3 修改请求下游服务的的请求

image.pngimage.pngimage.png

4.10 接收用户请求body

image.pngimage.png

client_body_buffer_size:Nginx分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储。如果请求的值大于client_body_buffer_size小于client_max_body_size,就会将数据先放到client_body_buffer_size的内存中,再一遍一遍地写到临时文件中。

client_body_in_single_buffer:客户端请求数据的body一律存储到内存buffer中。当然,如果HTTP包体的大小超过了下面client_body_buffer_size设置的值,包体还是会写入到磁盘文件中。

image.png

client_max_body_size 默认 1M,表示 客户端请求服务器最大允许大小,在“Content-Length”请求头中指定。如果请求的正文数据大于client_max_body_size,HTTP协议会报错 413 Request Entity Too Large。就是说如果请求的正文大于client_max_body_size,一定是失败的。如果需要上传大文件,一定要修改该值。

image.pngimage.png

2次读取body时间超过60s后,返回408.

4.11 连接下游服务器

image.png
当与下游服务建立连接超时时,再换一台服务器重新连接。

4.11.1 TCP keepalive

关闭无用的连接,减少资源浪费。

image.png

使用操作系统设置的默认keepalive相关配置来控制tcp的keepalive来降低资源使用。

4.11.2 HTTP keepalive

image.png

4.11.3 修改TCP连接中的local address

image.png

proxy_bind隶属于proxy_module,为向后端建立连接时的local ip,在nginx源码中只支持bind一个ip进行回源,若想使用多个ip进行回源时,可以修改源码支持bind ip数组。在实际应用中我就是这样做的。bind ip数据轮询选择ip进行回源与upstream建立连接,以解决单ip回源连接数限制问题。

proxy_bind:它的用法主要有两类用途,第一类用途就是当我们nginx上有多个ip地址时,可能有多个路由的策略是不同的,比如内网或者外网等,这个时候不要使用系统默认给我们选择的ip地址,而是主动使用一个ip地址。这个时候用proxy_bind。第二种场景,很可能为了传递一个ip地址,就是透传ip地址的策略,比如在stream反向代理中会很常用,在之后还会详述。这里先说下proxy_bind用法。

proxy_bind $remote_addr 也就是客户端的地址绑定到这里。绑定变量的时候呢,如果地址不是本地的地址,linux必须要加transparent。非linux操作系统呢需要保证worker进程有root 权限的,才能人为的修改socket的local address。

image.pngimage.png

4.12 接收下游的响应

4.12.1 接收下游服务的响应头部

image.png

proxy_buffer_size:限定了接收自上游的http response中header的最大值。所以当上游的server发送了http响应,如果有set cookie这种特别长的header可能就会导致整个全部的response header超出了这个值。超出完之后这个请求就不能够被nginx正确的处理了。我们的error.log中会看到upstream sent too big header
就是这样的一个原因。

4.12.2 接收下游服务的响应body

image.png

proxy_buffering:来控制我们是不是先接收完整的包体,接收完了才开始转发。或者说不接收完,而是每接收一部分就同步的向客户端发送我收到的那部分响应。这两种方式各有各的好处。通常情况下默认开启(on)。因为我们认为上游服务和我们nginx走的是内网,网速更快。如果我们边发边接收上游边往客户端发。因为客户端跟nginx之间的网速可能很慢。所以就会导致,对于比较大的body 的时候,nginx长时间与上游建立连接。而上游比如说tomcat、Django等它们的并发能力是很弱的。当然如果我们用了proxy_buffering off 它的优点是能让客户端及时接收到响应,特别是一些大包体的情况下。客户端不用再等待。

在我们接收上游发来的HTTP包体,即使我们开启了proxy_buffering on也并不一定向磁盘中写入包体,因为如果包体非常的小,在内存中就可以放入的话,就没有必要写到磁盘中,因为磁盘io总是比较慢的。所以这个时候就有了proxy_buffers指令。也就是包体大小没有超过这个设定值就不用写入磁盘。否则的话就要写入磁盘了。

image.png

proxy_buffering ,默认开启,希望尽快释放上游服务器的连接,当然proxy_buffering 还有一个nginx特定的header。这个header(X-Accel-Buffering头部)只有nginx才会认。当上游的tomcat 如果在response中加入X-Accel-Buffering头部,如果配置为yes,就会强制要求nginx先接收完上游的http body 再向client发送。也就是它会替换指定的内容。

当我们向磁盘中写入包体的时候还有三个指令,proxy_max_temp_file_size、proxy_temp_file_write_size、proxy_temp_path。

proxy_max_temp_file_size:限制写入磁盘中这个文件的最大值。如果上游服务中返回了非常大的文件超出了临时文件大小也会出错的。默认是1G。

proxy_temp_file_write_size:每一次向磁盘文件中写入的字节数。

proxy_temp_path:设定了存放临时文件的目录在哪里,以及目录level层级。

4.12.3 及时转发body

image.png

proxy_busy_buffers_size。虽然被缓存所有的响应,我们希望更及时的向客户端发送部分响应。比如我们收到1G文件。当我们接收到前8k或前16k(proxy_busy_buffers_size 8k|16k)的时候,就先向客户端转发接收到的这一部分响应的话就可以使用proxy_busy_buffers_size 。

4.12.4 接收下游服务时网络速度相关指令

image.png

proxy_read_timeout:两次读取操作之间最多60秒的超时。两次读取是一个TCP层的一个概念。

proxy_limit_reate:限速,和客户端limit_rate 有些类似,但是它限制的是读取上游的响应,而不是发送给上游服务的网速。设置为0表示不限制读取上游响应的速度。

4.12.5 上游body的持久化

image.png
proxy_store_access:配置指定目录权限。

proxy_store:把临时文件改名到root对应的目录下,默认不开启,如果是string,可再次指定,使用变量的方式,指定这个文件存放的位置。

4.13 处理下游响应头部

4.13.1 返回响应-加工响应内容

我们接收到了上游发来的http header跟http body,其实对上游发来的http header是有很多控制nginx行为的这样一些头部的。我们在反向代理这一层也可以去修改上游发来的header中的内容,以及它们所产生的效用。接下来看看这两种行为是怎么发生的。

第三部分讲的http 过滤模块。当我们生成的响应向客户端发送的时候。这个内容必须经历过滤模块的处理。对于nginx作为反向代理的时候也是同样的。nginx下游服务返回的一些header会被那些过滤模块处理(图中)。
image.png
比如ngx_http_modified_filter_module,它根据上游服务返回的cache control等等这些header,去修改到底是发送200还是304响应码给客户端。所以上游一些header的内容会改变作为反向代理的nginx的行为。

  • proxy_ignore_header指令

proxy_ignore_header可以禁止某些响应头改变nginx行为。

image.png

  • proxy_hide_header指令

nginx提供了一个指令proxy_ignore_header,禁用上游中一些header 的功能。当然不是所有的header 都具有功能,这个指令只针对于具有特殊功能的header才发生作用。

image.png
说明:
(1)X-Pad:是apache 使用的header,目前已经很少用了。
(2)X-Aceel-:只有nginx才认。
(3)如果上述这四类header你想发送给客户端,就使用proxy_pass_header。

  • 修改返回的set-cookie头部

image.png
修改下游服务器response header中的头部set-cookie中的内容。proxy_cookie_domain修改下游服务器返回的cookie中的域名;

  • 修改返回的Location头部

proxy_dedirect:对于我们上游服务发送的响应中有一个location,location后面的url可以做一次替换。

image.png

4.13.2 处理返回响应演示

(1)反向代理服务配置:
image.png
(2)下游服务配置:
image.png
直接访问localhost:8012如下所示有个aaa的header:
image.png
访问反向代理服务时也有个aaa的header:
image.png
(3)禁用反向代理服务的aaa:

proxy_hide_header aaa;

再次访问反向代理服务,发现没有了aaa的header。
(4)打开proxy_pass_header,可以把下游服务的nginx版本返回给客户端:

proxy_pass_header server

再次访问反向代理服务,发现server是nginx 1.15.6而非反向代理的openresty。

总结:以上几节课包括从proxy_pass指令来指定由反向代理来指定请求到生成向上游发送请求的内容,以及接收客户端发来的http body并与上游服务建立连接并上游服务的响应内容以及处理响应头部,以上几个环节,就是nginx作为反向代理处理客户端与上游服务之间的所有流程。

4.13.3 下游返回失败时处理方法

我们讨论了nginx作为反向代理时,从客户端接收http body,到完整的接收下游的响应并转发响应的流程。其中在nginx与下游服务建立连接时。提到过proxy_next_upstream指令,这个指令可以在第一台的错误的响应后重新选择另一台下游服务器处理请求返回给客户端这样的功能。

image.png
能够生效的前提是没有向客户端发送一个字节。只要向客户端已经发送了一个字节了,说明下游的服务已经生效了,就不能选用一个新的下游服务了。它一定是在接收到并开始转发一个字节之前nginx判定为错误,这个功能才能生效。proxy_next_upstream后面可以跟很多不同的参数(error、timeout那些)。
配置:

  • error:

nginx与上游建立连接读取响应,发送请求等等这些过程中,只要出现错误等等。error都可以满足这样的场景。这种错误主要是网络错误。比如TCP层、IP层的错误。

  • timeout:

超时有connection timeout 、read timeout、 write timeout,这个timeout可以命中这些场景。当出现这种场景的时候将执行重选另一个下游服务。

  • invalid_header:

则是我们收到的下游服务http header,它是不合法的。

  • http_:

http_可以跟一个明确的响应code。上游返回一个403或500,其实它既不是网络错误,也不是超时,也不是invalid_header。但是我们就是可以针对这样的错误从新选择一个新的upstream上游去处理。

  • non_idempotent:

根据RFC 7231文档中规定了post、lock等method的请求。在下游服务不能使用next_upstream上游服务的,去重选一个新的服务时候,当我们配置了这个non_idempotent就可以启用proxy_next_upstream功能。

  • off:

关闭 proxy_next_upstream功能。

两个相关指令:

proxy_next_upstream_timeout 超时时间;proxy_next_upstream_tries 重试次数

image.png

4.13.4 下游返回失败时处理演示

反向代理配置:
image.png
下游服务:
image.png
(1)关闭proxy_next_upstream,访问反向代理服务就会在8011和8012端口服务上轮询
(2)打开proxy_next_upstream,且关闭下游8013服务,访问反向代理服务,一直是8011服务做响应。
(3)修改反向代理服务配置:

location /httperr {
	proxy_next_upstream http_500;//下游服务返回500时生效
	proxy_pass http://nextups;
}

访问反向代理服务,一直是8011服务做响应。

4.13.5 使用error_page拦截下游失败响应

当下游响应码大于等于 300时,就应该使用error_page来处理请求返回给客户端。

image.png
proxy_intercept_errors 默认off。这个时候上游返回怎样的响应,客户端就会原封不动的拿到这个响应。比如上游返回来一个404,我们的error_page 配置的404是不会生效的。只有把proxy_intercept_errors 设置为on的时候error_page 就会生效了。

  • 演示:

代理服务配置:
image.png
proxy_intercept_errors 为on时,配置了error_page,发现500错误码的时候返回test1.txt。

4.14 对下游使用SSL连接

image.png
Nginx提供以上4种关于证书的指令。

  • 对上游使用证书

image.png

  • 验证上游证书

image.png

  • 对下游使用证书

image.png

  • 验证下游证书

image.png

4.14.1 SSL模块提供的变量

image.png
image.png

4.14.2 创建证书命令示例

image.png

4.15 浏览器缓存

在互联网中使用缓存是最有效的提升访问速度的方法。在web服务器场景中不仅要考虑nginx作为缓存服务时的使用方法,还要考虑浏览器缓存生效的场景。浏览器的缓存是否生效可以通过nginx的指令去控制。而浏览器的缓存对用户的体验提升也是最大的。

4.15.1 浏览器缓存和Nginx缓存的比较

image.png

4.15.2 浏览器缓存

image.png
  • Etag头部

image.png
image.png

  • If-None-Match

image.png

  • If-Modified-Since

image.png
Last-Modified:比较简单,也就是我们访问的资源,比如我们使用了一个js文件,这个js文件的在服务器上上次被修改时间。

4.16 Nginx决策浏览器过期缓存是否有效

4.16.1 Expires指令

image.png
演示:
image.png

4.16.2 not_modified过滤模块

image.png

not_modified过滤模块处理过程:
image.png

  • if_modified_since

image.png

  • If-Match

image.png

  • If-Unmodified-Match

image.png

4.17 Nginx缓存

这节课介绍在nginx之上配置上游服务器返回的响应的缓存。会涉及到一些指令的值,它是与第二部分课程中介绍过nginx进程结构的时候谈到的Cache Manager、Cache Loader 这两个进程。
image.png

4.17.1 nginx的cache使用

内容是放到磁盘上的,但是它的元素信息为了加快访问是放到内存中的。所以首先在proxy_cache_path指令中定义好共享内存。因为我们有多个worker进程,所以这些元信息一定是在共享内存中的。第二个定义在磁盘中哪个位置去存放缓存文件。proxy_cache_path定义好以后,其中keys_zone的name就是共享内存的名字,size就是共享内存的大小。共享内存的名字就是给proxy_cache使用的。也就是在proxy_cache_path定义了一批缓存文件存放的位置和共享内存的名称。也许有很多location,它们定义了各自独立的缓存的key或缓存策略。但是它们都可以使用同一个proxy_cache_path指定的keys_zone。所以proxy_cache在location中可以通过这个zone指定使用哪一个proxy_cache中的设置。

4.17.2 proxy_cache_path

image.pngimage.png
use_temp_path:使用这个临时文件目录,最后改名都会放到path中。但为什么会有这个设置呢?是因为,很可能nginx所在的机器中有多个文件系统,甚至有些网络文件系统。如果我们开始的use_temp_path 目录是在一个磁盘上,而path是在另外一个磁盘上。跨磁盘复制是在cp文件。如果在一个磁盘上,那最后的改名也只是改名而已。
image.png

4.17.3 proxy_cache_valid: 缓存什么样的响应

image.png

4.17.4 proxy_no_cache: 什么样的响应不缓存

image.png

proxy_cache_convert_head:默认为on,会把header方法转换成get方法。

4.17.5 upstream_cache_status变量

image.png
EXPIRED:表示nginx cache_vaild设置的时间还没有过期,用户的请求获取到缓存,但是上游服务器指定的缓存时间也许是小于cache_vaild设置的时间,根据上游的说法来说缓存已经过期了,但nginx配置的时候,这个缓存仍然在使用。所以和这个时候是EXPIRED,缓存已经过期。

4.18 对客户端请求的缓存处理

image.png

补充说明:

proxy_cache_methods GET | POST|HEAD...//对哪些请求方法使用缓存

4.19 接收下游响应缓存处理

补充说明:

  • X-Accel-Expires头部:

从下游服务定义缓存多少时间(0不缓存;@前缀表示缓存当天的某个时间)

  • Vary头部:

image.png

  • Set-Cookie:

image.png

4.19.1 缓存流程

image.png

4.19.2 使用分片提示缓存效率
  • slice模块

image.png

  • slice模块运行流程

image.png

4.19.3 open_flie_cache提示系统性能

image.png

  • 缓存元信息

image.png

  • 其他open_flie_cache指令

image.png

  • 案例

下游服务配置:
image.png
第一次访问:
image.png
第二次访问:
image.png

4.20 Nginx缓存失效时如何减轻下游服务压力

nginx重启或者意外退出时,所以缓存就会失效,这个时候接收下游服务全部穿透Nginx打到下游服务,导致下游服务压力剧增。

4.20.1 合并回源请求

image.png

4.20.1 减少回源请求

image.png
proxy_cache_use_stale:第一个请求来了后打到下游服务,后续的请求给客户端响应旧的缓存内容,直至第一个请求的下游响应被缓存。
image.png
对应缓存有问题的响应:
image.png
例子:
image.png
proxy_cache_background_update:第一个请求来了把旧的缓存响应给客户端,同时向下游服务发送一个子请求,后续的请求给客户端响应旧的缓存内容。直至第一个请求的子请求收到下游服务响应内容后,更新缓存,后续的请求均可使用到新缓存。

4.21 及时清除缓存

image.png

4.22 http反向代理和uwcgi、fastcgi、scgi反向代理的指令对照

4.22.1 构造请求内容的指令对照

image.png

4.22.2 建立连接并发送请求的指令对照

image.png

4.22.3 接收下游响应的指令对照

image.png

4.22.4 转发响应的指令对照

image.png

4.22.5 SSL的指令对照

image.png

4.22.6 缓存的指令对照

image.pngimage.png

4.22.7 独有配置

image.png

4.23 memcached反向代理用法

image.png

4.23.1 memcached指令

image.png
演示:
代理服务器配置:
image.png

[root]:#curl xxx.com/get?key=hello
[root]:#world//取出了hello的值

补充说明:
memcached_gzip_flag:如果设置的key使用了gzip压缩,取出的时候需要这个指令来标识。

4.24 webSocket反向代理

  • 功能

由nginx_http_proxy_module模块实现

  • 配置

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
image.png

websocket协议帧

image.pngimage.png

websocket协议和扩展

image.png

测试

image.png
image.png

4.25 HTTP2.0

4.25.1 http2.0特性

image.png

4.25.2 http2.0核心概念

image.png

  • 协议分层:

image.png

  • 多路复用

image.png

  • 传输无序,接收时组装

image.png

  • 数据流优先级

image.png

  • 标头压缩

image.png

  • Frame格式

image.png

  • 服务器PUSH

image.png

4.25.3 搭建http2.0服务并推送资源
  1. 使用模块ngx_http_v2_module

image.png

  1. 推送资源

image.png

  1. 测试

image.png
服务器配置:

设置了http2_push和http3_push_preload

image.png
请求:nghttp2 -ns https://localhost:4430/
image.png
请求:nghttp2 -ns https://localhost:4430/test/test.html
image.png

  1. 其他指令
  • 最大并行推送数

image.png

  • 超时控制

image.png

  • 并发请求控制

image.png

  • 连接最大请求数

image.png

  • 缓存区大小设置

image.png

4.26 grpc反向代理

协议:grpc协议(https://grpc.io)
模块:ngx_http_grpc_module,默认开启,可以通过without–ngx_http_grpc_module禁用
依赖:ngx_http_v2_module模块

2.26.1 grpc代理和http反向代理指令对照

image.png
image.png

4.27 传输层stream四层反向代理的七个阶段

  • 七个阶段

image.png

  • stream模块的ssl阶段

image.png

  • content阶段return模块

image.png

4.27.1 常用变量

image.png
image.png
image.png

  • 系统变量

image.png

  • 演示

服务器配置:
image.png
连接:
telnet localhost:10004,返回如下:
image.png

4.27.2 POST_ACCEPT阶段realip模块

proxy_protocol协议

image.png Nginx读取proxy_protocol协议超时控制:
image.png

stream处理proxy_protocol流程

image.png

post_accept阶段:realip模块

image.png

演示

服务器配置:
image.png
连接:
image.png

4.27.3 PREACCESS阶段limit_conn模块限制并发

image.png

limit_conn模块指令

image.png

4.27.4 ACCESS阶段access模块限制ip

image.png

access模块指令

image.png

4.27.5 LOG阶段stream_log模块记录日志

image.png

4.27.6 stream四层反向代理处理SSL上游客户端请求

stream模块TSL/SSL应用场景

image.png

stream中的ssl

image.png

对比stream模块的ssl和http模块的ssl配置

image.pngimage.pngimage.png

stream中的ssl模块提供的变量

image.png image.png

stream ssl模块实战

image.png

反向代理配置:
image.png
下游服务配置:
image.png
收到上游带ssl的请求,剥离调ssl证书,向下游服务发送请求。

stream_preread取出ssl关键信息

image.png
image.png
实战:
image.png
反向代理层根据域名代理到不同的下游服务。

4.27.7 stream proxy四层反向代理的用法

image.png

proxy模块对上下游的的限速指令

image.png

反向代理相关指令

image.pngimage.png

4.28 UDP反向代理

基本流程:
image.png
简要说明:
image.png
实战:
image.png

4.29 透传IP地址的3种解决方案

方案一:protocol协议
方案二:修改IP报文
image.png
image.png
B–>A:
image.png

image.png

image.png

五、Nginx的系统层性能优化

优化方法论:
image.png

5.1 内存效率

5.1.1 用tcmalloc优化内存分配

tcmalloc是什么?

image.png

使用方法?

image.png

5.2 CPU效率

5.2.1 如何增大Nginx使用CPU的有效时长?

image.png

worker进程数等于cpu核数
worker_process number | auto #一般设置为cpu核数

为何一个CPU能同时运行多个进程?
image.png

确保进程在运行态

image.png

减少进程间切换

image.png

延迟处理新连接

image.png

如何查看上下文切换次数?
image.png
什么决定CPU时间片的大小?
image.png
O1调度算法(CFS)
image.png

设置worker进程的静态优先级

image.png

5.2.2 多核间的负载均衡

image.png
使用linux内核3.9以上,打开reuseport,提高性能。

多队列网卡对多核CPU的优化(RSS、RPS、RFS)

image.png

绑定worker到指定CPU,提升CPU的缓存利用率

image.png
worker_cpu_affinity:
image.png

NUMA架构,提升CPU访问内存的效率

image.png

5.3 网络效率

5.3.1 控制TCP三次握手参数

image.png

SYN_SENT状态

image.png

主动建立连接时应用层超时时间

image.png

SYN_RECVD状态

image.png

Linux服务器处理三次握手

image.png

5.3.2 建立TCP连接的优化

如何应对SYN攻击

image.png

设置tcp_syncookies

image.png

设置句柄数上线

image.png

设置worker进程最大连接数量

image.png

设置两个队列的长度

image.png

开启TCP Fast Open

image.png
说明:正常TCP三次握手需要等待server返回syn+ack后,发送ack+http请求,fast open tcp是第一次建立连接后,client保存cookie,第二次直接带上cookie请求sever,减少前面2次握手。
image.png

5.3.3 传输数据阶段滑动窗口和读写缓冲区

滑动窗口

image.png
通告窗口?
收到对方的syn后,在回复ack时需要告诉请求方我还有多大的空间接收你的内容,这就是通告窗口。
image.png

发送TCP消息

image.png

TCP接收消息

image.png

TCP接收消息发生CS(进程间切换)

image.png

TCP消息接收时新报文到达

image.png

Nginx的超时指令和滑动窗口

image.png

TCP传输时的丢包重试

image.png

5.3.4 优化缓冲区和传输效率

TCP缓冲区

image.png

TCP调整接收窗口和应用缓存

image.png
BDP=带宽*时延,吞吐量=窗口/时延
image.png

禁用Nagle算法?

image.png

Nginx可以避免发送小报文

image.png

启用CORK算法

image.png

5.3.5 慢启动和拥塞窗口

滑动窗口:发送方主动限制流量
滑动窗口:接收方限制限制流量
实际流量:滑动窗口和滑动窗口的最小值

拥塞窗口

image.png

RTT和RTO

image.png

5.3.6 TCP协议的keepalive功能

应用场景

检查实际断连的连接
用于维持和客户端的防火墙有活跃的网络包

设置

image.png

5.3.7 减少关闭连接时的time_wait端口数量

image.png

服务器被动关闭连接端的状态

image.png

服务器主动关闭连接端的状态

image.png

优化time_wait

time_wait状态过短或者不存在会怎么样?
image.png

tcp_tw_reuse

image.png image.png

5.3.8 lingering_close延迟关闭TCP连接

lingering_close延迟的意义?

image.png

lingering配置指令

image.png

以RTS代替正常的四次握手关闭连接

image.png

5.3.9 应用层协议优化

TLS/SSL优化握手性能

image.png

TLS/SSL中的会话票证tickets

image.png

HTTP长链接

image.png

gzip压缩模块

image.png
压缩哪些请求的响应?
image.png
是否压缩下游的响应?
image.png
其他压缩参数:
image.png

升级更高效的http2.0协议

image.png

5.4 磁盘IO效率

image.png

5.4.1 大致优化方向

减少磁盘IO

image.png

直接IO绕开磁盘高速缓存

image.png
直接IO适用于大文件:
image.png

异步IO

image.png
image.png

异步读IO线程池

image.png
做静态资源服务读取文件时使用异步读IO线程池:
image.png

异步IO缓存

image.png

5.4.2 减少磁盘读写次数

empty_gif模块

image.png

access日志的压缩

image.png

error.log日志输出到内存

image.png

syslog协议

image.png
image.png
rsyslog与nginx:
image.png

5.4.3 零拷贝与gzip_static模块

sendfile 零拷贝提升性能

image.png
注意:直接IO会自动禁用sendfile
image.png

gzip_static模块

image.png

gunzip模块

image.png

5.5 监控分析Nginx运行状态

5.5.1 使用gperftools定位Nginx性能问题

image.png
文本展示说明:
image.png

5.5.2 使用stub_status模块监控Nginx状态

image.png

stub_status模块监控项

image.png

六、从源码视角深度使用Nginx和OpenResty

6.1 Nginx与第三方模块的关联关系

6.1.1 第三方模块源代码的快速阅读方法

image.png

config结构

image.png

configure脚本分析

image.png

configure执行结果

image.png
(1)configure概要,使用了哪些库或者功能
(2)一些重要文件的路径

6.1.2 Nginx启动流程

HTTP第三方模块初始化

image.png

HTTP模块的11个阶段:初始化

image.png

添加模块到11个阶段的两种常用方式

image.png

过滤模块的单链表

image.png

添加过滤模块的方式

image.png

6.1.3 Rewrite脚本

协程与Rewrite脚本

image.png

Rewrite脚本设置变量

image.png

脚本式编程:指令的实现

image.png

6.1.4 if指令

当if指令块连续出现时

image.png
说明:当if指令连续出现时,最后一个if为真的模块将一直影响到该模块结束。

if指令出现问题的根本原因

image.png

if指令的正确姿势

image.png

6.1.5 解读Nginx核心转储文件(coredump)

coredump核心转储文件

image.png

gdb调试基本命令

image.png

启用多进程模式

image.png

Debug定位问题:出现错误时的应对方案

image.png

6.1.6 通过debug日志定位问题

控制debug级别error.log日志的输出

image.png

debug日志类别

image.png

6.2 OpenResty的用法

6.2.1 OpenResty概述

OpenResty组成部分

image.png

OpenResty运行机制

image.png

OpenResty中的SDK

image.png

OpenResty的使用要点

image.png

6.2.2 OpenResty中的Nginx模块

核心模块

image.png

反向代理模块

image.png

工具模块

image.pngimage.png

6.2.3 OpenResty中的Lua模块

image.pngimage.pngimage.png

6.2.4 如何在Nginx中嵌入Lua代码

image.png

Nginx启动过程中嵌入Lua代码

image.png

在11个HTTP阶段中嵌入Lua代码

image.png

控制rewrite/access是否延迟执行Lua代码

image.png

Http反向代理流程嵌入Lua代码(balancer_by_lua)

image.png

Http反向代理收到响应-加工响应内容

image.png

在负载均衡和过滤响应时嵌入Lua代码

image.png

在OpenSSL处理SSL协议时嵌入Lua代码

image.png

在Lua代码中获取当前阶段

image.png

6.2.5 Openresty中Lua和C代码交互原理

Lua FFI

image.png

系统级配置指令

image.png

取得配置参数的SDK

image.png

6.2.6 获取、修改请求和响应的SDK

读取、修改变量的SDK

image.png

客户端提前关闭连接

image.png

获取请求头部的SDK

image.png

获取请求URL的SDK

image.png

获取请求Body的SDK

image.png

HTTP请求方法名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值