疑问:webman是基于workerman的框架,mysql既然是阻塞的,如何做到高并发呢?

RayInHeart

webman是基于workerman的框架,mysql既然是阻塞的,如何做到高并发呢?

根据官方手册,workerman是多进程架构,各个工作进程处理请求,而mysql是阻塞操作,也就是说要遇到耗时的数据库操作是要等待的。那么我不能理解的是,既然这里出现阻塞,岂不是拖累了框架的性能嘛。workerman每个进程都是使用epoll的非阻塞运行方式,那我理解应该是对http请求用这个方式处理,也就是事件机制,那mysql在这里到底会不会拖累这个结果呢,比如一个http请求需要等mysql的数据结果,那个这个是不是等结果出来再响应,等待的时间继续下一个请求?这么理解对吗?那么问题来了,如果出现一个超长时间阻塞的case(在真实的公网环境下一定有概率发生,DNS查询卡住、网络请求超时等),那么这个进程岂不是被阻塞了嘛,那是不是就要靠其他进程来处理更多请求,那不是要开好多进程。换言之,单个 IO 等待过长是否影响当前一个请求所在的进程,其他请求是可以在该进程继续向下执行还是由其他进程执行?遇到这种短时间多个复杂mysql查询的请求,这种情况webman是如何优化的?

谢谢!

1100 6 1
6个回答

liziyu

那么问题来了,如果出现一个超长时间阻塞的case(在真实的公网环境下一定有概率发生,DNS查询卡住、网络请求超时等),那么这个进程岂不是被阻塞了嘛。

大佬tw**e吗?^_^

  • nitron 2022-12-20

    哈哈哈,要素察觉

  • RayInHeart 2022-12-21

    我不是tw**e。这句话是我和同事聊天的时候他发给我的,我觉得描述的比较精炼,直接copy了~看来这句话是有出处的...

  • 张若初 2022-12-22

    等PHP8的协程吧

nitron

等待mysql结果时当前进程无法处理下一个请求,每个进程只能同时处理一个

单个 IO 等待过长是否影响当前一个请求所在的进程,其他请求是可以在该进程继续向下执行还是由其他进程执行

由其他进程执行或者在当前进程排队

遇到这种短时间多个复杂mysql查询的请求,这种情况webman是如何优化的?

优化sql

  • zgh419566 2022-12-21

    方法1:将请求发给其他专门的程序去处理;
    方法2:使用workerman+swoole协程方式实现

  • RayInHeart 2022-12-21

    workerman也可以和swoole并存吗,厉害的

  • RayInHeart 2022-12-21

    我有点不解的是,每个工作进程都是epoll非阻塞模型,为什么遇到mysql查询就退化成阻塞了呢,如果是这样,岂不是比FPM的运行模式的优势不就就只多了一个常驻内存嘛?(当然workerman还可以用于网络编程,应用领域更广)

  • zgh419566 2022-12-26

    可以的 ,你试一下
    <?php
    //*****//
    Worker::$eventLoopClass = 'Workerman\Events\Swoole';
    Co::set(['hook_flags' => SWOOLE_HOOK_SLEEP]);
    Swoole\Coroutine::set(['enable_deadlock_check' => false]);

MarkGo

个人见解:
1、mysql是阻塞操作,也就是说要遇到耗时的数据库操作是要等待的。
就算使用协程方式,其实也是堵塞,mysql只要发生堵塞,后续基本越来越塞,特别是加锁的情况下,必须等待上一个解锁后才能开始下一个。这场景是否协程意义不大。
单纯慢查询不涉及锁的情况下,协程的优点会提现出来,但最终还要看数据库IO,比方一个3S的慢查,可能触发了全表查询,此时如果数据库IO已经100%了,后续再多查询都快不了去哪里,针对这种情况webman的方法是多开进程。

2、如果出现一个超长时间阻塞的case(在真实的公网环境下一定有概率发生,DNS查询卡住、网络请求超时等)
其实同上,协程并不能减少以上case发生频率,只是能加大吞吐。
如果通过协程方式,开一个进程,可能就能解决了单进程阻塞问题;
而webman的话只能通过多进程方式,具体多到多少就要看平均请求量,一般这种涉及网络查询的,最好加个超时。

  • 暂无评论
happy321

https://revolt.run/ php的协程库已经发正式版了,等老大集成进去了就可以用了

什么是Revolt?
Revolt是一个用于并发的PHP应用程序的坚硬的事件循环。通常的PHP应用程序的大部分时间是在等待I/O。虽然PHP是单线程的,但合作多任务可以通过利用等待时间做不同的事情来实现并发。

PHP的传统同步执行流程很容易理解。一次做一件事。如果你查询一个数据库,你发送查询并等待数据库服务器的响应。一旦得到响应,你就可以开始做下一件事。

Amp、ReactPHP和其他库在PHP中提供合作式多任务已经有很长一段时间了。然而,它们的事件驱动性质与许多现有的接口不兼容,需要一个不同的思维模型。PHP 8.1内置了Fibers,它提供了合作多线程。调用可以是异步的,没有承诺或回调,同时仍然允许非阻塞的I/O。

每个使用合作多线程的应用程序都需要一个单一的调度器(也叫事件循环),这个包提供了这个调度器。Revolt是结合Amp和ReactPHP的事件循环实现的多年经验的结果。然而,它并不是一个完整的编写并发PHP应用程序的框架,而只是提供了作为一个共同基础的必要条件。不同的(强烈)意见的库可以建立在它上面,Amp和ReactPHP都将继续共存。

  • 暂无评论
深林孤鹰

workerman差个协程就无敌了~
至于数据库瓶颈,只能优化sql语句、加各种cache、读写分离、分布式数据库来缓解。

  • 暂无评论
tanhongbin

你这种情况,啥玩意啥语言都是白费的,mysql出现这个问题意味着cpu飙升,并发几十个就会100%,后续的处理基本都瘫痪

  • 暂无评论
🔝