Nginx核心知识100讲学习笔记(陶辉)Nginx架构基础(二)

一、网络收发与Nginx事件间的对应关系

1、网络传输

2、TCP流与报文

3、TCP协议与非阻塞接口

二、Nginx网络事件实例演示

1、TCP层:本地打开了53842,Nginx打开的是8080端口 进程与进程通信这件事情

2、IP层:本机IP地址:192.168.0.109 nginx服务器的IP地址:192.168.0.123(机器和机器之前怎么互相找到的问题)

 3、三次握手

  1. windows先向nginx发送一个SYN
  2. 相反的nginx所在的linux也会向windos发送一个SYN,这个时候nginx是没有感知到的、因为这是一个半打开的状态
  3. 直到widows再向nginx所在的linux服务器发送一个ACK时,linux操作系统才会通知nginx这时有一个读事件需要处理

 

三、 Nginx的事件驱动模型

1、Nginx的事件驱动模型

知道Nginx事件循环有什么好处?

  1. 第三方模块做大量的CPU计算,导致我处理一个事件会特别长,会导致后续队列中的大量事件长事件得不到处理
  2. 所以nginx无法容忍第三方模块长时间使用CPU执行计算任务
  3. 我们看到gzip模块不是一次计算而是分段计算

四、epoll的优劣和原理

1、epoll的优劣

 

2、epoll的原理

3、场景描述:

有100万用户同时与一个进程保持着TCP连接,而每一时刻只有几十个或几百个TCP连接是活跃的(接收到TCP包),
也就是说,在每一时刻,进程只需要处理这100万连接中的一小部分连接。那么,如何才能高效地处理这种场景呢?
进程是否在每次询问操作系统收集有事件发生的TCP连接时,把这100万个连接告诉操作系统,然后由操作系统找出其中有事件发生的几百个连接呢?

4、select和poll如何处理:

每次收集事件时,都把这100万连接的套接字传给操作系统(这首先就是用户态内存到内核态内存的大量复制),而由操作系统内核寻找这些连接上有没有未处理的事件,将会是巨大的资源浪费

这里有个非常明显的问题,即在某一时刻,进程收集有事件的连接时,其实这100万连接中的大部分都是没有事件发生的。

5、epoll如何处理

它在Linux内核中申请了一个简易的文件系统,把原先的一个select或者poll调用分成了3个部分:

  1. 调用epoll_create建立1个epoll对象(在epoll文件系统中给这个句柄分配资源)
  2. 调用epoll_ctl向epoll对象中添加这100万个连接的套接字
  3. 调用epoll_wait收集发生事件的连接。

这样,只需要在进程启动时建立1个epoll对象,并在需要的时候向它添加或删除连接就可以了

因此,在实际收集事件时,epoll_wait的效率就会非常高,因为调用epoll_wait时并没有向它传递这100万个连接,内核也不需要去遍历全部的连接。

 6、这是如何实现的

维护了一个epitem的数据结构,他通过两种数据结构把这两件事件分开实现

也就是Nginx每次取活跃连接的时候,我们只需要去遍历一个链表,这个链表里仅仅只有活跃的的连接、这样我们速度效率就会很高

1、创建:Nginx收到80端口建立连接的请求,请求连接成功以后,这时候我要添加一个读事件,这个读事件是用来读取http消息的,这个时候我可能会添加一个新的事件、或者是写事件

  这个添加我只会放到红黑树中,二叉平衡树能保证我的插入效率是logn的复杂度

2、添加:当操作系统接收到网卡中发送来一个报文的时候,这个链表就会增加一个链接

3、修改:读取一个事件的时候链表自然就没了

4、删除:如果我我不想再处理读事件和写事件,我只要从这个平衡二叉树移除一个节点

5、获取句柄:就是遍历活跃链接的链表,从内核态读取到用户态

五、Nginx的请求切换、同步&异步、阻塞&非阻塞之间的区别

1、Nginx的请求切换

每做一次切换大概需要5微妙,虽然很小,当并发量很大时切换需要的时间是指数级的增加
而Nginx直接在用户态进行切换、操作系统给了nginx足够处理请求的时间

2、阻塞调用

3、非阻塞调用

4、非阻塞调用下的同步与异步


反向代理的有一个特点:去考虑上游的服务处理请求是不足的,所以如果是一个有body的http请求,先把body接收完、再向上游发起连接

六、 Nginx的模块究竟是什么?

1、前提

 

1、提供了那些配置项:gzip模块官网查询

http://nginx.org/en/docs/http/ngx_http_gzip_module.html

2、我如何确定某个模块编译到nginx中呢?

有一个数组叫ngx_module_t *ngx_modules[]这个数组包含了编译进了nginx的模块,我们找一gzip摸快

[root@nginx objs]# pwd
/usr/local/src/nginx-1.14.2/objs
[root@nginx objs]# cat ngx_modules.c 

#include <ngx_config.h>
#include <ngx_core.h>

extern ngx_module_t  ngx_core_module;
......
extern ngx_module_t  ngx_http_not_modified_filter_module;

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    ......
    &ngx_http_gzip_filter_module,
	......
    &ngx_http_not_modified_filter_module,
    NULL
};

char *ngx_module_names[] = {
    "ngx_core_module",
	......
    "ngx_http_not_modified_filter_module",
    NULL
};

3、如何确定支持那些指令?

ngx_command_t 这个结构体是一个数组、数组中的每一个成员是他所支持的指令名

[root@luoahong modules]# pwd
/usr/local/src/openresty-1.13.6.2/bundle/nginx-1.13.6/src/http/modules
[root@luoahong modules]# cat -n ngx_http_gzip_filter_module.c
......
static ngx_command_t  ngx_http_gzip_filter_commands[] = {

    { ngx_string("gzip"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                        |NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, enable),
      NULL },

    { ngx_string("gzip_buffers"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
      ngx_conf_set_bufs_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, bufs),
      NULL },

    { ngx_string("gzip_types"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
      ngx_http_types_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, types_keys),
      &ngx_http_html_default_types[0] },

    { ngx_string("gzip_comp_level"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, level),
      &ngx_http_gzip_comp_level_bounds },

    { ngx_string("gzip_window"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, wbits),
      &ngx_http_gzip_window_p },

    { ngx_string("gzip_hash"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, memlevel),
      &ngx_http_gzip_hash_p },

    { ngx_string("postpone_gzipping"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, postpone_gzipping),
      NULL },

    { ngx_string("gzip_no_buffer"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, no_buffer),
      NULL },

    { ngx_string("gzip_min_length"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_gzip_conf_t, min_length),
      NULL },

      ngx_null_command
};
......

2、什么是?

 3、Nginx模块的分类

posted @ 2020-03-05 22:26  活的潇洒80  阅读(761)  评论(0编辑  收藏  举报