Example of implementing real-time asynchronous task queue with PHP extended swoole

Time:2020-2-24

The example of this paper describes how to extend swoole in PHP to realize real-time asynchronous task queue. To share with you for your reference, as follows:

If want to send 100 mail, for circulates 100 times, the user rises directly, what break a website!

But in fact, we are likely to have more than 10000 emails. How to deal with this delay?

The answer is asynchrony. Encapsulate the “send mail” operation, and then perform 10000 times asynchronously in the background. In this way, when a user submits a web page, the time he waits is only the time to “push the email task request into the queue”. And our backstage service will run where users can’t see it.

In the implementation of “asynchronous queue”, some people use MySQL table or redis to store the messages to be sent, and then read the list to be sent regularly every minute, and then process it. This is the timed asynchronous task queue. However, the currently submitted tasks can only be executed one minute later, which is not fast in some real-time application scenarios. Some scenarios require that the task be executed as soon as it is submitted, but the user does not need to wait for the returned result.

In this paper, we will discuss the implementation of real-time asynchronous task queue with PHP extended swoole.

Server side

Create a new server.php in the directory where you plan to place the script (you can also create it yourself). The code is as follows

<?php
class Server
{
  private $serv;
  public function __construct()
  {
    $this->serv = new swoole_server("0.0.0.0", 9501);
    $this->serv->set(array(
      'worker_num' = > 1, // usually set to 1-4 times the number of CPU in the server
      'daemonize' = > 1, // executed as a Daemons
      'max_request' => 10000,
      'dispatch_mode' => 2,
      'task \ worker \ num' = > 8, // number of task processes
      "Task? IPC? Mode" = > 3, // use message queuing to communicate and set to scramble mode
      //"Log file" = > log / taskqueueu. Log ", // log
    ));
    $this->serv->on('Receive', array($this, 'onReceive'));
    // bind callback
    $this->serv->on('Task', array($this, 'onTask'));
    $this->serv->on('Finish', array($this, 'onFinish'));
    $this->serv->start();
  }
  public function onReceive(swoole_server $serv, $fd, $from_id, $data)
  {
    //echo "Get Message From Client {$fd}:{$data}\n";
    // send a task to task worker.
    $serv->task($data);
  }
  public function onTask($serv, $task_id, $from_id, $data)
  {
    $array = json_decode($data, true);
    if ($array['url']) {
      return $this->httpGet($array['url'], $array['param']);
    }
  }
  public function onFinish($serv, $task_id, $data)
  {
    //echo "Task {$task_id} finish\n";
    //echo "Result: {$data}\n";
  }
  protected function httpGet($url, $data)
  {
    if ($data) {
      $url .= '?' . http_build_query($data);
    }
    $curlobj = curl init(); // initialize curl,
    Curl_setopt ($curlobj, curlopt_url, $URL); // set URL
    Curl_setopt ($curlobj, curlopt_returntransfer, 1); // returns the result of curl_exec
    curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, FALSE);
    Curl_setopt ($curlobj, curlopt_header, 0); // output return header information
    $response = curl_exec ($curlobj); // execute
    Curl_close ($curlobj); // close the session
    return $response;
  }
}
$server = new Server();

Client

After starting the service, let’s see how to invoke the service. Create a new test file client_test.php


<?php
class Client
{
  private $client;
  public function __construct()
  {
    $this->client = new swoole_client(SWOOLE_SOCK_TCP);
  }
  public function connect()
  {
    if (!$this->client->connect("127.0.0.1", 9501, 1)) {
      throw new Exception(sprintf('Swoole Error: %s', $this->client->errCode));
    }
  }
  public function send($data)
  {
    if ($this->client->isConnected()) {
      if (!is_string($data)) {
        $data = json_encode($data);
      }
      return $this->client->send($data);
    } else {
      throw new Exception('Swoole Server does not connected.');
    }
  }
  public function close()
  {
    $this->client->close();
  }
}
$data = array(
  "url" => "http://192.168.10.19/send_mail",
  "param" => array(
    "username" => 'test',
    "password" => 'test'
  )
);
$client = new Client();
$client->connect();
if ($client->send($data)) {
  echo 'success';
} else {
  echo 'fail';
}
$client->close();

In the above code, the URL is the address of the task, and param is the required parameter.

Save the code, execute client_test.php in the command line or browser, and the asynchronous task queue is realized. The URL you fill in will be executed asynchronously by HTTP get after each asynchronous task is submitted.

For more information about PHP, you can see the following topics: PHP extended development tutorial, PHP network programming skills summary, PHP curl usage summary, PHP array operation skills Collection, PHP data structure and algorithm tutorial, PHP programming algorithm summary and PHP string Usage Summary

I hope that this article will be helpful for PHP programming.

Recommended Today

Laravel service container must know

The article was forwarded from the professional laravel developer community. Original link: https://learnku.com/laravel/t To learn how to build an application with laravel is not only to learn how to use different classes and components in the framework, but also to remember allartisanCommand or all helper functions (we have Google). Learning to code with laravel is […]