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();
fpm模式的进程一样是阻塞的,它应对的方法无法就是多开进程,相对应的,webman也可以多开,对于这种阻塞严重的,你搞个一两百进程都可以.
“别给生活太多假设”。
干就完了! 相信webman能满足目前99%以上的web项目!
不是假设啊,是我的业务场景就是有这样的,第三方接口经常性的1-60秒才有响应,有时候我并发又能达到1K左右,总不可能去开1K个进程吧?
哦哦,这算是大项目了,没经历过呢!~
如果你的请求不是需要实时响应,可以考虑用定时任务,异步任务,队列之类的来做
是实时响应的~
这种场景适合用workerman来做,配合workerman/http-client
好的 我研究研究
这样也不行,只能多开进程,workerman/http-client是异步请求,无法和安卓ios等前端响应。楼主提的这个问题确实是php的短板,php一般基于进程而不是线程,如果是基于线程的话就很好解决楼主的问题,比如go的协程。
可以的,workerman配合workerman/http-client是非阻塞请求,可以响应安卓 iOS前端
协程只是能支持更多的请求而已,但不会缩短处理请求的时间,对于每个请求而言,该等5秒,还是要等5秒
前端请求服务器,服务器请求第三方接口,请求三方接口时用异步workerman/http-client, 请问你什么时候响应给前端
@evilk 协程可以开很多,因为开销很小,当前协程可以等待三方接口响应后再返回给前端,不像php一样受进程数量限制,协成它确实不会缩短三方接口的请求时间,但是可以同时处理更多前端请求,一个前端请求对应一个协程
@小阳光 示例代码发在下面了。
非常感谢@小阳光 @
six 两位的耐心解答和探讨。
在等待异步回调时难道要休眠挂起当前客户端连接吗?不然等回调时客户端连接已经断开了没法再返回数据了。
第三方接口 定时异步请求回来缓存可以吗
不行的,比如获取验证码,肯定是要实时返回来。
第三方API获取验证码??
其他语言也会有线程/进程数量的限制吧。go的http的是来一个请求创建一个协程。你这种场景是高io,低运算的场景,可以和其他接口分开单独开一个服务器,然后把webman的数量调整高一点,毕竟你的这个场景大多是在等待,把运算型和io型的分开也可以
这种场景适合直接workerman + workerman/http-client 来做,纯异步的,没有所谓的协程消耗,代码类似这样
workerman是可以保存当前链接,提问是webman,有没有办法
这个是异步非阻塞的,不会阻塞当前进程,也没有创建线程、协程的开销
你说的这种业务场景不论是哪种语言,都一样,瓶颈不在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(也就是多进程的),利用多核,处理能力也翻番,丝毫不需要担心。
其实说了那么多,说白了,最后就是一个吞量载量问题,和语言真的没什么关系。
另外,协程如果仅仅用协程,是没办法并发的,协程现在的玩法有这几种:
协程本质上解决的是event-loop这种异步回调模式会带来很多编写代码和理解代码的不便,从异步开发的发展历史就可以得出这个结论:
回调地狱 -> promises -> aysnc/wait -> 协程
协程开多了不处理,还是会累积在线程上,线程池的数量又有上线,最后还是回到了载量问题上。
学习了
补充:协程又分有栈协程和无栈协程,PHP自身的yield就是无栈协程,返回的是生成器,需要上层程序自行判断处理;有栈协程的话,每个协程都有对应的栈,对于中断/继续操作就比较方便了。
目前建议workerman或者webman自定义进程去做。
后面workerman v5+fiber可以让webman做到利用http-client写同步代码发起异步非阻塞请求,参考 https://www.workerman.net/q/8696#answer_13638
老大,webman又要升级嘛,这个功能听起来很屌呀
这个问题我记得有人回答过..用 php版本的 promise
起一个非阻塞服务吧,比如swoole或者其他非阻塞的httpclient包,也可结合队列,多进程方式处理。
不考虑 依赖的第三方接口服务的性能的情况下,本身能做的:非阻塞+多进程处理