一 知识铺垫
① connection_pool_size
说明: connection_pool_size '512 字节'是 nginx 框架和客户端'建立了tcp连接时'就产生的
补充: pool_size只是内存池的'初始'分配大小,'实际'使用中可以'超出'此大小
强调: 连接池中的'连接'是指'tcp(代指)|udp(传输层)'连接
连接内存池'作用':对于'HTTP长连接',tcp连接块'被复用',增加对'资源的利用率'
② worker_connections
注意:nginx做'反向代理'的时候,每一个'客户端'消耗'两个[client-->nginx-->upstream]'连接
说明: worker_connections'不是随便'设置的,而是与'两个指标'有重要关联
[1]、一是'内存'大小
[2]、二是操作系统级别的"进程最大可打开文件数" -->进程最大可打开文件数'受限于'操作系统
相关参考
③ client_header_buffer_size
1)client_header_buffer_size则具体指明'某一用途下'的内存大小
2)这里就是'最开始接收HTTP请求'的内存大小
3)如果'请求行+请求头'的大小如果'没超过1k',large_client_header_buffers 没有'用武'之地
补充: 当接收到'1个字节(data)'时,'才会分配'这1K内存;建立好连接,到接收到'data字节',有时间差
思考:client_header_buffer_size'为什么'要从connection_pool中'分配'呢?
解读:
1)建立好'tcp连接'后就会有'connection_pool连接池'
2)此时究竟'收到的消息是HTTP/1'还是'其他协议'消息并'不确定',所以只能'从连接内存池'中分配
④ large_client_header_buffers
large_client_header_buffers都是从'连接内存池'中分配的
重点: 了解分配'大内存'生效的场景 <-- 如果'请求行+请求头'的大小如果'没超过1k'
1)假设:large_client_header_buffers的配置默认为'4 8k'
2)请求行'request line'的大小不能超过8k,否则返回'414'错误
3)请求头'request header'中的'每一个头部字段'的大小不能超过8k,否则返回400错误
备注:实际是'494'错误,但nginx统一返回'400'了
4)'请求行+请求头'总的大小'不能'超过'4 * 8k'
5)大内存主要是解决'接收'问题
+++++++++++++ '分配大内存的流程' +++++++++++++
先分配'8K'的内容,'复制'之前的1K的内容,用省下的7k'继续接收'url,继续用'状态机'分析
⑤ request_pool_size
说明: 而对于'请求'而言,需要保留'大量'的'上下文'信息,所以'连接内存池预分配'比请求内存池'大'
上下文信息: 'URI'、'Header'等
补充: 请求内存池涉及到'业务',根据业务需要'修改'参数
⑥ 有限状态机解析HTTP请求
⑦ client_header_timeout
client_header_timeout'含义':
1)当client 'connect'到服务端后,建立'tcp'连接后,并没有send数据
2)服务端'socket recv 头信息'的超时时间
目的: 设置这种'读取客户端数据'的超时时间,为了避免客户端'建立连接后'不发送任何数据,浪费'资源'
补充:'网络波动'、tcp超时重传等也会造成nginx在'建立连接'后,无法在'规定'时间接收完整header
二 处理HTTP请求头部的流程
① 接收请求事件模块
[1]、nginx开始'处理'nginx请求'之前'完成的事情
1)nginx框架先对客户端'建立连接',预分配'512'字节的内存大小
2)开始准备'接收'用户的'请求(data)'信息
[2]、nginx开启'内存'缓冲区接收tcp字节流、用状态机解析'请求头+请求行'
② 接收请求HTTP模块
思考来源
流程图参考
三 nginx在处理HTTP请求头遇到的报错
思考:'接收'tcp字节流和状态机'解析'请求行、请求头'发现'的问题
0) TLS/SSL
常见: 配置了'双向认证',但是客户端认证'不通过' -->客户端'证书过期'、'没有'配置证书
典型'error.log'报错: No required SSL certificate was sent
1)request_line
[1]、url太长['一般是查询参数'],超过默认'8k'会报错
[3]、请求行中的'HTTP1.2协议'nginx 'listen'不支持
2)request_header
[1]、请求行中'没有Host'头
[2]、单个'request_geader'太大,超过默认的'8k'
[3]、由于与'request_line'共用内存,剩余的大内存'不足以'容纳'继续接收'请求头
① 排查思路
说明:nginx记录'4xx',不一定是nginx自身返回的
1)是否'转发'到上游
[1]、没有转发 --> 查看'access.log'和'error.log'日志综合分析
[2]、转发了 --> 还要协查'源站'的日志
2)频次:'偶'现还是'必'现
[1]、低频 --> '抓包'、分析轻链路'499'
[2]、高频 --> 客户端的'请求方式'和服务端的'配置'
② 400 Bad Request
原因: 服务端认为'客户端请求语法(参数)'错误,导致nginx'无法理解'去处理请求
1) HTTP1.1没有携带Host头
rpm安装高版本curl
2)请求发送时的协议不正确
eg: http://www.wzj.com:443 ; nginx配置的'listen ssl 443'
client sent plain HTTP request to HTTPS port while reading client request header
3) Request请求头太大
1)400报错的时候,怎么判断是否是浏览器的'Header(尤其Cookies)'过大?
2)通过'nginx的debug日志'和浏览器'控制面板'来看
③ url过大 414报错
Request-URL的长度'超出'了服务器的处理能力
实验: 模拟'URL'过大
④ 408报错
408(Request Timeout):如果'完成请求'所花时间太长,'服务器'可以'返回'此状态码