zoukankan      html  css  js  c++  java
  • 阻塞和非阻塞模型

    1.PHP-FPM是阻塞模型,假设你用 php-fpm,你的 php 程序中需要向外部提供接口请求。那么每一个 Worker 进程在执行这些网络 I/O 的时候,是不是都阻塞了?假设你的 php-fpm 最大进程数有 500 个,那么同时进来了 500 个请求,是不是都阻塞在了网络 I/O 上了?那么接下来,php-fpm 已经无法处理第 501 个请求了。可是此时,由于在等待网络 I/O 响应,CPU 实际上并没有做什么工作,你会发现,CPU 很闲,但是却无法处理请求了。

    swoole是非阻塞模型,例如Swoole,我们在网络 I/O 的时候,让它去等待响应,与此同时,处理下一个请求。那么,我们会发现,并发数上去了,CPU 的利用率变高了。

    如果只有一个套接字的情况下,使用阻塞IO是极好的,读到数据就返回。

    但是如果在有很多套接字的情况下,比如有100个套接字:

    1. 如果使用阻塞IO,可能因为读取一个没有数据的套接字而阻塞剩下的99个套接字的数据处理,那么就会造成服务器的响应性很差。
    2. 如果使用非阻塞IO,那么就需要轮询这一百个套接字到底可不可以读取到数据,这个轮询操作会浪费CPU时间片,照样也不是一个高效的方式,套接字多了,照样性能很差。

    那有没有一种比较好的方式来同时检测多个套接字是否可读可写,并且不浪费CPU时间片呢?那就是要用IO多路复用了,使用IO多路复用可以同时检测多个不同的套接字是否就绪。有多种IO多路复用的实现,其中包括select,poll, epoll, /dev/poll, kqueue等。

    2.Nginx 是非阻塞IO复用模型,通过操作系统提供的类似 epoll 的功能,可以在一个线程里处理多个客户端的请求。

    Nginx 的进程就是线程,即每个进程里只有一个线程,但这一个线程可以服务多个客户端。

    PHP-FPM 是阻塞的单线程模型,配置文件中pm.max_children 指定的是最大的进程数量,pm.max_requests 指定的是每个进程处理多少个请求后重启(因为 PHP 偶尔会有内存泄漏,所以需要重启)。

    PHP-FPM 的每个进程也只有一个线程,但是一个进程同时只能服务一个客户端。

    大多数的 Linux 程序都倾向于使用进程而不是线程,因为 Linux 下相对来说创建进程的开销比较小,而 Linux 的线程功能又不是很强大。

    3.首先登录nginx.com机器查看nginx worker进程数,然后我们登录web.com机器查看php-fpm的worker进程数(子进程数)。

    异步非阻塞

    • 同步,就是外卖小哥给你送外卖,送到了就等你给钱,不给不走
    • 异步,就是外卖小哥给你送外卖,送到了你说没钱,等有钱在给,他就走了,有一天你有钱了,就通知外卖小哥,过来拿钱。
    • 阻塞,就是你是送外卖的,去店里拿外卖,拿到了你就给订外卖的人打电话送钱来,然后就一直等着他,期间不能做别的事情。
    • 非阻塞,就是你是送外卖的,去店里拿外卖,拿到了你就给订外卖的人打电话送钱来,但是不用等着他,你又可以处理其他事情,喝喝茶。

    所以同步、异步指的是发送方,阻塞、非阻塞指的是接收方

    即: 客户端(异步/同步) => 服务器(阻塞/非阻塞)

    这里有个问题,异步,客户端请求完了,你没给钱就让他走了,人走了,还回得来么?

    即:服务端send(异步/同步) => 服务器recv(阻塞/非阻塞)

    (1)为什么用php-fpm?

    cgi执行方式慢!为啥?如果nginx每次接收到一个请求后,通过popen,执行 php index.php是什么感觉?

    apache_mod执行方式,有点慢!不灵活!apache在启动的时候把php解析器给加载进去了,合体了!每次请求过来的时候需要通过解析器执行用户代码

    fastcgi执行方式(php-fpm), 很快!通过socket和nginx通信,解耦了!opcache缓存了字节码不用每次解析用户代码了!

    即:php-fpm是多进程的,主进程负责worker进程的调度,socket bind && listen。worker进程负责socket accept,不要怀疑为什么worker进程同时accept不会发生惊群,linux内核已经加锁了。worker进程就是异步非阻塞的模型了,使用的poll函数。worker进程同一时间只执行一个请求,所以不会因为描述符数量上升影响poll的效率。

    (2)nginx

    即:nginx也是多进程的,主进程负责worker进程的调度,不处理请求。但是worker进程使用的是epoll,因为worker进程并不是同时只能处理一个请求,他处理请求的个数是没有限制的,直至达到服务器的性能瓶颈。

    所以我们通常把nginx的worker进程数设置为cpu核数,每个进程通过异步非阻塞同时轮训处理多个请求,这样所有的worker进程可以保证cpu可以完全利用起来。

    php-fpm的机器和nginx机器是一样的,但是每个进程只能同时处理一个请求,如果只有20个进程,cpu将长时间处于空闲状态,异步非阻塞会让出cpu的使用权,这时候cpu就可以处理更多进程的任务,直至完全利用。

  • 相关阅读:
    Info.plist的秘密(raywenderlich笔记)
    我所理解的性能测试中负载测试与压力测试的区别
    seo优化
    localStorage,sessionStorage那些事儿
    浏览器cookie那些事儿
    JavaScript--Ajax请求
    javascript-理解原型、原型链
    React Native:从入门到原理
    知道这 20 个正则表达式,能让你少写 1,000 行代码
    程序猿进化必读:让App的运行速度与响应速度趋于一流(iOS)
  • 原文地址:https://www.cnblogs.com/redfire/p/11972775.html
Copyright © 2011-2022 走看看