webman应用场景问题

badman

webman是不是不适合做依赖第三方接口的实时应用,比如某服务,需要依赖第三方的接口去查询用户信息,如果第三方接口的响应时间需要5秒(假设),同时进来50个请求(开启4个进程监听的话),那么是不是就会导致另外的46个请求至少要等5秒之后才有响应呢?如果想用webman实现这个业务类型应用是否有解决方案?

2588 11 6
11个回答

2548a

fpm模式的进程一样是阻塞的,它应对的方法无法就是多开进程,相对应的,webman也可以多开,对于这种阻塞严重的,你搞个一两百进程都可以.

  • 暂无评论
liziyu

“别给生活太多假设”。
干就完了! 相信webman能满足目前99%以上的web项目!

  • badman 2022-06-19

    不是假设啊,是我的业务场景就是有这样的,第三方接口经常性的1-60秒才有响应,有时候我并发又能达到1K左右,总不可能去开1K个进程吧?

  • liziyu 2022-06-19

    哦哦,这算是大项目了,没经历过呢!~

a178251115

如果你的请求不是需要实时响应,可以考虑用定时任务,异步任务,队列之类的来做

six

这种场景适合用workerman来做,配合workerman/http-client

  • badman 2022-06-19

    好的 我研究研究

  • 小阳光 2022-06-19

    这样也不行,只能多开进程,workerman/http-client是异步请求,无法和安卓ios等前端响应。楼主提的这个问题确实是php的短板,php一般基于进程而不是线程,如果是基于线程的话就很好解决楼主的问题,比如go的协程。

  • six 2022-06-19

    可以的,workerman配合workerman/http-client是非阻塞请求,可以响应安卓 iOS前端

  • evilk 2022-06-19

    协程只是能支持更多的请求而已,但不会缩短处理请求的时间,对于每个请求而言,该等5秒,还是要等5秒

  • 小阳光 2022-06-19

    前端请求服务器,服务器请求第三方接口,请求三方接口时用异步workerman/http-client, 请问你什么时候响应给前端

  • 小阳光 2022-06-19

    @evilk 协程可以开很多,因为开销很小,当前协程可以等待三方接口响应后再返回给前端,不像php一样受进程数量限制,协成它确实不会缩短三方接口的请求时间,但是可以同时处理更多前端请求,一个前端请求对应一个协程

  • six 2022-06-20

    @小阳光 示例代码发在下面了。

  • badman 2022-06-20

    非常感谢@小阳光 @
    six 两位的耐心解答和探讨。

  • WatcherLuo 2022-06-21

    在等待异步回调时难道要休眠挂起当前客户端连接吗?不然等回调时客户端连接已经断开了没法再返回数据了。

蚂蚁搬家

第三方接口 定时异步请求回来缓存可以吗

  • badman 2022-06-19

    不行的,比如获取验证码,肯定是要实时返回来。

  • 蚂蚁搬家 2022-06-19

    第三方API获取验证码??

缝合

其他语言也会有线程/进程数量的限制吧。go的http的是来一个请求创建一个协程。你这种场景是高io,低运算的场景,可以和其他接口分开单独开一个服务器,然后把webman的数量调整高一点,毕竟你的这个场景大多是在等待,把运算型和io型的分开也可以

  • 暂无评论
six

这种场景适合直接workerman + workerman/http-client 来做,纯异步的,没有所谓的协程消耗,代码类似这样

require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;

$worker = new Worker('http://0.0.0.0:1234');
$worker->onMessage = function (TcpConnection $connection, Request $request) {
    $http = new Workerman\Http\Client();
    $http->get('https://example.com/', function ($response) use ($connection) {
        $connection->send((string)$response->getBody());
    }, function ($exception) use ($connection) {
        $connection->send((string)$exception);
    });
};
Worker::runAll();
  • 小阳光 2022-06-20

    workerman是可以保存当前链接,提问是webman,有没有办法

  • six 2022-06-20

    这个是异步非阻塞的,不会阻塞当前进程,也没有创建线程、协程的开销

chaz6chez

你说的这种业务场景不论是哪种语言,都一样,瓶颈不在webman,也不在语言。

假设你的服务叫A,你需要调用B服务的相关API实现同步阻塞的工作流,这没问题,但现在你说这个过程可能很长,需要5秒,QPS可能达到几千,这没问题;

从每一个请求到每一个请求完毕假设就是5秒,实际上你的服务器需要承受这5秒内累计的请求数量,只要能承受就没问题;
这取决于是否使用http长连接,服务器是否有这样的承载能力,毕竟每台服务器的socket连接是由上限的,太多了可能会出现close wait,或是缓冲区沾满,或是内存超限等情况;

在使用了http长连接的前提下,并且你的服务器内核做了调优,对于socket连接有做优化,workerman的缓冲区设置大一些,php的内存限制调大一些,这些前提下,是没问题的;只要在你累计请求的过程中保证承载量可以达到就OK,剩下的就交给webman的reactor模型就好了;

这里有必要说一下,其他语言也同样这样处理,不论是开线程也好还是开进程也好,都是提高短时间的承载量,但都受限于消费的速度和服务器自身的承载量,如果使用线程/进程,CPU的决定了调度效率;内存/磁盘决定了资源承载量极限;

workerman/webman的reactor模型实际上利用了系统的事件循环,本质上和多线程/多进程没差,外加上workerman/webman是使用了multi-reactor(也就是多进程的),利用多核,处理能力也翻番,丝毫不需要担心。

其实说了那么多,说白了,最后就是一个吞量载量问题,和语言真的没什么关系。

另外,协程如果仅仅用协程,是没办法并发的,协程现在的玩法有这几种:

  1. event-loop + 协程:nodejs python
  2. 单线程 + 协程: swoole
  3. 多线程 + 协程: golang java

协程本质上解决的是event-loop这种异步回调模式会带来很多编写代码和理解代码的不便,从异步开发的发展历史就可以得出这个结论:

回调地狱 -> promises -> aysnc/wait -> 协程

协程开多了不处理,还是会累积在线程上,线程池的数量又有上线,最后还是回到了载量问题上。

  • evilk 2022-06-21

    学习了

  • chaz6chez 2022-06-21

    补充:协程又分有栈协程和无栈协程,PHP自身的yield就是无栈协程,返回的是生成器,需要上层程序自行判断处理;有栈协程的话,每个协程都有对应的栈,对于中断/继续操作就比较方便了。

walkor

目前建议workerman或者webman自定义进程去做。

后面workerman v5+fiber可以让webman做到利用http-client写同步代码发起异步非阻塞请求,参考 https://www.workerman.net/q/8696#answer_13638

  • tanhongbin 2022-06-23

    老大,webman又要升级嘛,这个功能听起来很屌呀

za2883632

这个问题我记得有人回答过..用 php版本的 promise

  • 暂无评论
artisan

起一个非阻塞服务吧,比如swoole或者其他非阻塞的httpclient包,也可结合队列,多进程方式处理。

不考虑 依赖的第三方接口服务的性能的情况下,本身能做的:非阻塞+多进程处理

  • 暂无评论
年代过于久远,无法发表回答
🔝