多应用+插件架构,代码干净,支持一键云编译,码云点赞13K star,4.8-4.12 预售价格198元 广告
# 发送数据协程调度 [TOC] ## 现状 现在`Server/Client->send`在缓存区已满的情况下,会直接返回`false`,需要借助`onBufferFull`和`onBufferEmpty`这样复杂的事件通知机制才能实现任务的暂停和恢复。 在实现需要大量发送的场景下,现有机制虽然可以实现,但非常复杂。 ## 思路 现在基于协程可以实现一种机制,直接在当前协程内`yield`,等待数据发送完成,缓存区清空时,自动`resume`当前协程,继续`send`数据。 * `Server/Client->send`返回`false`并且错误码为`SW_ERROR_OUTPUT_BUFFER_OVERFLOW`时,不返回`false`到`php`层,而是`yield`挂起当前协程 * `Server/Client`监听`onBufferEmpty`事件,在该事件触发后,缓存区内的数据已被发送完毕,这时`resume`对应的协程 * 协程恢复后,继续调用`Server/Client->send`向缓存区内写入数据,这时因为缓存区已空,发送必然是成功的 ## 实例 #### 改进前 ~~~ for ($i = 0; $i < 100; $i++) { //在缓存区塞满时会直接返回`false` $server->send($fd, $data_2m); } ~~~ #### 改进后 ~~~ for ($i = 0; $i < 100; $i++) { //在缓存区塞满时会 yield 当前协程,发送完成后 resume 继续向下执行 $server->send($fd, $data_2m); } ~~~ ## 选项 此项特性会改变底层的默认行为,因此需要额外的一个参数来开启。 ~~~ $serv->set([ 'send_yield' => true, ]); ~~~ ## 影响范围 * `Swoole\Server::send` * `Swoole\Http\Response::write` * `Swoole\WebSocket\Server::push` * `Swoole\Coroutine\Client::send` * `Swoole\Coroutine\Http\Client::push`