layout | title | subtitle | date | author | tags |
---|---|---|---|---|---|
post
|
Laravel 广播
|
使用 redis + socket.io 等进行 websocket 通信
|
2019-03-30
|
cj
|
laravel redis websocket laravel-echo-server socket.io laravel-echo
|
Laravel5.7 广播
环境为 homestead/ubuntu18.04/laravel5.7/php7.2
。。。
本想用 pusher
,他官网访问极慢,换 redis
。。。
大致步骤
-
编辑
config/app.php
,取消对BroadcastServiceProvider
的注释 -
编辑
.env
,修改BROADCAST_DRIVER=redis
-
yarn global add laravel-echo-server --prefix /usr/local --no-bin-links
-
laravel-echo-server init
除了第一项
development mode
选yes
其他一路回车默认 -
创建
event
,app/Events/EventMachineOperated.php
,真实项目,摘录一些关键代码class EventMachineOperated implements ShouldBroadcast { public $message; // public 的成员都将广播出去 public function broadcastOn() { return new Channel('machineStatus'); } }
-
编辑
routes/channels.php
,对这个频道暂时不做权限控制Broadcast::channel('machineStatus', function () { return true; });
-
yarn add socket.io-client
-
yarn add laravel-echo
-
编辑
/resources/assets/js/bootstrap.js
,最底下取消注释稍作修改import Echo from "laravel-echo" window.io = require('socket.io-client'); window.Echo = new Echo({ broadcaster: 'socket.io', host: window.location.hostname + ':6001' });
-
编辑
resources/views/pages/test_websocket.blade.php
<!DOCTYPE html> <html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>Websocket Test</title> <!-- Styles --> <link href="{{ mix('css/app.css') }}" rel="stylesheet"> </head> <body> <div id="app"> <div class="content"> <div class="m-b-md"> Websocket Test </div> </div> </div> <!-- receive notifications --> <script src="http://\{\{ Request::getHost() \}\}:6001/socket.io/socket.io.js"></script> <script src="{{ mix('js/app.js') }}"></script> <script> //Pusher.logToConsole = true; Echo.channel('machineStatus') .listen('EventMachineOperated', (e) => { console.log('triggered'); console.log(e); }); </script> <!-- receive notifications --> </body> </html>
-
npm run dev
-
php artisan horizon
-
laravel-echo-server start
-
创建了个测试
api
,使用postman
调用接口后触发EventMachineOperated
事件 -
创建相关路由,不提
-
浏览器打开页面
http://your-website/testWebsocket
,按下 F12 开调试模式,使用postman
触发事件,有log
产生,大功告成。 -
创建私有频道时,需修改
laravel-echo-server.json
内authHost
设置项为真实域名,我这边使用http://localhost
失败鸟。
frpc 反向代理设置
由于我的环境是域名指向公网阿里云服务器,并配置了 frps
做转发。websocket
通信用到的 6001 端口需要在防火墙放开,且需要本地 homestead
内修改 frpc
做相应设置。frp
相关资料参阅 使用frp搭建微信开发环境。
frpc.ini
[websocket]
type = tcp
local_ip = 127.0.0.1
local_port = 6001
remote_port = 6001
测试时可以先执行 laravel-echo-server start
,然后启动 frpc
: ./frpc -c frpc.ini
,在浏览器内输入 http://your-site:6001
做测试,如果输出 OK
说明配置成功。
生产环境部署
2019年4月3日21:04:19新增
当在生产环境部署时,由于网站开启了全站 HTTPS
, 客户端一直无法认证通过。
查看官方文档,可以让 js
代码不再显示走 6001
端口,而是配置 nginx
转发解决。
-
在网站的
nginx conf
中新增:location /socket.io { proxy_pass http://localhost:6001; #could be localhost if Echo and NginX are on the same box proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; }
-
修改
laravel-echo-server.conf
中authHost
设置项为真实域名如https://your-domain.com
-
修改
app/resources/assets/js/bootstrap.js
,去掉显示指定的6001
端口:window.Echo = new Echo({ broadcaster: 'socket.io', host: window.location.hostname });
-
修改引入
socket.io.js
的blade view
,同样去除6001
端口:<script src="https://\{\{ Request::getHost() \}\}/socket.io/socket.io.js"></script>
如此一来,浏览器端都是访问的 https://your-domain.com
,让 nginx
帮我们处理 location
为 socket.io
的情况,自动转发流量到 laravel-echo-server
的服务接口 http://localhost:6001
,完美。