如何使用GatewayWorker 与 Laravel开发聊天室

Posted PHP开源社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用GatewayWorker 与 Laravel开发聊天室相关的知识,希望对你有一定的参考价值。


如何使用GatewayWorker 与 Laravel开发聊天室 

        

       世界上一成不变的东西,只有“任何事物都是在不断变化的”这条真理。 —— 斯里兰卡

                                                             

帮助你练脑子的逻辑思维题:

一间囚房里关押着两个犯人。每天监狱都会为这间囚房提供一罐汤,让这两个犯人自己来分。起初,这两个 人经常会发生争执,因为他们总是有人认为对方的汤比自己的多。后来他们找到了一个两全其美的办法:一个人分汤,让另一个人先选。于是争端就这么解决了。可 是,现在这间囚房里又加进来一个新犯人,现在是三个人来分汤。必须寻找一个新的方法来维持他们之间的和平。该怎么办呢? 

答案将会公布在下一期的文章里 如何使用GatewayWorker 与 Laravel开发聊天室 (听说长得帅气的都做出来了)

上一期的答案公布:

小黄。因为小李是第一个出手的,他要解决的第一个人就会是 
小林,这样就会保证自己的安全,因为如果小黄被解决,自己理所当然地会成为小林的目标,他也必定会被打死。而小黄如果第一枪不打小林而去打小李,自己肯定会死(他命中较高,会成为接下来的神枪手小林的目标)。他必定去尝试先打死小林。那么30% 50%的几率是80%(第一回合小林的死亡率,但会有一点点偏差,毕竟相加了)。那么第一回合小黄的死亡率是20%多一点点(小林的命中减去自己的死亡率)。假设小林第一回合死了,就轮到小李打小黄了,那么小李的命中就变成了50%多一点点(自己的命中加上小黄的死亡率)。这样就变成了小李小黄对决, 
第二回合的小李的第一枪命中是50%,小黄也是。可是如果拖下去的话占上风的自然就是小黄了,可能赢得也自然是小黄了。至于策略我看大家都领悟了吧。 

(你猜对了吗?如何使用GatewayWorker 与 Laravel开发聊天室


今天推送一首周董的歌,虽然他已经是孩子的爸爸了,听说这首歌是他为昆凌写的,周董也是努力的代名词,希望今天的你也能够像周董一样用心工作,拥有好的心情如何使用GatewayWorker 与 Laravel开发聊天室如何使用GatewayWorker 与 Laravel开发聊天室如何使用GatewayWorker 与 Laravel开发聊天室

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 如何使用GatewayWorker 与 Laravel开发聊天室 如何使用GatewayWorker 与 Laravel开发聊天室


聊天室(上篇)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:客户端连续  p i n g N o t R e s p o n s e L i m i t pingInterval 秒内不回应心跳则断开连接。

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 与 Laravel开发聊天室

 这里面比较重要的是 GatewayWorker 的超全局数组 $_SESSION。每个客户端连接对应一个 Session 会话,并由 Gateway 进程存储在内存里。示例如下,在收到客户端消息时,打印所有在线连接的 Session:

如何使用GatewayWorker 与 Laravel开发聊天室

注意上面的注释,操作当前连接上的 Session 时,直接使用 $_SESSION['xx'] = 'xxx'; 的方式赋值即可,操作其他用户的 Session 时用  Gateway::setSession 接口。

此外,如果你在 GatewayWorker 的进程模型里需要获取客户端、服务端的 IP,请使用 $_SERVER 数组。它由 Workerman 框架定义,内置了 5 个数组成员,数组 key 分别如下,详细请参考文档。

如何使用GatewayWorker 与 Laravel开发聊天室

更多 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 与 Laravel开发聊天室

客戶端浏览器建立与 GatewayWorker 的 WebSocket 连接,所有的业务逻辑由客户端通过 HTTP 协议 GET/POST 到 Web 框架,由 Web 框架统一处理。仅当客户端浏览器需要主动推送数据时, Web 框架将调用 GatewayWorker 提供的 API(GatewayClient),由 GatewayWorker 通过 WebSocket 主动推送给客户端。

 

步骤

大致的思路有了,具体的实现步骤配合聊天室部分代码,如下所示。

首先要定制 GatewayWorker 的所有进程,并把它整合到 laravel 项目根目录下的 gatewayworker 目录,该目录的结构遵循了官方推荐:

如何使用GatewayWorker 与 Laravel开发聊天室

整个 gatewayworker/ 目录的结构和源码几乎与官方的 workerman-chat 一模一样。仅有 Events.php 略有不同。

start.php 负责启动所有的 worker 进程:

如何使用GatewayWorker 与 Laravel开发聊天室

start_register.php 负责启动 Register 进程,监听本机 1238 端口,以便 Gateway 进程与 BuisnessWorker 进程建立通信。

(c)2006-2024 SYSTEM All Rights Reserved IT常识