Рубрики
Uncategorized

От введения к практике свула (I): установка исходного кода php7 и swoole, игра с механизмом сетевой связи, сценарий асинхронного неблокирующего ввода-вывода

Автор оригинала: David Wong.

1.1 установка исходного кода php7

1.1.1 получение исходного кода и установка

Получите исходный код php 7: www.php.net

Tar - xzvf... Unzip command

. / configure -- prefix = / home / study / PHP install to a path, install GCC in advance, etc
Make compile
Make install

Файл выполнения исходного кода размещен в: мусорное ведро Каталог

PHP - M ා check the extension of PHP installation

1.1.2 упростить выполнение команд PHP

псевдоним Путь к команде для команды

vim /.bash_profile
Alias PHP = / home / work / soft / PHP / bin / PHP
Source /. Bash? Profile? Note

исходное имя файла Эффект: В настоящее время баш Чтение и выполнение в среде Имя файла Ввод команды. Используется для повторного выполнения только что измененного документа инициализации, такого как .bash_profile и .профиль Подождите Примечание: Эта команда обычно использует команду” . “Заменить” Например: источник/и т.д./профиль И ./etc/профиль Это эквивалентно.

PHP - I | grep php.ini ා find the PHP configuration file

1.2 компиляция и установка исходного кода swool

Получить исходный код swole: Получить исходный код swole:

phpize Это для расширения php Модульный, через phpize Можно построить php Подключаемый модуль не был решен настройка проблема

/Usr / local / PHP / bin / phpize ා execute this line of code in the directory to be executed
./configure --with-php-config=/usr/local/php/bin/php-config
 make
 make install

Наконец, вы можете PHP В каталоге расширений swoole.so увеличить файл

1.3 комбинация двух мечей, php7 поддерживает swoole

В php.ini Добавить в файл: extension=swoole.so Чтобы узнать, было ли оно успешно добавлено: php-m

В swoole/примеры/сервер Более низкое выполнение php echo.php Проверьте, нужно ли выполнять порт: 9501

netstat -anp|grep 9501

2.1 Служба TCP и клиент TCP

2.1.1 Служба TCP

Официальный веб-сайт Swoole документ: создание TCP – сервера | создание UDP-сервера

//Create a server object and listen to port 127.0.0.1:9501
$serv = new swoole_server("127.0.0.1", 9501);
//The swoole server - > set function is used to set the parameters of the swoole server runtime
$serv->set([
    'worker_num' = > 6, // number of worker processes, 1-4 times of CPU
    'max_request' => 10000,
]);
/**
 *Listen for connection entry events
 *$FD unique identification of client connection
 *$reactor? ID thread ID
 */
$serv->on('connect', function ($serv, $fd, $reactor_id) {
    echo "Client: {$reactor_id} - {$fd}-Connect.\n";
});
/**
 *Listening for data receiving events
 * $reactor_id = $from_id
 */
$serv->on('receive', function ($serv, $fd, $reactor_id, $data) {
    $serv->send($fd, "Server: {$reactor_id} - {$fd}".$data);
});
//Listen for connection closing events
$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});
//Start server
$serv->start();

тест tcp Серверный метод:

  1. netstat -anp | grep 9501
  2. принять telnet Для входа на удаленный хост: telnet 127.0.0.1 9501
  3. tcp Клиентский скрипт

Просмотреть текущий рабочий Номер процесса: ps -af | grep tcp_server.php

Чаевые: Для обеспечения целостности выполнения программы при изменении tcp Лучше установить плавный перезапуск после серверного скрипта рабочий процесс Плавно перезапустите рабочий процесс

2.1.2 Клиент TCP

Гигантская яма облачного сервера Alibaba-порт не открыт для внешнего мира!!! Если websocket не удается подключиться к серверу, отображаются заголовки рекомендаций

connect("127.0.0.1", 9501)) {
    Echo "connection failed";
    exit;
}

//PHP cli constant
Fwrite (stdout, "please enter message:");
$msg = trim(fgets(STDIN));

//Send message to TCP server server
$client->send($msg);

//Accept data from server
$result = $client->recv();
echo $result;

2.2 Служба HTTP(обычно используемая)

$http = new swoole_http_server("0.0.0.0", 8811);

//Add test one: get parameters and print them out
//$http->on('request', function ($request, $response) {
//    $response->cookie("singwa",'xsssss', time() + 1800);
//    $response->end('sss'.json_encode($request->get));
//});
/**
 * https://wiki.swoole.com/wiki/page/783.html
 *Configure the root directory of the static file, which is used with enable? Static? Handler.
 *When document root is set and enable static handler is set to true,
 *When the underlying layer receives the HTTP request, it will first determine whether the file exists under the document root path,
 *If it exists, the content of the file will be sent directly to the client, and the onrequest callback will not be triggered.
 */
$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/home/work/hdtocs/swoole_mooc/data",
    ]
);
$http->on('request', function($request, $response) {
    //print_r($request->get);
    $content = [
        'date:' => date("Ymd H:i:s"),
        'get:' => $request->get,
        'post:' => $request->post,
        'header:' => $request->header,
    ];
    swoole_async_writefile(__DIR__."/access.log", json_encode($content).PHP_EOL, function($filename){
        // todo
    }, FILE_APPEND);
    $response->cookie("singwa", "xsssss", time() + 1800);
    $response->end("sss". json_encode($request->get));
});

$http->start();

2.3 сервис websocket(ключ)

2.3.1 общий обзор

Веб-карман Протокол основан на TCP Новый сетевой протокол. Он реализует полный дуплекс браузера и сервера( полный дуплекс Связь — Разрешить серверу активно отправлять информацию клиенту

Зачем нужен websocket

  • Дефекты: HTTP Связь для может быть инициирована только клиентом

Особенности Websocket

  1. Настройка в TCP Выше соглашения
  2. Низкая стоимость производительности, высокая эффективность связи
  3. Клиент может взаимодействовать с любым сервером
  4. Идентификатор протокола ws всиво
  5. Постоянный сетевой протокол связи

2.3.2 реализация кейса

2.3.2.1 реализация сервера

1. Ориентированный на процесс: procedure_ws_server.php

$server = new swoole_websocket_server("0.0.0.0", 9912);
//Configure static file root, optional
$server->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/home/wwwroot/www.lingyuan88.com/public/swoole/data",
    ]
);
//Listen for websocket connection open event
$server->on('open', 'onOpen');
function onOpen($server, $request) {
    print_r($request->fd);
}
//Listen for WS message events
$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd, "singwa-push-secesss");
});
$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

2. Оптимизация сервиса Websocket, базовая библиотека классов объектно-ориентированный: Оптимизация сервиса Websocket, базовая библиотека классов

class Ws {

    CONST HOST = "0.0.0.0";
    CONST PORT = 9912;
    public $ws = null;
    public function __construct() {
        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        //Configure static file root, optional
        $this->ws->set(
            [
                'enable_static_handler' => true,
                'document_root' => "/home/wwwroot/www.lingyuan88.com/public/swoole/data",
            ]
        );
        $this->ws->on("open", [$this, 'onOpen']);
        $this->ws->on("message", [$this, 'onMessage']);
        $this->ws->on("close", [$this, 'onClose']);

        $this->ws->start();
    }
    /**
     *Listen for WS connection events
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request) {
        print_r($request->fd);
    }
    /**
     *Listen for WS message events
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame) {
        echo "ser-push-message:{$frame->data}\n";
        $ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));
    }
    /**
     * close
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd) {
        echo "clientid:{$fd}\n";
    }
}
$obj = new Ws();

2.3.2.2 реализация клиента

ws_client.html





  
  


Singwa swoole WS test

2.3.2.3 тестирование

1. пропуск WebSocket Проверка статического каталога файлов

2. пропуск HTTP Тестирование сервиса

2.4 использование асинхронных задач(ключ)

Сценарии использования

  • Выполнение трудоемких операций (отправка широковещательной почты и т.д.)

Будьте осторожны:

  • После того, как асинхронная задача будет доставлена , программа Продолжит , не ждите завершения задачи, прежде чем продолжить выполнение вниз
class Ws {
    CONST HOST = "0.0.0.0";
    CONST PORT = 9912;
    public $ws = null;
    public function __construct() {
        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        $this->ws->set(
            [
                'worker_num' => 2,
                'task_worker_num' => 2,
            ]
        );
        //Register event callback function of server
        $this->ws->on("open", [$this, 'onOpen']);
        $this->ws->on("message", [$this, 'onMessage']);
        $this->ws->on("task", [$this, 'onTask']);
        $this->ws->on("finish", [$this, 'onFinish']);
        $this->ws->on("close", [$this, 'onClose']);
        $this->ws->start();
    }
    /**
     *Listen for WS connection events
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request) {
        var_dump($request->fd);
    }
    /**
     *Listen for WS message events
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame) {
        echo "ser-push-message:{$frame->data}\n";
        // todo 10s
        $data = [
            'task' => 1,
            'fd' => $frame->fd,
        ];
        //Deliver asynchronous tasks
        //Note: the program will continue to execute downward, and will not wait for the task to finish executing before continuing to execute downward
        $ws->task($data);
        //The client will receive the following information immediately
        $ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));
    }
    /**
     * @param $serv
     * @param $taskId
     * @param $workerId
     * @param $data
     * @return string
     */
    public function onTask($serv, $taskId, $workerId, $data) {
        print_r($data);
        //Time consuming scenario 10s
        sleep(10);
        Return "on task finish"; // tell worker and return $data to onfinish
    }
    /**
     * @param $serv
     * @param $taskId
     * @param $data
     */
    public function onFinish($serv, $taskId, $data) {
        echo "taskId:{$taskId}\n";
        echo "finish-data-sucess:{$data}\n";
    }
    /**
     * close
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd) {
        echo "clientid:{$fd}\n";
    }
}
$obj = new Ws();

3.1 асинхронные, блокирующие и модели ввода-вывода(обязательно поймите.)

3.1.1 синхронный и асинхронный

Озабоченность вызывает Уведомление о сообщении Механизм;

Синхронизация: После выполнения вызова Немедленного возврата нет , но после возврата будет возвращен окончательный результат;

Асинхронный: После выполнения вызова/| Вызываемая сторона Верните сообщение сейчас , Но это не конечный результат 。 Вызывающий абонент информирует вызывающего абонента через статус, механизм уведомления и т.д. Или обрабатывает результат с помощью функции обратного вызова;

3.1.2 блочные и неблочные

Беспокойство вызывает Состояние, в котором вызывающий абонент ожидает, что вызываемый абонент вернет результат вызова.

Препятствие: Вызывающий абонент приостанавливается до тех пор , пока не будет возвращен результат вызова , вызывающий абонент может продолжить только после получения возвращенного результата.

Не блокируется: Вызывающий абонент не будет приостановлен до тех пор, пока не будет возвращен результат;

3.1.3 Модель ввода-вывода

Blocking IO: blocking IO 
Nonblocking IO: non blocking IO
Multiplexing IO: multiplexing IO 
Signal driven IO: event driven IO 
Asynchronous IO: asynchronous IO

Реальное исполнение ИО Этапы процесса: Данные памяти ядра копирование в Память процесса в

3.2 асинхронный миллисекундный таймер свула

асинхронный Высокоточный таймер с детализацией миллисекунда

//Trigger every 2000ms
swoole_timer_tick(2000, function ($timer_id) {
    echo "tick-2000ms\n";
});

//Execute this function after 3000ms
swoole_timer_after(3000, function () {
    echo "after 3000ms.\n";
});

3.3 ввод-вывод асинхронной файловой системы

Официальный веб-сайт Swoole документ: асинхронная файловая система ввода-вывода

3.3.1 асинхронное чтение

/**
 *Read file
 * __DIR__
 *If the file does not exist, false will be returned
 *File opened successfully returns true immediately
 *After reading the data, the specified callback function will be called back.
 */
//Function style
$result = swoole_async_readfile(__DIR__."/1.txt", function($filename, $fileContent) {
    echo "filename:".$filename.PHP_EOL;  // \n \r\n
    echo "content:".$fileContent.PHP_EOL;
});
//Namespace style
$result = Swoole\Async::readfile(__DIR__."/1.txt", function($filename, $fileContent) {
    echo "filename:".$filename.PHP_EOL;  // \n \r\n
    echo "content:".$fileContent.PHP_EOL;
});
var_dump($result);
echo "start".PHP_EOL;

3.3.2 асинхронная запись (например, в журнал)

$http->on('request', function($request, $response) {
    $content = [
        'date:' => date("Ymd H:i:s"),
        'get:' => $request->get,
        'post:' => $request->post,
        'header:' => $request->header,
    ];
    swoole_async_writefile(__DIR__."/access.log", json_encode($content).PHP_EOL, function($filename){
        // todo
    }, FILE_APPEND);
    $response->end("response:". json_encode($request->get));
});

3.4 подробная информация об асинхронном MySQL

class AsyncMySql {
    /**
     * @var string
     */
    public $dbSource = "";
    /**
     *MySQL configuration
     * @var array
     */
    public $dbConfig = [];
    public function __construct() {
        //new swoole_mysql;
        $this->dbSource = new Swoole\Mysql;

        $this->dbConfig = [
            'host' => '127.0.0.1',
            'port' => 3306,
            'user' => 'root',
            'password' => 'test',
            'database' => 'test',
            'charset' => 'utf8',
        ];
    }
    public function update() {}
    public function add() {}
    /**
     *MySQL execution logic
     * @param $id
     * @param $username
     * @return bool
     */
    public function execute($id, $username) {
        $this->dbSource->connect($this->dbConfig, function($db, $result) use($id, $username)  {
            echo "mysql-connect".PHP_EOL;
            if($result === false) {
                var_dump($db->connect_error);
                // todo
            }
            $sql = "select * from cmf_user where id=1";
            //$sql = "update test set `username` = '".$username."' where id=".$id;
            // insert into
            // query (add select update delete)
            $db->query($sql, function($db, $result){
                //Select = > result returns the result content of the query
                if($result === false) {
                    // todo
                    var_dump($db->error);
                }elseif($result === true) {// add update delete
                    // todo
                    var_dump($db->affected_rows);
                }else {
                    print_r($result);
                }
                $db->close();
            });

        });
        return true;
    }
}
$obj = new AsyncMySql();
$flag = $obj->execute(1, 'singwa-111112');
var_dump($flag).PHP_EOL;
echo "start".PHP_EOL;

3.5 асинхронные повторы

3.5.1 подготовка окружающей среды

Предварительные условия для использования redis в swoole

  • редис сервис
  • hiredis библиотека
  • Скомпилировать swoole Нужно присоединиться -включить-асинхронность-redis

Скомпилировать и установить хиредис

Использовать Redis Клиент, требуется установка hiredis Библиотека, Загрузка hiredis После исходного кода, выполнять

make -j
sudo make install
sudo ldconfig

Адрес для загрузки Hiredis

Включить асинхронный клиент redis

Скомпилировать свул Когда настроить Добавить в инструкцию --включить-асинхронный-повтор

[[email protected]z8wdxsujiec2oz swoole]# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-async-redis
make clean
make -j
sudo make install

Просмотр PHP Из свула Расширение: php -m Посмотреть нанятые Следует ли успешно скомпилировать и установить: php --ri swoole

3.5.2 проверка кода

$redisClient = new swoole_redis;// Swoole\Redis
$redisClient->connect('127.0.0.1', 6379, function(swoole_redis $redisClient, $result) {
    echo "connect".PHP_EOL;
    var_dump($result);

    //Synchronize redis (New redis()) - > set ('key ', 2);
    /*$redisClient->set('singwa_1', time(), function(swoole_redis $redisClient, $result) {
        var_dump($result);
    });*/

    /*$redisClient->get('singwa_1', function(swoole_redis $redisClient, $result) {
        var_dump($result);
        $redisClient->close();
    });*/
    $redisClient->keys('*gw*', function(swoole_redis $redisClient, $result) {
        var_dump($result);
        $redisClient->close();
    });

});
echo "start".PHP_EOL;

Следующая статья:Переход от введения к практике (2): процесс, память и сотрудничество , swoole отлично поддерживает thinkphp5, реализацию асинхронного механизма распределения задач

Справочное руководство: Хань Тяньфэн рекомендует внедрить swoole для создания живой платформы для высокопроизводительных мероприятий

Оригинал: “https://developpaper.com/from-introduction-to-practice-of-swoole-i-php7-swoole-source-code-installation-playing-with-network-communication-engine-asynchronous-non-blocking-io-scenario/”