- redis生产者发布
php artisan make:command Redis/PublishCommand
- redis消费者订阅
php artisan make:command Redis/SubCommand
- 启动websocket
php artisan ws | |
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 | |
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
<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 | |
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代码
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; | |
} | |
} | |
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 |