如何使用GatewayWorker 与 Laravel开发聊天室
Posted PHP开源社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用GatewayWorker 与 Laravel开发聊天室相关的知识,希望对你有一定的参考价值。
世界上一成不变的东西,只有“任何事物都是在不断变化的”这条真理。 —— 斯里兰卡
|
帮助你练脑子的逻辑思维题: 一间囚房里关押着两个犯人。每天监狱都会为这间囚房提供一罐汤,让这两个犯人自己来分。起初,这两个 人经常会发生争执,因为他们总是有人认为对方的汤比自己的多。后来他们找到了一个两全其美的办法:一个人分汤,让另一个人先选。于是争端就这么解决了。可 是,现在这间囚房里又加进来一个新犯人,现在是三个人来分汤。必须寻找一个新的方法来维持他们之间的和平。该怎么办呢? 答案将会公布在下一期的文章里 (听说长得帅气的都做出来了) |
上一期的答案公布:
小黄。因为小李是第一个出手的,他要解决的第一个人就会是
小林,这样就会保证自己的安全,因为如果小黄被解决,自己理所当然地会成为小林的目标,他也必定会被打死。而小黄如果第一枪不打小林而去打小李,自己肯定会死(他命中较高,会成为接下来的神枪手小林的目标)。他必定去尝试先打死小林。那么30% 50%的几率是80%(第一回合小林的死亡率,但会有一点点偏差,毕竟相加了)。那么第一回合小黄的死亡率是20%多一点点(小林的命中减去自己的死亡率)。假设小林第一回合死了,就轮到小李打小黄了,那么小李的命中就变成了50%多一点点(自己的命中加上小黄的死亡率)。这样就变成了小李小黄对决,
第二回合的小李的第一枪命中是50%,小黄也是。可是如果拖下去的话占上风的自然就是小黄了,可能赢得也自然是小黄了。至于策略我看大家都领悟了吧。
(你猜对了吗?)
今天推送一首周董的歌,虽然他已经是孩子的爸爸了,听说这首歌是他为昆凌写的,周董也是努力的代名词,希望今天的你也能够像周董一样用心工作,拥有好的心情
聊天室(上篇)GatewayWorker 基础
前言
本文的目的是基于 GatewayWorker 官方手册,梳理一次 GatewayWorker,并在实践中与 MVC 框架整合的思路。如果你已经理解了整合这一块儿的知识,那么就可以关掉这个网页了。时间蛮宝贵的~
这篇是上篇,梳理 GatewayWorker 基础,下篇是 GatewayWorker 与 Laravel 整合聊天室。如果你具备了 GatewayWorker 基础,请直接阅读下篇。
很久以前就想做一个聊天室了。查了下 "php 通信",找到了可用的东西:Socket、WebSocket、 Workerman 以及 GatewayWorker。Socket(接口)提供了一组端到端互相通信的接口,作为通信的核心功能。Websocket(协议)定义了通信中数据的封装和显示的格式,而且最大的特点是它支持服务端向客户端的主动推送,这一点是 HTTP 做不到的。而 Workerman (框架)将这两者很好地整合在了一起(当然不仅仅于此)。GatewayWorker(框架)是在 Workerman 的基础上开发的 TCP 长连接应用框架,提供了单发、群发和广播等接口,还可以客户端和客户端通信。
所以最终我选择了 GatewayWorker 作为 Socket 监听的服务端,Laravel 作为 HTTP 请求的业务处理框架,完成一个响应式的在线聊天室。
GatewayWorker工作原理
先理解一下工作原理,可以对 GatewayWorker 有个整体的把握。这一块儿其实手册里已经详细不啰嗦地解释清楚了。我这里再理一下:
1、Register、Gateway、BusinessWorker 3 种进程依次启动(因为支持多进程,所以我说“种”,而不是“个”)
2、Gateway 进程和 BusinessWorker 进程启动后向 Register 服务进程发起长连接注册自身。
6、至此,所有 Gateway 和 BusinessWorker 进程就通过 Register 服务进程建立了长连接。
7、客户端的连接事件和连接上的数据会经由 Gateway 转发给 BusinessWorker,BusinessWorker 默认调用 Events.php 中 Events 类的 onConnect、onMessage、onClose 事件回调处理业务逻辑。
8、BusinessWorker 负责运行所有的业务逻辑,实际的处理逻辑默认在 Events.php 中实现。
GatewayWorker进程模型
GatewayWorker 是以进程的形式进驻内存的,了解了它的工作原理之后,有必要理解一下它的进程模型。
GatewayWorker 主要有 3 种进程:Register 进程、Gateway 进程和 BusinessWorker 进程。这 3 种进程分别对应了内核源码中的 Register 类、Gateway 类和 BusinessWorker 类,并且它们都是基于 Workerman 框架的 Worker 类开发的,所以这 3 种进程都有一些公共的属性,比如 name、count、onWorkerStart、onWorkerStop 等等。可以说,GatewayWorker 里所有的进程都是 Worker 进程。
1、Register进程
Register 进程主要负责 Gateway 进程 与 BusinessWorker 进程建立连接并内部通讯。
该进程由 Register 类实例化,并随进程启动进驻内存。
2、Gateway进程
Gateway 进程主要负责客户端的连接以及连接上的数据,并将所有的请求转发给 BusinessWorker 进程进行处理。BusinessWorker 进程的所有处理结果都经由 Gateway 进程转发给客户端。
该进程由 Gateway 类实例化,并随进程启动进驻内存。
它可定制的有:
(1)实例化。指定协议、IP 和端口。
协议:目前支持的有 Websocket 协议、text 协议、Frame 协议、自定义通讯协议和 裸 TCP 协议(不推荐,见通讯协议作用),不支持监听 HTTP 协议。
IP:"0.0.0.0" 表示监听本机所有网卡;"127.0.0.1"表示仅允许本机通过 127.0.0.1 访问该进程;内网 IP 如 "192.168.11.2" 表示只允许该 IP 访问;外网 IP 如 "110.110.110.110" 表示只允许该 IP 访问。
端口:大于 1024 小于等于 65535。小于 1024 时需要 root 权限运行该进程。
(2)name:Gateway 进程名。以便在 Bash 等终端里查看区分。
(3)count:Gateway 进程数。充分利用多 CPU 资源。默认为 1。如何设置进程数,请参考这里。
(4)lanIp:Gateway 进程所在服务器的内网 IP,默认填写 "127.0.0.1" 即可。多服务器分布式部署 时要填写真实 IP。无论如何都不能填写 "0.0.0.0"。
(5)startPort:Gateway 进程启动后监听的起始端口(本机端口),用来给 BusinessWorker 进程提供连接服务,然后两者通过这个端口建立通讯。假设进程数 count 为 4,起始端口 startPort 为 2003,则 会启动 4 个 Gateway进程,各进程分别监听 2003、2004、2005、2006 端口。
(7)心跳设置:为了防止长时间不通讯被路由节点强行断开或断电断网等极端事件,必须加心跳。相关属性有 pingInterval、pingNotResponseLimit、pingInterval。详细心跳设置请参考服务端到客户端的心跳检测。
pingInterval:心跳间隔,单位秒,0 表示不发送心跳检测。
pingNotResponseLimit:客户端连续
pingData:心跳数据,可任意,客户端能识别就行。
(8)onWorkerStart:Gateway 进程启动后的回调函数。
(9)onWorkerStop:Gateway 进程关闭的回调函数。
(10)onConnect:当有客户端连接上来时触发。与 Events::onConnect 的区别是 Events::onConnect 方法运行在 BusinessWorker 进程上。而 Gateway::onConnect 方法是运行在Gateway 进程上,无法使用 \GatewayWorker\Lib\Gateway 类提供的接口。
(11)onClose:当有客户端连接关闭时触发。同样与Events::onClose的区别是 Gateway::onClose 方法是运行在 Gateway 进程上,无法使用 \GatewayWorker\Lib\Gateway 类提供的接口。
3、BusinessWorker进程
BusinessWorker 进程负责运行业务逻辑。BusinessWorker 进程收到 Gateway 进程转发来的事件和请求时,会默认调用 Events.php 中的 onConnect、onMessage、onClose 方法处理事件和数据。
该进程由 BusinessWorker 类实例化,并随进程启动进驻内存。
它可定制的有:
(1)name:BusinessWorker 进程名。以便在 Bash 等终端里查看区分。
(2)count:BusinessWorker 进程数。充分利用多 CPU 资源。默认为 1。如何设置进程数,请参考这里。
(4)onWorkerStart:BusinessWorker 进程启动后的回调函数
(5)onWorkerStop:BusinessWorker 进程关闭的回调函数。
(6)eventHandler:指定 BusinessWorker 进程里实际处理业务逻辑的类,默认是 Events。也就是默认使用 Events.php 中的 Events 类来处理业务。业务类至少要实现onMessage 静态方法,onConnect 和 onClose 静态方法可以不用实现。(如果使用了命名空间,建议填写完全限定名称的命名空间。)
。
Events.php
上面提到了 Events.php,它是实际处理业务逻辑的类 Events 所在的文件。我们在实际的开发中,只需要关注这一个文件。
Events 里有 5 个事件回调的处理方法,按照发生顺序,依次是
onWorkerStart (Worker $businessWorker):当 BusinessWorker 进程启动时触发。每个进程生命周期内只触发一次。
onConnect (string $client_id):当客户端连接上 Gateway 进程时触发(TCP 三层握手)。
onMesssge (string
c l i e n t i d , m i x e d recv_data):当客户端发来数据,也就是 Gateway 进程收到数据后触发。onClose (string client_id):当客户端连接断开时触发。无论是客户端还是服务端主动断开,都会触发。
onWorkerStop (Worker $businessWorker):当 BusinessWorker 进程退出时触发。每个进程生命周期内只触发一次。
这里面我们常用到的是 onMessage 和 onClose 回调,其他比较少用。
上面的回调事件里有一个比较重要的参数:$client_id。client_id 是 20 个字符的定长字符串,用来全局标识一个 Socket 连接。每个客户端连接都会被分配一个全局唯一的 client_id。客户端关闭连接时,对应的 client_id 会失效。当客户端再次打开一个 Socket 连接时,会被分配一个新的 client_id。
Lib\Gateway类提供的接口
既然(默认)在 Events.php 中处理实际的业务逻辑,回调的事件我们已经知道了。那么怎么向客户端发送消息呢?
命名空间 \GatewayWorker\Lib\Gateway 指向的这个 Gateway 类,提供了一组单发、群发和广播的接口,在 Events.php 中向客户端发信的时候就可以使用这个类。它提供的接口非常丰富:
这里面比较重要的是 GatewayWorker 的超全局数组 $_SESSION。每个客户端连接对应一个 Session 会话,并由 Gateway 进程存储在内存里。示例如下,在收到客户端消息时,打印所有在线连接的 Session:
注意上面的注释,操作当前连接上的 Session 时,直接使用 $_SESSION['xx'] = 'xxx'; 的方式赋值即可,操作其他用户的 Session 时用 Gateway::setSession 接口。
此外,如果你在 GatewayWorker 的进程模型里需要获取客户端、服务端的 IP,请使用 $_SERVER 数组。它由 Workerman 框架定义,内置了 5 个数组成员,数组 key 分别如下,详细请参考文档。
更多 GatewayWorker 开发和部署的细节或问题,比如心跳检测、设置定时器、合理选择多进程、分布式部署、定制通讯协议、启用 wss 协议等等,都在文档里有详细的介绍。
相关链接
GatewayWorker 在线文档:http://doc2.workerman.net/326102
Workerman 在线文档:http://doc.workerman.net/
Workerman 官网:https://www.workerman.net/
聊天室(下篇)GatewayWorker 与 Laravel 的整合
思路
上一篇大概梳理了一下 GatewayWorker 的基础知识。这篇就来准备整合 GatewayWorker 到 Laravel。
GatewayWorker 是基于 Socket 监听的服务器框架,而 Laravel 是基于 HTTP 请求/响应模型的 Web 框架。所以一定要明白,两者的部署是独立分开、互不干扰的。
因此在物理上它们的整合方式就见仁见智了。而官方, walkor 大神(GatewayWorker 框架作者)在手册里也给出了与 MVC 框架的结合方式,如下图所示:
客戶端浏览器建立与 GatewayWorker 的 WebSocket 连接,所有的业务逻辑由客户端通过 HTTP 协议 GET/POST 到 Web 框架,由 Web 框架统一处理。仅当客户端浏览器需要主动推送数据时, Web 框架将调用 GatewayWorker 提供的 API(GatewayClient),由 GatewayWorker 通过 WebSocket 主动推送给客户端。
步骤
大致的思路有了,具体的实现步骤配合聊天室部分代码,如下所示。
首先要定制 GatewayWorker 的所有进程,并把它整合到 laravel 项目根目录下的 gatewayworker 目录,该目录的结构遵循了官方推荐:
整个 gatewayworker/ 目录的结构和源码几乎与官方的 workerman-chat 一模一样。仅有 Events.php 略有不同。
start.php 负责启动所有的 worker 进程:
start_register.php 负责启动 Register 进程,监听本机 1238 端口,以便 Gateway 进程与 BuisnessWorker 进程建立通信。
1
以上是关于如何使用GatewayWorker 与 Laravel开发聊天室的主要内容,如果未能解决你的问题,请参考以下文章 WorkerMan 入门学习之GatewayWorker框架使用 |