安装
wget https://github.com/swoole/swoole-src/archive/v1.9.14.tar.gz
tar -zxvf v1.9.14.tar.gz
cd swoole-src-1.9.14/
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
sudo make install
vi /usr/local/php/etc/php.ini
extension=swoole
使用
服务sever.php
<?php
class Server
{
private $ip = '127.0.0.1';
private $port = '9901';
private $manage_port = '9909';
public function __construct($cmd) {
switch ($cmd){
case 'start':
$this->start();
break;
default:
$this->manager($cmd);
}
}
private function start(){
$server = new swoole_server($this->ip, $this->port);
$server->set(array(
'worker_num' => 4,
'task_worker_num' => 12,
'max_conn' => 1000,
'max_request' => 10000,
'debug_mode' => 1,
'open_eof_check' => true, //打开EOF检测
'package_eof' => "\r\n", //设置EOF
'backlog' => 128,
'daemonize' => false, //Is start Daemon process
'log_file' => 'swoole.log',
));
//增加监听的端口
$server->addlistener($this->ip, $this->manage_port, SWOOLE_SOCK_UDP);
$server->on('Start', array($this, 'onStart'));
$server->on('WorkerStart', array($this, 'onWorkerStart'));
$server->on('Receive', array($this, 'onReceive'));
$server->on('Task', array($this, 'onTask'));
$server->on('Finish', array($this, 'onFinish'));
$server->on('Packet', array($this, 'onPacket'));
$server->start();
}
/**
* 内网管理
*
* @param $cmd
* @throws Exception
*/
private function manager($cmd){
if(!in_array($cmd, array('reload'))) {
exit('错误命令,仅支持start,stop,reload');
}
$client = new swoole_client(SWOOLE_SOCK_UDP, SWOOLE_SOCK_SYNC);
$ret = $client->connect($this->ip, $this->manage_port, 0.5);
if(!$ret) {
throw new Exception($client->errCode);
}
$client->send("{$cmd}\r\n");
$ret = $client->recv();
echo $ret . PHP_EOL;
}
public function onStart($server) {
echo 'Server Start: ' . date('m-d H:i:s') . ' 主进程Pid:' . $server->master_pid . " 管理进程Pid:" . $server->manager_pid . PHP_EOL;
}
public function onWorkerStart($server) {
if(function_exists('opcache_reset')){
opcache_reset();
}
echo '运行onWorkerStart'.PHP_EOL;
require_once 'reload.php';
}
public function onConnect($server, $fd){
echo "Connected" . PHP_EOL;
}
public function onReceive($server, $fd, $from_id, $data){
$server->task($data);
}
public function onClose($server, $fd, $from_id ) {
echo "Client {$fd} close connection" . PHP_EOL;
}
public function onTask($server, $task_id, $from_id, $data) {
$dataList = explode("\r\n", $data);
foreach ($dataList as $row) {
if(!empty($row)) {
if(empty($row)) {
continue;
}
$handler = new a();
$handler->handle($row);
}
}
unset($row, $dataList, $handler);
$server->finish("ok");
}
public function onFinish($server, $task_id, $data) {
echo $task_id." complete!".$data . PHP_EOL;
}
/**
* 监听UDP数据包
*/
public function onPacket($server, $data, $client_info) {
$fd = $client_info['address'];
$port = $client_info['port'];
$dataList = explode("\r\n", $data);
foreach ($dataList as $row) {
if(!empty($row)) {
switch($row) {
case 'reload':
echo '服务器Worker重启成功' . PHP_EOL;
$server->reload();
$server->sendto($fd, $port,'服务器Worker重启成功');
break;
case 'stop':
echo '服务器Worker关闭成功' . PHP_EOL;
$server->stop();
$server->sendto($fd, $port,'服务器Worker关闭成功');
break;
default:
$server->sendto($fd, $port,'命令错误');
break;
}
}
}
unset($row,$dataList, $fd, $port);
}
}
global $argv;
$startFile = $argv[0];
if(!isset($argv[1])) {
exit("使用方法: php {$startFile} {start|stop|reload}\n");
}
new Server($argv[1]);
处理task的文件,可以热部署reload.php
<?php
class a{
public function handle($data){
echo 'handing';
}
}
客户端
/**
* 设置waring等信息
*/
function warning_log($errno, $errstr, $errfile, $errline){
file_put_contents('error.log',date("Y-m-d H:i:s")."#".$errno."#".$errstr."#".$errfile."#".$errline."\n",FILE_APPEND);
}
set_error_handler("warning_log",E_ALL);
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
if (!$client->connect('127.0.0.1', 9901, 100))
{
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("message\r\n");
$client->close();
启动
php server.php start
关闭
php server.php stop
热更新reload.php代码
php server.php reload
ps:
1如果开启opcache请在onWorkerStart中添加,否则会导致热更新失败
opcache_reset();
2. 上述演示代码中reload.php中加载其他的php文件,可以不需要发送reload命令就可以自动更新。