webman采用阻塞worker模式运行为什么性能还这么高?

king

问题描述

webman采用阻塞worker模式运行为什么性能还这么高?

为此你搜索到了哪些方案及不适用的原因

截图

既然这样的话那么假如开启了100个worker进程,那么在瞬时只能实时处理100个请求,每个请求假如500ms,那么第101个请求过来是会被阻塞500ms左右,最后第101次执行完成需要耗时500ms + 500ms,这样的一个机制难道不会在并发情况下出现很大的性能问题吗?

php-fpm、swoole、go,它们都是可以非阻塞的接收请求,不会出现第101个请求打进来时受其他请求的影响,所以哪位能给说说这种情况难道真的可以接受嘛?

1159 2 3
2个回答

tanhongbin

php-fpm 能非阻塞接受请求 ???????????????????????????????????????????

  • king 2023-07-03

    每次请求都是一个独立进程,为什么不可以呀?

  • tanhongbin 2023-07-03

    难受,是阻塞的呀,就是你开500进程 最多就是接受500个请求,现在webman 有协程加持 可以处理请求第三方请求阻塞问题了

  • king 2023-07-03
    1. fpm开500个进程,每个进程是独立的,不会受其他进程的影响,而worker的这种模式是复用worker,所以会造成worker进程本身的阻塞,这是两码事。

    2. “webman 有协程加持,可以处理请求第三方请求阻塞问题了”,5.0我看过了,目前还没有发布正式版本。但真实业务中不单单是请求第三方curl,每一个可能存在耗时(IO、cup密集计算等)的操作都会出现以上阻塞情况。

  • six 2023-07-03

    fpm是阻塞处理,虽然可以设置动态进程数,但也并不是一个请求创建一个进程。现在基本没有一个请求创建一个进程的服务器软件了,因为那样性能极低。

    webman支持fiber协程调用第三方接口,第三方接口慢不会阻塞业务。
    另外看了下源码,webman也支持swoole/swow作为驱动,应该可以使用swoole或swow的协程。

  • king 2023-07-03

    fpm是同步处理没有问题,但是我的意思是它的每一次请求都是在一个独立的进程内完成的,所以不会因为当前的进程没有处理完成而导致其他进程出现阻塞请求(前提未达到设定的最大进程数量时,因为这又是另外一个概念了),可能我描述的概念不够清晰,总之一个复用进程,一个独占进程。

    那么就目前而言,webman这个机制处理一些io操作确实不如swoole这种非阻塞的模式合适。。

  • six 2023-07-03

    fpm也一样,100个进程,瞬间第101个请求过来时也是在排队阻塞等待处理,这和webman没有多少区别。
    webman本身io处理机制和swoole是一样的,都是基于event-loop加非阻塞IO,差别也不大。但是webman身为php层面的框架无法改变PHP内置函数(如PDO)的IO接口阻塞问题,而swoole作为扩展可以hook这些阻塞接口变成非阻塞。区别实际在于这里。说得通俗一点,webman本身的IO是异步非阻塞的,但是业务代码可能是阻塞的。

    另外webman本身也支持swoole驱动,可以hook PHP内置的IO接口,达到非阻塞调用,但是带来的负面影响就是和swoole一样,需要管理上下文。

  • king 2023-07-03

    OK,学习了

  • walkor 2023-07-03

    @six 专业

  • nitron 2023-07-03

    你把Webman当成不需要每次请求都冷启动一次框架代码的FPM(近似)就好理解了

chaz6chez

有栈/无栈协程本身不具备并发处理能力,仅仅只是将异步编码同步化的能力,说白了就是整理代码执行顺序的能力,让你通过简单的同步书写的方法就可以轻松实现异步的执行;
在主线程上运行的协程本质上和同步阻塞没有太大区别:

  • 同步阻塞下:100个请求打在一个worker进程上,和阻塞队列类似,队列容量就是socket buffer的大小,只要buffer足够多,worker进程就可以继续接收请求等待;假设每个请求需要2秒执行完成,那么100个请求需要200秒完成。
  • 主线程协程下:100个请求被稀释在协程中,每个协程栈储存了这个请求的上下文,所有上下文由协程调度器来进行运行,看起来就如同把socket buffer交给协程栈来保存了而已。

所以现在的协程调度器至少都是另起一个/多个线程来执行,保证不阻塞主线程,主线程主要负责接收,然后拆分丢给协程调度器,看起来就是一个迷你的基于线程的master-worker模型;

再说回MySQL或者Redis等服务,他们是C/S架构的服务,所以一个进程/线程上可以启动多个client,多个client在宏观上看起来就是多个线程,因为可以并行执行(Redis客户端也同样,但执行命令时是单线程),这个时候利用多个协程来向多个client发起请求的时候,本质上是利用了多线程,因为每个client的消息是不会相互阻塞的,本质上也是因为这些服务是支持并行处理的;而workerman这边只是颗粒度粗一些,是一个进程对应一个/多个client,但是相互阻塞排队的;

结论:看性能的话,主要看最后并行的情况,和缩减阻塞等待的时间,并行就是利用多核,目前来说利用多核就是进程/线程,不论是自身利用还是所使用的服务利用,都是利用。

  • king 2023-07-03

    讲解很详细,其实异步并行能够更充分的利用服务器资源,达到一个比较高的处理效率~

    多线程在这里只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。多线程在解决高并发问题中所起到的作用就是使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

  • chaz6chez 2023-07-03

    是的,单线程异步就需要利用事件循环,本质上可以看作是一个消费者,通过自己的规则来进行消费

🔝