快捷搜索:  汽车  科技

Swoole实战关系映射,Swoole实战关系映射

Swoole实战关系映射,Swoole实战关系映射猿来 一首朗朗上口的韵文,送给各位看官。赤日对苍穹雷隐隐雾蒙蒙日下对天中

前言

天对地

雨对风

大陆对长空

山花对海树

赤日对苍穹

雷隐隐雾蒙蒙

日下对天中

一首朗朗上口的韵文,送给各位看官。

Swoole实战关系映射,Swoole实战关系映射(1)

猿来

关系映射

关系映射,从字面意思来看,肯定得先有关系啊,关系才是重中之重,没有关系的谈情说爱,都是耍流氓。

前戏太多,看官心里已骂娘,看这篇文章,怎么像是工作日在WX群里划水骗工资呢!莫怒,莫怒,身体是自己的。

映射:即对应关系。

好比:你 和 镜子中的你,都是一样的文字彬彬,才华横溢……(众多赞美词)

再好比:拿着钥匙,你知道开那把锁

在Swoole 中,咱们知道fd,是客户端连接服务端的文件句柄,咱们可以标示为是那一个客户端,那么怎么和DB 中的user 表关系关联呢,我想推消息,知道推给谁呢。

显然,我们需要产生绑定关系啊!

这个绑定关系,swoole 也实现了,

Server->bind (摘自官方文档)

将连接绑定一个用户定义的UID,可以设置dispatch_mode=5设置以此值进行hash固定分配。可以保证某一个UID的连接全部会分配到同一个Worker进程。

function Server->bind(int $fd int $uid);

  • $fd:连接的ID
  • $uid:要绑定的UID,必须为非0的数字
  • 未绑定UID时默认使用fd取模进行分配

同一个连接只能被bind一次,如果已经绑定了UID,再次调用bind会返回false

可以使用$serv->getClientInfo($fd) 查看连接所绑定UID的值

仅在设置dispatch_mode=5时有效

在默认的dispatch_mode=2设置下,Server会按照socket fd来分配连接数据到不同的Worker进程。因为fd是不稳定的,一个客户端断开后重新连接,fd会发生改变。这样这个客户端的数据就会被分配到别的Worker。使用bind之后就可以按照用户定义的UID进行分配。即使断线重连,相同UID的TCP连接数据会被分配相同的Worker进程。

官方连接:https://wiki.swoole.com/wiki/page/369.html

先贴个为代码吧

Swoole实战关系映射,Swoole实战关系映射(2)

ws服务

注释:

1、在open 的时候,建立映射关系

userID 1 --> fd1

2、在推消息的时候,想给userID2 推 (message)

传入 userID2 获取userID2 在该服务中的fd,然后push 消息

3、在关闭连接的时候,解除绑定

unbind

思考:

(以下思考,纯属扯淡,可忽略)

假如,我使用了关系映射,但是,在关闭连接的时候,我不解除绑定,可以吗?

好,顺着思路想,不解触绑定,那么用户userID1 ,的关系会出现下面的情况,

userID1 --> fd1

userID1 --> fd6

userID1 --> fd100

userID1 --> fd888

userID1 --> ……

这么多关系,有的已经关闭,有且仅有一个在真正的维持连接。在fd复用的情况下,还有可能出现推送错误。

fd复用的情况下:

userID1 --> fd1 (实际已经废弃,但是没有剔除)

userID1 --> fd6 (当前真正在维持连接)

userID2 --> fd1 (当前真正在维持连接)

通过userID1 获取 fd,有可能得到结果fd1,推送消息出现错误

(当然,在userID 和 fd 为 一对一关系的时候,咱们通常都是更新了,也不会存在这个问题)

若userID 和 fd 为 一对多关系的时候,例如同一个用户多个终端,APP、PC等,问题就暴漏出来了

所以,没有谁,不会解除绑定。最多在推演的时候,会脑回路青奇想到这里,仔细品味之后,发现自己多虑了,有系就有解,解肯定是要的,只吃不拉的是貔貅。

How(自定义实现)

可以采用多种方案实现映射关系的存储

  1. redis
  2. apc
  3. swoole table

分析:

  1. redis有网络的开销,确实会慢一些,但天然是分布式的。未来有多台机器的时候,可以很方便地跨机器查询连接相关信息。
  2. swoole_table可以理解为是内存,能存多少要看你申请了多大的内存,比如一条数据需要100字节一百万条需要用占用100M内存。

业务需求

服务端:多台服务器

客户端:可多个终端同时登录,信息共享

实现方式:redis

第一步:

设计redis 的key,遵循唯一性

Swoole实战关系映射,Swoole实战关系映射(3)

key前缀

key = key前缀 服务器节点 客户端节点 uid

第二步:

建立连接绑定:

Swoole实战关系映射,Swoole实战关系映射(4)

set

第三步:

通过uid,获取fd

Swoole实战关系映射,Swoole实战关系映射(5)

get

第四步:

close 关闭,解除绑定unbind

Swoole实战关系映射,Swoole实战关系映射(6)

unbind

结束语

多看,多学,多练

(啪,多嘴!每个人都在努力)

Swoole实战关系映射,Swoole实战关系映射(7)

左手代码,右手诗,趣味学习新知识

猜您喜欢: