web服务之NGINX架构&模块

3.2 nginx架构

架构基础

3.2.1 nginx进程结构

任何Unix应用程序的基本基础都是线程或进程

 

NGINX Worker流程内部

在这里插入图片描述

每个NGINX工作进程都使用NGINX配置初始化,并且由主进程提供一组侦听套接字。

NGINX工作进程始于等待侦听套接字上的事件(accept_mutex和内核套接字分片)。事件由新的传入连接启动。这些连接被分配给状态机 -HTTP状态机是最常用的,但是NGINX还为流(原始TCP)流量和许多邮件协议(SMTP,IMAP和POP3)实现状态机。

在这里插入图片描述

状态机本质上是一组指令,用于告诉NGINX如何处理请求。大多数执行与NGINX相同功能的Web服务器都使用类似的状态机-区别在于实现。

 

1.单进程结构

用于开发,调试环境

 

2.多进程结构

在这里插入图片描述

 

3.参考链接

https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

 

3.2.2 epoll模型

Linux中IO复用工具:在Linux中先后出现了select、poll、epoll等,FreeBSD的kqueue也是非常优秀的IO复用工具,kqueue的原理和epoll很类似

参考知乎文章:https://www.zhihu.com/question/20122137/answer/14049112

流:一个流可以是文件,socket,pipe等等可以进行I/O操作的内核对象。

阻塞:比如某个时候你在等快递,但是你不知道快递什么时候过来,而且你没有别的事可以干(或者说接下来的事要等快递来了才能做);那么你可以去睡觉了,因为你知道快递把货送来时一定会给你打个电话(假定一定能叫醒你)。

非阻塞轮询:接着上面等快递的例子,如果用忙轮询的方法,那么你需要知道快递员的手机号,然后每分钟给他挂个电话:“你到了没?”

为了避免CPU空转,可以引进了一个代理(一开始有一位叫做select的代理,后来又有一位叫做poll的代理,不过两者的本质是一样的)。

这个代理比较厉害,可以同时观察许多流的I/O事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中醒来,于是我们的程序就会轮询一遍所有的流(于是我们可以把“忙”字去掉了)。

于是,如果没有I/O事件产生,我们的程序就会阻塞在select处。

epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll只会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。(复杂度降低到了O(k),k为产生I/O事件的流的个数,也有认为O(1)的)

注:单个select最多只能同时处理1024个socket。

 
select的做法:

步骤1的解法:select创建3个文件描述符集,并将这些文件描述符拷贝到内核中,这里限制了文件句柄的最大的数量为1024(注意是全部传入—第一次拷贝);

步骤2的解法:内核针对读缓冲区和写缓冲区来判断是否可读可写,这个动作和select无关;

步骤3的解法:内核在检测到文件句柄可读/可写时就产生中断通知监控者select,select被内核触发之后,就返回可读可写的文件句柄的总数;

步骤4的解法:select会将之前传递给内核的文件句柄再次从内核传到用户态(第2次拷贝),select返回给用户态的只是可读可写的文件句柄总数,再使用FD_ISSET宏函数来检测哪些文件I/O可读可写(遍历);

步骤5的解法:select对于事件的监控是建立在内核的修改之上的,也就是说经过一次监控之后,内核会修改位,因此再次监控时需要再次从用户态向内核态进行拷贝(第N次拷贝)

 
epoll的做法:

步骤1的解法:首先执行epoll_create在内核专属于epoll的高速cache区,并在该缓冲区建立红黑树和就绪链表,用户态传入的文件句柄将被放到红黑树中(第一次拷贝)。

步骤2的解法:内核针对读缓冲区和写缓冲区来判断是否可读可写,这个动作与epoll无关;

步骤3的解法:epoll_ctl执行add动作时除了将文件句柄放到红黑树上之外,还向内核注册了该文件句柄的回调函数,内核在检测到某句柄可读可写时则调用该回调函数,回调函数将文件句柄放到就绪链表。

步骤4的解法:epoll_wait只监控就绪链表就可以,如果就绪链表有文件句柄,则表示该文件句柄可读可写,并返回到用户态(少量的拷贝);

步骤5的解法:由于内核不修改文件句柄的位,因此只需要在第一次传入就可以重复监控,直到使用epoll_ctl删除,否则不需要重新传入,因此无多次拷贝。

简单说:epoll是继承了select/poll的I/O复用的思想,并在二者的基础上从监控IO流、查找I/O事件等角度来提高效率,具体地说就是内核句柄列表、红黑树、就绪list链表来实现的。

 
 

epoll高效的原因:

​ 这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件.

​ 当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效

五种网络IO模型和select/epoll对比:https://zhuanlan.zhihu.com/p/38277885

在这里插入图片描述

 

3.3 nginx模块

 

3.3.1 动态模块

nginx在编译时可以将模块编程成动态模块,需要使用模块时被可执行文件加载

./configure --XXX=dynamic

 

3.3.2 模块本质

指令

内置变量

 

3.3.3 模块指令

值指令:可以被局部的值指令覆盖

动作指令:一旦满足某条件直接执行

 

3.3.4 请求处理的11个阶段
1.nginx模块简介
  • 核心功能(Core Functionality)

参考网址:http://nginx.org/en/docs/ngx_core_module.html

功能:主要负责nginx的main区块和event区块,定义了nginx的全局参数

 
 

  • http标准功能模块集合

参考网址:http://nginx.org/en/docs/

模块列表

在这里插入图片描述

 

2.请求处理流程示意图

在这里插入图片描述

 

3.请求处理的11个阶段

在这里插入图片描述

 

1.POST_READ

读取请求头后

realip

REALIP_MODULE模块:https://my.oschina.net/xxj123go/blog/907041/print

 
1.1 模块功能

​ 在复杂集群环境中remote_addr 为反向代理的地址,而不是真实客户端ip,realip用于获取真正客户端地址

在这里插入图片描述

 

1.2 模块指令

set_real_ip_from 定义可信任的地址

在这里插入图片描述

 

real_ip_header 定义使用那个请求头部

在这里插入图片描述

 

real_ip_recursive 如果最后一个地址是本机地址则去除,去去除后的非本机地址

在这里插入图片描述

 
 

1.3 模块变量

$realip_remote_addr 替换之前的remote_addr

$realip_remote_port 替换之前的remote_port

 
 
1.4 模块实战

1.编辑hosts

192.168.217.155	www.pl.com realip.pl.com

2.安装nginx(编译realip到nginx)

./configire --prefix=/usr/local/nginx --with-http_realip_module
make

3.配置

nginx.conf

include conf.d/*.conf;
vi /usr/local/nginx/conf/conf.d/realip.conf
server {
        listen 80;
        server_name realip.pl.com;
        error_log logs/realip.err_log;

        set_real_ip
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值