zoukankan      html  css  js  c++  java
  • 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管理器

    1、Slab内存管理

    1、这样的数据结构会有内存的浪费、那么最多会浪费多少了?

    最多两倍内存消耗

    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;
            }
        }
    }

    5、查看服务状态

    [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表

  • 相关阅读:
    MT【105】待定系数算最大最小
    MT【103】二阶递推找规律
    MT【102】一个常见的因式分解公式
    MT【101】分配问题举例若干
    MT【100】经典计数之分配问题
    MT【99】2005联赛二试题我的一行解法
    Qt Creator键盘快捷键速查
    AdaBoost中利用Haar特征进行人脸识别算法分析与总结1——Haar特征与积分图
    图像开源代码
    c++实用技巧
  • 原文地址:https://www.cnblogs.com/luoahong/p/12409498.html
Copyright © 2011-2022 走看看