- 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