Nginx核心知识100讲学习笔记(陶辉)Nginx架构基础(三)
一、Nginx如何通过连接池处理网络请求
1、连接池
1、预分配的connections_n 个链接
http://nginx.org/en/docs/ngx_core_module.html#worker_connections Syntax: worker_connections number; Default: worker_connections 512; Context: events
1、设置的越大,占用的内存越多
2、每一个connections到底是用了多大的内存呢?
64位操作系统中:大小232字节事件大小为96 一个连接就是328
2、仅当在一次read中,没有收到请求头,才会算成超时。
http://nginx.org/en/docs/http/ngx_http_core_module.html#client_header_timeout Syntax: client_header_timeout time; Default: client_header_timeout 60s; Context: http, server
定义用于读取客户端请求体的超时时间。超时仅设置在两个连续读取操作之间的时间段内,而不是用于整个请求体的传输。如果客户端在此时间内不发送任何内容,则请求终止(408)(请求超时)错误。
3、nginx返回给客户端的字节数,包括响应头和响应体
http://nginx.org/en/docs/http/ngx_http_core_module.html#variables $bytes_sent number of bytes sent to a client (1.3.8, 1.2.5)
NGIXN日志中的使用
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status [$request_length:$bytes_sent] "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
访问日志
192.168.0.109 - - [01/Mar/2020:17:57:58 +0800] "GET /plus.gif HTTP/1.1" 304 [435:179] "http://192.168.0.123:8080/" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/82.0.4068.5 Safari/537.36" "-
重点看:[435:179]
2、核心数据结构
二、内存池对性能的影响
1、允许精确调整每个连接内存分配connection_pool_size size
http://nginx.org/en/docs/http/ngx_http_core_module.html#connection_pool_size Syntax: connection_pool_size size; Default: connection_pool_size 256|512; Context: http, server
还可以分配更大的 、可以减少分配的次数
2、request_pool_size size
http://nginx.org/en/docs/http/ngx_http_core_module.html#request_pool_size Syntax: request_pool_size size; Default: request_pool_size 4k; $ Context: http, server
为什么这么小?对于连接而言需要的上下文信息特别少
三、所有worker进程协同工作的关键:共享内存
1、Nginx进程间的通讯方式
2、自旋锁
当锁的条件没有满足:也就是这把锁被1号work进程正在使用、那么2号进程去请求锁只要1号进程没有释放、那么2号会一直不停的请求这把锁
假入一把锁锁住了一扇门、如果work1号进程已经拿到这把锁、那么work2号去敲门发现里面已经有人了、就会就地休息、等待1号进程出来以后通知她、而自旋锁就不一样work2进程发现门里有人会持续的敲门
3、共享内存:nginx那些模块使用到了共享内存:单链表
1、为什么需要一个链表?
因为这个10M是有限的、但我们的lua代码涉及到了应用代码、我们的应用代码很容易超过10M的限制
当超过了10M的限制、他用LRU淘汰、最早set或get不同的节点会被淘汰掉
2、单链表模块
Ngx_http_upstream_zone_module Ngx_stream_upstream_zone_module
4、nginx那些模块使用到了共享内存:红黑树
比如我们想做限速、流控不能容忍在内存中做的、否则一个work进程对于某一个用户触发了一个流控、而其他的work进程确不知道、所以我们只能在共享内存中做的
Ngx_stream_limit_conn_module Ngx_http_limit_conn_module Ngx_stream_limit_req_module Ngx_http_file_cache Ngx_http_proxy_module http cache Ngx_http_scgi_module Ngx_http_uwsgi_module Ngx_http_fastcgi_module Ngx_http_ssl_modul ssl Ngx_mail_ssl_module Ngx_stream_ssl_module
这些模块都有一个共同的特点:我需要快速的插入和删除
比如我现在发现了一个客户端、需要对他限速、如果限速达到了、我要把这个客户端从我的限速容器中移出、都需要非常的快速
3、Ngx_http_lua_api :OpenResty共享内存代码示例
定义了一个sdk sdk的名称叫做lua_shared_dict
当这个指令出现的时候它会分配一块共享内存大小为:10M 这块共享名称叫做dogs
使用红黑树来保存每一个key value
四、 用好共享内存的工具:Slab管理器
最多两倍内存消耗
2、应用场景:适合小对象
因为我们要分配的内存特别小、比如分配小于一个页面的大小、因为它很少会有碎片 有时候我分配的内存数据机构是固定大小的甚至需要初始化、那么原来的数据结构都还在、这样就避免了重复初始化
2、ngx_slab_stat模块安装
1、下载
wget http://tengine.taobao.org/download/tengine-2.3.2.tar.gz tar xf tengine-2.3.2.tar.gz [root@ceph-client ngx_slab_stat]# pwd /usr/local/src/tengine-2.3.2/modules/ngx_slab_stat [root@ceph-client ngx_slab_stat]# ll total 44 -rw-rw-r--. 1 root root 204 Sep 5 2019 config -rw-rw-r--. 1 root root 6627 Sep 5 2019 ngx_http_slab_stat_module.c -rw-rw-r--. 1 root root 3465 Sep 5 2019 README.cn -rw-rw-r--. 1 root root 3501 Sep 5 2019 README.md -rw-rw-r--. 1 root root 21430 Sep 5 2019 slab_stat.patch drwxrwxr-x. 2 root root 20 Sep 5 2019 t
2、编译安装
[root@ceph-client openresty-1.13.6.2]# pwd /usr/local/src/openresty-1.13.6.2 [root@ceph-client openresty-1.13.6.2]#./configure --add-module=../tengine-2.3.2/modules/ngx_slab_stat/ [root@ceph-client openresty-1.13.6.2]#make [root@ceph-client openresty-1.13.6.2]#make install
3、替换nginx二进制文件 ,当前nginx文件最好备份下,避免出问题
[root@ceph-client conf]# nginx -s reload [root@ceph-client conf]# netstat -lntup|grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 22522/nginx: master [root@ceph-client]#cp /usr/local/openresty/nginx/sbin/nginx /usr/local/bin/nginx [root@ceph-client bin]# ll /usr/local/bin/ total 15464 lrwxrwxrwx. 1 root root 37 Mar 4 09:57 nginx -> /usr/local/openresty/nginx/sbin/nginx -rwxr-xr-x. 1 root root 15832600 Aug 19 11:11 nginx_no_slab_stat /usr/local/openresty/nginx/sbin/nginx
4、验证是否安装成功
[root@ceph-client ~]# nginx -V nginx version: openresty/1.13.6.2 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.0 ..... --add-module=/usr/local/src/openresty-1.13.6.2/../tengine-2.3.2/modules/ngx_slab_stat --with-stream --with-stream_ssl_module --with-http_ssl_module
3、统计Slab使用状态
nginx配置文件
[root@ceph-client ~]# grep -vE "#|^$" /usr/local/openresty/nginx/conf/nginx.conf worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; lua_shared_dict dogs 10m; server { listen 80; server_name localhost; location = /slab_stat { slab_stat; } location = /set { content_by_lua_block{ local dogs = ngx.shared.dogs dogs:set("JIM",8) ngx.say("STORED") } } location = /get { content_by_lua_block{ local dogs = ngx.shared.dogs ngx.say(dogs:get("JIM")) } } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
[root@ceph-client ~]# curl localhost:80/set STORED [root@ceph-client ~]# curl localhost:80/get 8 [root@ceph-client conf]# curl http://localhost:80/slab_stat * shared memory: dogs total: 10240(KB) free: 10168(KB) size: 4(KB) pages: 10168(KB) start:00007F2DE5FFC000 end:00007F2DE69EC000 slot: 8(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 16(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 32(Bytes) total: 127 used: 1 reqs: 1 fails: 0 slot: 64(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 128(Bytes) total: 32 used: 1 reqs: 1 fails: 0 slot: 256(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 512(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 1024(Bytes) total: 0 used: 0 reqs: 0 fails: 0 slot: 2048(Bytes) total: 0 used: 0 reqs: 0 fails:
五、 哈希表的max_size与bucket_size如何配置
1、Nginx容器
2、Nginx哈希表
1、nginx的哈希表和我们正常见得到hash表有什么不同?
从实现层面看:是相似的、哪里不同?应用场景不同:
仅仅应用于静态不变的内容、也就是在运行过程中这个hash表通常不会存在插入和删除的操作也就是说刚启动的时候已经确定hash表中一共有多少元素
3、哈希表配置
1、Max size的作用
Max size是最大的Bucket size、而不是实际上使用的的多少、Max size的作用限制了最大化的使用我们的内存
2、我们的哈希表为什么要向64节对齐了?
如果一个Bucket是59字节、如果是紧密排列在一起的、这样你取第一个字节取了两个元素、然后第二个元素就要取两次、为了这种取两次的的问题nginx在它的代码中自动的向上对齐了
3、配置Bucket size需要注意两个问题
所以我们在配置Bucket size需要注意两个问题
如果没有特殊需求建议配置不要超过64字节、避免一个元素取两次 如果你配置70字节、它就会给我们分配128字节
4、所有使用hash表的结构的模块都有哪些特点了?
他们对所有的变量使用了hash表