nginx原理了解
| |||||
什么是nginx? | ngnix是一款自由的、开源的、高性能的HTTP服务器[1] 和反向代理服务器; 同时也是一个IMAP、POP3、SMTP代理服务器; Nginx 可以作为一个HTTP服务器进行网站的发布处理,另外 Nginx 可以作为反向代理进行负载均衡的实现。
| ||||
Nginx三个主要应用场景 | 1、静态资源服务(通过本地文件系统提供服务) 2、缓存、负载均衡服务器(反向代理能够用于在多个后端服务器提供负载均衡,能够简单的将多个服务器映射到同一个URL空间)
3.API服务(OpenResty)
| ||||
为什么选择nginx? |
这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应;另一方面, 在高峰期(如有数以万计的并发请求), Nginx 可以比其他Web服务器并发时可以更快地响应请求。
高可靠性是我们选择 Nginx 的最基本条件,因为 Nginx 的可靠性是大家有目共睹的,很多家高流量网站都在核心服务器上大规模使用 Nginx 。 Nginx 的高可靠性来自于其核心框架代码设计优秀、模块设计的简单性;另外,官方提供的常用模块都非常稳定,每个 worker 进程相对独立,master进程在1个 worker 进程出错时可以快速“拉起”新的 worker 子进程提供服务。
一般情况下,10000个非活跃的HTTP Keep-Alive连接在 Nginx 中仅消耗2.5MB的内存,这是 Nginx 支持高并发连接的基础。
| ||||
Nginx高效的原因及原理解析 | 服务器的网络服务模型web服务器和客户端是一对多的关系,Web服务器必须要有能力处理多个客户端的请求。一般来说完成ngnix服务器并行处理多个客户端请求有三种工作方式
1、单进程阻塞的网络服务器2、多进程方式3、单进程IO复用方式
| ||||
单进程阻塞的网络服务器 |
1、创建一个socket,绑定服务器端口(bind),监听端口(listen),在PHP中用stream_socket_server一个函数就能完成上面3个步骤
2、客户端与服务端的连接,进入while循环,等待客户端连接进入,此时程序会进入睡眠状态,直到有新的客户端发起连接到服务器,操作系统会唤醒此进程。accept函数返回与客户端连接的socket
长连接的服务会持续与客户端交互, 而短连接服务一般收到响应就会close。
缺点: 一次只能处理一个连接,不支持多个连接同时处理 老师只能应付一个学生
Fd = 1 -><- 服务端( 协议 端口 范围1-65535 ) 触发事件执行了事件回调,当有请求来的时候,会将业务交给后端 http 基于tcp协议封装的 Tcp 、 udp
Fd = 2 <-
通过fd标识符区分客户端
Swoole workerman的区别 主要体现在对协程的支持 W 是纯异步的 意味着代码的嵌套 开发起来复杂
| ||||
多进程方式 | 多进程方式指,服务器每收到一个客户端请求,服务器主进程就会生成一个子进程出来和客户端建立连接进行交互,直到连接断开该子进程就结束了。
程序启动后就会创建N个进程。每个子进程进入 Accept,等待新的连接进入。当客户端连接到服务器时,其中一个子进程会被唤醒,开始处理客户端请求,并且不再接受新的TCP连接。 当此连接关闭时,子进程会释放,重新进入 Accept,参与处理新的连接。
这个模型的优势是完全可以复用进程,不需要太多的上下文切换,比如php-fpm就是基于此 预派生子进程模型来处理解析php (pfp-fpm是如何处理解析php)
Pstree apn | grep xxx
1个worker只会处理一个请求,请求完后会销毁。 所以请求越多,会造成阻塞状态,或者请求超时,解决办法: 可以做负载均衡或者适当加点work进程,太多的话,会内存大,电脑慢,会有OOM
多进程方式的优点是设计简单,各个子进程相对独立,处理客户端请求时彼此不受干扰;
缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销;当有大量请求时,会导致系统性能下降; 例如:即时聊天程序,一台服务器可能要维持数十万的连接,那么就要启动数十万的进程来维持。这显然不可能 | ||||
单进程IO复用方式 |
优点:性能最好!一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。
缺点:稳定性!某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机,单进程对于大量任务处理乏力
一个老师可以同时服务多个学员 一个进程可以为多个连接做服务
| ||||
多进程的master-worker IO复用方式 |
| ||||
IO复用/EventLoop | 1、IO复用是什么? I/O多路复用就是通过一种机制,一个进程可以监视多个socket,一旦某个socket可读或可写,能够通知程序进行相应的读写操作,目前支持I/O多路复用的系统调用有 select , poll , epoll。
2、select跟pollSelect介绍:(拉一个学员出来问,你有问题吗?) 监视并等待多个文件描述符的属性变化(可读、可写或错误异常)。 select 函数监视的文件描述符分 3 类,分别是writefds、readfds、和 exceptfds。调用后 select 会阻塞,直到有描述符就绪(有数据可读、可写、或者有错误异常),或者超时( timeout 指定等待时间),函数才返回。当 select ()函数返回后,可以通过遍历 fdset,来找到就绪的描述符,并且描述符最大不能超过1024
Poll 介绍:(拉一个学员出来问,你有问题吗?) poll 的机制与 select 类似,与 select 在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是 poll 没有最大文件描述符数量的限制。 poll 和 select 同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
问题: select/poll 问题很明显,它们需要循环检测连接是否有事件。如果服务器有上百万个连接,在某一时间只有一个连接向服务器发送了数据, select/poll 需要做循环100万次,其中只有1次是命中的,剩下的99万9999次都是无效的,白白浪费了CPU资源。
更加灵活,没有描述符限制,无需轮询。
当连接有I/O流事件产生的时候, epoll 就会去告诉进程哪个连接有I/O流事件产生,然后进程就去处理这个连接。
这里可以多加一个选择 worker ,原因是因为 worker 是基于 epoll 的异步非阻塞的服务器程序。自然, worker 能够轻松处理10w+的并发连接,也就无可厚非了。
(有同学举手提问了,老师才会走过去)
php要使用epoll机制需要安装libevent依赖,或者是swoole当中的event机制 | ||||
进程相关 |
fork函数将创建调用的进程副本,并非根据完全不同的程序创建进程,而是复制正在运行的、调用fork函数的进程,但因为通过同一个进程、复制相同的内存空间,之后需要根据返回值加以区
父进程空间:fork函数会返回子进程id 子进程空间:fork函数返回0 如果小于0,说明进程创建失败
僵尸进程,占据着空间,跑不动了 父进程结束或者异常终止,而子进程继续运行。
我们需要做的就是在父进程中调用wait函数回收子进程。
孤儿进程 还在那里跑 |