简体   繁体   中英

PHP Swoole coroutine, async messages not async

I am running a Swoole WebSocket server and I am trying to send messages to end users while a script is running. The problem I am having is that the messages aren't sent asynchronously, and are only sent once the script finishes execution. Which sort of defeats the purpose.

A condensed version of my issue is as follows:

# Recipient IDs
$fd = [75371];
# Message to recipient
$message = "Ping";

# Let's send the message as a coroutine
go(function() use ($fd, $message){
    print "About to send message [{$message}] to recipients ".json_encode($fd).PHP_EOL;
    # Connect to the WebSocket and send the message
    $client = new \Swoole\Coroutine\Http\Client(0.0.0.0, 1234);
    $client->upgrade("/");
    $client->push(json_encode([
        "fd" => $fd,
        "data" => $message
    ]));
    $client->close();
    print "Finally the message was sent".PHP_EOL;
});

# Coroutine script is done, let's continue with our other tasks
print "But wait, I'm gonna be busy with other tasks for 5 seconds first".PHP_EOL;
sleep(5); // This simulates process intensive tasks

# Another coroutine, not related
go(function() {
    print "Gonna be busy again again for another 5 seconds".PHP_EOL;
    co\System::sleep(5);
    print "And we're done".PHP_EOL;
});

I was under the impression that the commands in the coroutine would be executed like a separate thread, by that I mean that the thread wouldn't care what is happening in the parent script thread, because it's doing it's own thing.

That doesn't seem to be the case. Before the message gets sent, the script continues and it's not until we're done with the "tasks" below that the message finally gets sent. The order I was expecting was as follows:

About to send message [Ping] to recipients [75371]
Finally the message was sent
But wait, I'm gonna be busy with other tasks for 5 seconds first
Gonna be busy again again for another 5 seconds
And we're done

But the order I am getting is as follows:

About to send message [Ping] to recipients [75371]
But wait, I'm gonna be busy with other tasks for 5 seconds first
Gonna be busy again again for another 5 seconds
Finally the message was sent
And we're done

What am I getting wrong about coroutines? I have resorted to executing the coroutine as an actual separate PHP thread. Then it works, but that seems to be slightly counterproductive, as I thought coroutines were the thread. Does everything have to be in a coroutine for it to work?

This is the correct output

About to send message [Ping] to recipients [75371]
But wait, I'm gonna be busy with other tasks for 5 seconds first
Finally the message was sent
Gonna be busy again again for another 5 seconds
And we're done

Here an IO is generated that causes the coroutine to switch.

$client = new \Swoole\Coroutine\Http\Client(0.0.0.0, 1234);

so, go to But wait, I'm gonna be busy with other tasks for 5 seconds first

get sleep , switch again to the client above

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM