Skip to content

Instantly share code, notes, and snippets.

@bixuehujin
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bixuehujin/d2fb8a396604b070b9cb to your computer and use it in GitHub Desktop.
Save bixuehujin/d2fb8a396604b070b9cb to your computer and use it in GitHub Desktop.

Swoole - Asynchronous & concurrent & distributed networking framework for PHP.

Swoole is a event-based & concurrent framework for internet applications written in C for PHP,

  • event-based

The network layer in swoole is event-based, take full advantage of the underlayer epoll/kqueue implementation. And it is really easy to serve thousands of connections.

  • concurrent

In the request processing part, swoole take the multi-process model, every process works as a worker. All business Logic are executed in workers synchronous.

With the synchronous logic execution, we can easily write large and robust applications, and take advantage of almost all libraries in PHP community.

  • in-memory

Different with the traditional apache/php-fpm stuff, All memory allocated in swoole will not be free'd after request, this can improve preformance a lot.

Why Swoole?

Traditional PHP applications are almost run behinds Apache/Nginx, without much control of the request, this have several limitations:

  1. All memory are free'd after request, all PHP code need be recompile on every request, even with opcache enabled , all opcode still need to be re-executed.
  2. Almost impossible to implement long connection and connection pool techniques.
  3. Implement asynchronous tasks requires 3rd party queue servers, such as rabbitmq and beanstalkd.
  4. Implement realtime application such chatting server requires 3rd party languages, nodejs for example.

This why swoole coming from, swoole extended the use cases of PHP, and brings all these possibilities to PHP world. By using swoole, you can build enhanced web applications with more control, you can build realtime chatting server more easily and so forth.

Requirements

  • PHP 5.3+
  • Linux, OS X and basic Windows support (Thanks to cygwin)

Installation

  1. Install via pecl

    pecl install swoole
    
  2. Install from source

    sudo apt-get install php5-dev
    git clone https://github.com/swoole/swoole-src.git
    cd swoole-src
    phpize
    ./configure
    make && make install
    

Introducation

Swoole includes components for different purposes: Server, Task Worker, Timer, Event and Async IO. With these components, swoole brings different functionalities to us.

Server

This is the most important part in swoole, it provides necessary infrastructure for build server applications. With swoole server, you can build web server, chat messaging server, game server and almost everything what you want.

The following example demonstrated a simple echo server.

// create a server instance
$serv = new swoole_server("127.0.0.1", 9501); 

// attach handler for connect event, once client connected to server the registered handler will be executed
$serv->on('connect', function ($serv, $fd){  
    echo "Client:Connect.\n";
});

// attach handler for receive event, every piece of data received by server, the registered handler will be
// executed. And all custom protocol implementation should be located there.
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    $serv->send($fd, $data);
});

$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

// start our server, listen on port and ready to accept connections
$serv->start();

Try to extend your server and implement what you want!

Task Worker

Swoole brings two types of worker for you, server worker and task worker. Server worker are for request handling, as demonstrated above. Task worker are for task executing, with task workers, we can make our task executed asynchronous without blocking the server workers.

Task worker are mainly used for time-consuming tasks, such as sending password recovery email. And ensure the main request returns as soon as possible.

The following example demonstrated a simple server with task support.

$serv = new swoole_server("127.0.0.1", 9502);

// sets server configuration, we let task_worker_num config greater than 0 to enable task worker
$serv->set(array('task_worker_num' => 4));

// attach handler for receive event, which explained above.
$serv->on('receive', function($serv, $fd, $from_id, $data) {
    // we dispath a task to task workers by invoke the task() method of $serv
    // this method returns a task id as the identity of ths task
    $task_id = $serv->task($data);
    echo "Dispath AsyncTask: id=$task_id\n";
});

// attach handler for task event, the handler will be executed in task workers.
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
    // handle the task, do what you want with $data
    echo "New AsyncTask[id=$task_id]".PHP_EOL;

    // after the task task is handled, we can tell 
    $serv->finish("$data -> OK");
});

// attach handler for finish event, the handler will be executed in server workers, the same worker 
// that task dispath from.
$serv->on('finish', function ($serv, $task_id, $data) {
    echo "AsyncTask[$task_id] Finish: $data".PHP_EOL;
});


$serv->start();

As well, swoole has support for synchronous tasks. By using synchronous task, just simply replace $serv->task($data) with $serv->taskwait($data). Different with task(), taskwait() will wait task to complete and returns its response.

Timer

Swoole has build in millisecond timer support. By using timer, it is easily to get a block of code executed periodicly, really useful for managing interval tasks.

To demonstrate how timer works, there is small example:

$serv->on('timer', function ($interval) {
    switch($interval) {
        case 10000: // timer1
            // code for timer1
        break;

        case 20000: // timer2
            // code for timer2
        break;
    }
});
$serv->on('start', function ($serv) {
     $serv->addtimer(10000);
     $serv->addtimer(20000);
});

In the example above, we first set the timer event handler for swoole_server to enable timer support. Then, we add two timer by call bool swoole_server::addtimer($interval) once server started. To handle multiple timers, we switch the $interval in registered handler and do what we want to do.

Event

The I/O layer of swoole is event-based, it is very convenient to add our own file descriptor to the main eventloop of swoole. With event support, we can also build full asynchronous applications with swoole.

To use event in swoole, we can use swoole_event_set() to register event handler to sepecified file descriptor, once registered descriptor become readable or writble, our registered handler will be invoked. As well, we can using bool swoole_event_del(int $fd); to remove registered file descriptor from eventloop.

The following are prototypes for the related functions:

bool swoole_event_set($fd, mixed $read_callback, mixed $write_callback, int $flag);
bool swoole_event_del($fd);

The $fid parameter can be one of the following types:

  • unix file descriptor
  • stream resource created by stream_socket_client()/fsockopen()
  • sockets resources created by socket_create() in sockets extension (require compile swoole with --enable-sockets support)

The $read_callback and $write_callback are callbacks for corresponding read/write event.

The $flag is a mask to indicate what type of events we should get notified, can be SWOOLE_EVENT_READ, SWOOLE_EVENT_WRITE or SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE

Async IO

The Async IO of swoole provides the ability to read/write file and lookup dns records in an asynchronous way. The following are signature for these functions:

swoole_async_readfile(string $filename, mixed $callback);
swoole_async_writefile('test.log', $file_content, mixed $callback);
bool swoole_async_read(string $filename, mixed $callback, int $trunk_size = 8192);
bool swoole_async_write(string $filename, string $content, int $offset = -1, mixed $callback = NULL);
swoole_async_dns_lookup(string $domain, function($host, $ip){});

Refer API Reference for more detail information of these functions.

Client

Swoole also provides Client component to build tcp/dup clients in both an asynchronous and synchronous way. Swoole use class swoole_client to expose all its functionalities.

The following methods are avaliable in swoole_client:

swoole_client::__construct(int $sock_type, int $is_sync = SWOOLE_SOCK_SYNC, string $key);
int swoole_client::on(string $event, mixed $callback);
bool swoole_client::connect(string $host, int $port, float $timeout = 0.1, int $flag = 0)
bool swoole_client::isConnected();
int swoole_client::send(string $data);
bool swoole_client::sendfile(string $filename)
string swoole_client::recv(int $size = 65535, bool $waitall = 0);
bool swoole_client::close();

Refer API Reference for more detail information of these functions.

API Reference

License

Apache License Version 2.0 see http://www.apache.org/licenses/LICENSE-2.0.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment