redis生產者釋出
php artisan make:command Redis/PublishCommand
redis消費者訂閱
php artisan make:command Redis/SubCommand
啟動websocket
php artisan ws
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use App\Facades\MyRedis;
class WebSocket extends Command
{
protected $signature = 'ws';
protected $ws;
public function __construct()
{
parent::__construct();
}
public function handle()
{
//建立websocket伺服器物件,監聽0.0.0.0:9502埠,開啟SSL隧道
$this->ws = new \swoole_websocket_server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
//配置引數
$this->ws ->set([
'daemonize' => false, //守護程式化。
//配置SSL證照和金鑰路徑
'ssl_cert_file' => env('SSL_CERT_FILE'),
'ssl_key_file' => env('SSL_KEY_FILE')
]);
$this->ws->on("open", function (\Swoole\WebSocket\Server $ws, \Swoole\Http\Request $request) {
// dump($request->fd, $request->get, $request->server);
$ws->push($request->fd, "連線成功\n");
});
$this->ws->on("message", function (\Swoole\WebSocket\Server $ws, $frame) {
// dump("訊息: {$frame->data}\n");
$ws->push($frame->fd, "服務端回覆: {$frame->data}\n");
});
//監聽WebSocket主動推送訊息事件
$this->ws->on('request', function ($request, $response) {
$data = $request->post;
//$this->ws->connections 遍歷所有websocket連線使用者的fd,給所有使用者推送
foreach ($this->ws->connections as $fd) {
if ($this->ws->isEstablished($fd)) {
$this->ws->push($fd, json_encode($data));
}
}
});
$this->ws->on("close", function (\Swoole\WebSocket\Server $ws, $fd) {
dump("{$fd}關閉");
});
$this->ws->start();
}
}
- 啟動redis消費者訂閱
php artisan sub:info
<?php
namespace App\Console\Commands\Redis;
use App\Facades\MyRedis;
use Illuminate\Console\Command;
class SubCommand extends Command
{
protected $signature = 'sub:info';
protected $description = 'redis消費者訂閱';
public function __construct()
{
parent::__construct();
}
public function handle()
{
MyRedis::subScribe();
$this->comment('sub successful');
}
}
- h5頁面連線websocket
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>websocket</title>
</head>
<body>
<script>
var wsServer = 'wss://test.自己域名.com:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
</script>
</body>
</html>
- redis生產者釋出
php artisan publish:info
<?php
namespace App\Console\Commands\Redis;
use App\Facades\MyRedis;
use Illuminate\Console\Command;
class PublishCommand extends Command
{
protected $signature = 'publish:info';
protected $description = 'redis生產者釋出';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$data = [
'orders_id' => 1
];
MyRedis::publish($data);
$this->comment('publish successful');
}
}
- 檢視h5 websocket頁面實時返回通知結果
相關Facades程式碼
<?php
namespace App\Facades;
use App\Services\MyRedis\MyRedisService;
use Illuminate\Support\Facades\Facade;
/**
* Class Response
* @package App\Facades
* @method static boolean publish(array $data)
* @method static subScribe()
*/
class MyRedis extends Facade
{
protected static function getFacadeAccessor()
{
return MyRedisService::class;
}
}
<?php
namespace App\Services\MyRedis;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
class MyRedisService
{
protected $subKey = 'ordersRemind';//訂單提醒
//生產者釋出
public function publish(array $data) : bool
{
try {
Redis::publish($this->subKey, json_encode($data));
} catch (\Exception $exception) {
Log::error($exception->getMessage());
return false;
}
return true;
}
//消費者訂閱
public function subScribe()
{
set_time_limit(0);
ini_set('default_socket_timeout', -1);
try {
echo 'start' . "\n";
Redis::subscribe($this->subKey, function ($json, $message) {
$url = "https://test.自己的域名.com:9502";
MyRedisService::httpPost($url, json_decode($json,true));
});
} catch (\Exception $exception) {
Log::error($exception->getMessage());
}
}
public static function httpPost($url, $param){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
curl_exec($curl);
curl_close($curl);
}
}
守護程式
- 藉助 nohup 和 & 配合使用
nohup php artisan sub:info &
- 透過 fg 命令讓程式恢復到普通佔用控制檯的模式
fg
關閉程式
netstat -anp | grep 9502
kill -9 1682674
相關文件
php實現守護程式的兩種常見方式
本作品採用《CC 協議》,轉載必須註明作者和本文連結