A用户发起http请求,服务器发起ws获取客户端B数据,收到B数据后回复给A

Mruos

问题描述

1、A用户发起http请求,
2、http服务端,通过调用让Gateway的ws服务端向ws客户端B发送请求,
3、ws客户端B收到数据后,发送回复给ws服务端,
4、ws服务端收到数据后,让http服务器响应A的http请求

请问怎么实现,ws过程是异步的,好像A用户的http请求处理过程必须有等待,类似sleep来等待ws通讯完,才能拿到数据响应给A。等待就堵塞,不好,还有什么好的方案吗?

想到的方案

A用户也发起ws数据,这样大家都异步了,有个标识符,来回传就行了;还有其他出路吗?

有没有什么方案、插件、工具,可以让A用户的请求挂起不堵塞,收到ws数据后,在响应A的http请求

801 2 1
2个回答

Dalong

等老大的1.5版本出来目测就能解决你的问题。

  • 暂无评论
tianyiw

Revolt很简单,我刚改造了我的代码。。。下面的代码是从我项目里精简复制出来的,需要自己整理一下,无法直接运行。。。仅供参考


// 将事件循环换成Revolt
\Workerman\Worker::$eventLoopClass = \Workerman\Events\Revolt::class;

// 代码不完整,仅供参考,下面的代码需放入onWorkerStart()中运行

$listens = [];

// websocket服务端收到信息后,进行[$command, $hash, $data] = unserialize($data)反序列化,
// 然后回复消息时$connection->send(serialize([$hash, $result]))
// 保证收到消息、回复消息时$hash值一致

$connection = new AsyncTcpConnection('ws://127.0.0.1:8877');
$connection->onMessage = function (TcpConnection $connection, $data) use ($listens) {
    [$hash, $data] = unserialize($data);
    if (!isset($listens[$hash])) {
        return;
    }

    [$timerid, $suspension] = $listens[$hash];
    unset($listens[$hash]);
    \Workerman\Timer::del($timerid);
    $suspension->resume($data);
};
$connection->connect();

function post(string $command, array $data, int $timeout = 10): mixed
{
    global $listens, $connection;

    $suspension = \Revolt\EventLoop::getSuspension();
    $hash = intval(microtime(true) * 1000);

    $timerid = \Workerman\Timer::add(
        $timeout,
        function () use ($hash, $listens, $suspension) {
            if (isset($listens[$hash])) {
                $suspension->throw(new \Exception('超时了'));
            }
        },
        [],
        false
    );

    $listens[$hash] = [$timerid, $suspension];

    $connection->send(serialize([
        $command,
        $hash,
        $data,
    ]));

    return $suspension->suspend();
}

// 执行
$value = $this->post('get', ['key'=>'good']);
var_dump($value);
年代过于久远,无法发表回答
🔝