Gobelieve 架构

Gobelieve github地址

im 客户连接服务器 (可分布式部署,暂无负载均衡模块)

imr 路由查询服务器(主要解决im分布式部署的问题)

ims 存储服务器 (主从部署)

基础模块


1.数据包协议

包:header()|body

header:len(),seq(),cmd(),version(),空()

2.数据收发流程

accept收到一个连接
开启写线程和读线程 写线程:监听client.wt阻塞队列,一有数据就写入conn 读线程:按照数据包协议从conn读出数据包,由client.HandleMessage处理

3.几个方法

PushMessage 通过route_channel 发送 MSG_PUBLISH 给IMR
PushGroupMessage 通过route_channel 发送 MSG_PUBLISH_GROUP 给IMR
SaveMessage 通过IMS RPC服务 调用SavePeerMessage
SaveGroupMessage 通过IMS RPC服务 调用SaveGroupMessage
im_client.SendMessage
.PushMessage
.本地路由查询 并EnqueueMessage
im_client.SendGroupMessage
.PushGroupMessage
.group_manager查询group
.由group得到所有menber,对每个menber查询路由表,并EnqueueMessage
im_client.EnqueueMessage
将数据写入client.wt,供发送出去

IM 模块


IM模块初始化

1.redis_pool

2.storage_pools 连接ims:3333

http服务器读取最近消息时调用

3.rpc_clients ims:13333

SyncMessage
SyncGroupMessage
SavePeerMessage
SaveGroupMessage

4.group_rpc_clients (可选)

5.route_channels 连接imr:4444

开启读写线程
写:从channel.wt管道取值并发送给imr
读:从imr接受消息,并分发给当前im节点连接用户

6.group_manager

.load: 从mysql加载group,保存至 group_manager.groups
.run: reids订阅
case group_create、
group_disband、
group_member_add、
group_member_remove、
group_upgrade、
回调处理 增删改查group_manager.groups
case ping
脏数据检测
.ping:
每个五分钟发送ping

7.group_message_deliver:普通群消息分发

.init:创建本地存储文件
.run: 监听wt管道,有数据表示有新消息写入文件
读取文件并发送

8.ListenRedis 禁言

redis订阅 speak_forbidden
接受事件推送,从本地路由查询到对应client,修改forbidden字段。

9.SyncKeyService

从 group_sync_c 和 sync_c 管道取值,保存至redis
( 客户端发送的 MSG_GROUP_SYNC_KEY 和 MSG_SYNC_KEY 消息会将消息内同步key写入对应的管道 group_sync_c 和 sync_c)

10.StartHttpServer :6666

web服务器

11.StartSocketIO :websocket

12.ListenClient :23000 处理客户端连接

ListenClient 处理流程


1.登录认证 cmd:MSG_AUTH_TOKEN

客户端将uid与token传给服务器,由redis_pool查询认证

认证成功: .由EnqueueMessage发送消息{cmd:MSG_AUTH_STATUS,status:}
.client.AddClient() 缓存本连接到本机路由表
.client.IMClient.Login() 缓存本链接到IMR路由表
认证失败: 由EnqueueMessage发送消息{cmd:MSG_AUTH_STATUS,status:}

2.IMClient 处理消息类型

MSG_IM: 处理IM 同步消息
MSG_GROUP_IM: 处理Group 同步消息
MSG_INPUTING: 处理Inputing消息
MSG_RT: 处理实时消息
MSG_UNREAD_COUNT: 设置未读消息数
MSG_SYNC: 客户端请求同步最新消息
MSG_SYNC_KEY: 客户端将SYNC_KEY 传至服务端
MSG_SYNC_GROUP: 客户端请求同步最新群消息
MSG_GROUP_SYNC_KEY: 客户端将GROUP_SYNC_KEY 传至服务端

RoomClient 消息类型

MSG_ENTER_ROOM:进入聊天室
MSG_LEAVE_ROOM:离开聊天室
MSG_ROOM_IM:聊天室IM消息

VOIPClient消息类型

MSG_VOIP_CONTROL: VOIP命令

CustomerClient消息类型

MSG_CUSTOMER: 顾客->客服
MSG_CUSTOMER_SUPPORT:客服->顾客

3.MSG_IM处理流程:
用户A -> B

.SaveMessage:保存消息到目标用户B存储队列 (rpc->SavePeerMessage)
.SaveMessage:保存消息到发送用户A存储队列(供多点登录同步消息)
.PushMessage:外部推送消息给目标用户B(由IMR寻路由)MSG_IM
.SendMessage:发送同步消息给目标用户B (外部推送+本地寻址发送) MSG_SYNC_NOTIFY
.SendMessage:发送同步消息给发送用户A(多点登录)MSG_SYNC_NOTIFY
.EnqueueMessage:给本连接回复MSG_ACK消息

4.MSG_GROUP_IM处理流程

.由group_manager查询到指定group
.根据Group类型:
.HandleSuperGroupMessage:
SaveGroupMessage:保存MSG_GROUP_IM消息 (rpc->SaveGroupMessage)
PushGroupMessage:外部推送群消息 MSG_GROUP_IM
SendGroupMessage:发送群同步通知消息(外部推送+本地寻址推送) MSG_SYNC_GROUP_NOTIFY
.HandleGroupMessage:
group_message_deliver:
saveMessage:本地保存消息 MSG_PENDING_GROUP_MESSAGE
ReadMessage:读取消息 MSG_PENDING_GROUP_MESSAGE
对群每个成员:SaveMessage:保存MSG_GROUP_IM消息
PushMessage:外部推送消息 MSG_GROUP_IM
SendMessage:发送同步消息 MSG_SYNC_NOTIFY
.EnqueueMessage:给本连接回复MSG_ACK消息

5.MSG_INPUTING:

SendMessage:发送给目标用户

6.MSG_RT 实时消息处理流程

SendMessage:发送消息给目标用户

7.MSG_UNREAD_COUNT 设置用户未读数:

由redis_pool操作 hashkey:users_$appid_$uid field:unread

8.消息同步流程:

服务端->客户端 MSG_SYNC_NOTIFY:
客户端:
.isSyncing==false:sendSync 发送旧syncKey,请求消息MSG_SYNC,状态切换为同步状态
.isSyncing==true: 同步状态中,新的newSyncKey 保存在pendingSyncKey中,this.pendingSyncKey = newSyncKey; 客户端->服务端:MSG_SYNC
服务端:
.从客户端传来的sync_key得到last_id,(如果last_id==,从redis取出最新sync_key)
.rpc->SyncMessage:根据last_id取出缓存的最近消息msgs
.EnqueueMessage:发送MSG_SYNC_BEGIN消息 (客户端不做处理)
.EnqueueMessage:循环发送msgs
.EnqueueMessage:发送MSG_SYNC_END消息 其中包含sync_key为最后一条msg的MsgID 服务端->客户端:MSG_SYNC_END
客户端:
.取出newSyncKey(如果newSyncKey>this.syncKey,客户端保存newSyncKey,并发送给服务端MSG_SYNC_KEY)
.切换同步状态isSyncing = false;
.如果this.pendingSyncKey > this.syncKey ,
即在上次同步中有新的MSG_SYNC_NOTIFY消息传给客户端,则再次同步,sendSync发送syncKey,pendingSyncKey置零 客户端->服务端: MSG_SYNC_KEY
服务端:
.从sync_key得到last_id,
.包裹成SyncHistory,写入管道sync_c <- s
 
消息传输流程

9.超级群同步流程

服务端->客户端 MSG_SYNC_GROUP_NOTIFY
客户端:
.isSyncing==false:sendSync 发送旧syncKey,请求消息MSG_SYNC_GROUP,状态切换为同步状态
.isSyncing==true: 同步状态中,新的newSyncKey 保存在pendingSyncKey中,this.pendingSyncKey = newSyncKey; 客户端->服务端 MSG_SYNC_GROUP
服务端:
/从客户端传来的group_sync_key取出group_id,sync_key,last_id=sync_key,(如果last_id,从redis取出新的group_sync_key_$groupid)
.rpc->SyncGroupMessage:根据last_id取出最近的群消息 msgs
.EnqueueMessage:发送MSG_SYNC_GROUP_BEGIN 消息
.EnqueueMessage:循环发送msgs
.EnqueueMessage:发送MSG_SYNC_GROUP_END,其中sync_key为最后一条msg的MsgID 服务端->客户端 MSG_SYNC_GROUP_END
客户端:
.取出GroupSyncKey.syncKey和当前syncKey(如果GroupSyncKey.syncKey较大,客户端保存更新,并发送给服务端 MSG_GROUP_SYNC_KEY) .切换同步状态isSyncing = false;
如果this.pendingSyncKey > this.syncKey ,
即在上次同步中有新的MSG_SYNC_NOTIFY消息传给客户端,则再次同步,sendSync发送syncKey,pendingSyncKey置零 客户端->服务端 MSG_GROUP_SYNC_KEY
服务端:
.取出group_id last_id
.包裹成SyncGroupHistory,写入管道group_sync_c <- s

IMR模块

1.redis_pool

2.group_manager

3.ListenClient :4444

.MSG_SUBSCRIBE
.MSG_UNSUBSCRIBE
.MSG_SUBSCRIBE_ROOM
.MSG_UNSUBSCRIBE_ROOM
(以上四个均是对imr维护的路由表增删改查)
.MSG_PUBLISH
.根据消息内容得到消息类型和目标用户
.查询路由表,用户如果离线则将消息放入第三方推送队列
.根据路由表得到用户连接所在im节点,并把消息推送至该节点 第三部过滤条件:
.消息类型不为 MSG_IM、MSG_GROUP_IM、MSG_CUSTOMER、MSG_CUSTOMER_SUPPORT、MSG_SYSTEM
.目标IM节点和发送IM节点不是同一节点 .MSG_PUBLISH_GROUP
.根据消息内容得到消息类型和群
.对群内每个成员查询路由表,用户如果离线则将消息放入第三方推送队列
.群发给所有IM节点 第三部过滤条件:
.消息类型为 MSG_PUBLISH_GROUP .MSG_PUBLISH_ROOM
.根据消息内容得到roomid
.根据roomid查询路由表得到所有节点
.对每个节点发送消息 第三部过滤条件:
.发送节点和目标节点不是同一节点
 
IMR架构

IMS模块 (主从)

1.NewMaster

.init:创建容器存储 clients,创建队列ewt
.run:监听队列ewt,将ewt队列内消息添加到缓存cache数组
cache每满1000或者每隔1分钟,执行SendBatch,
SendBatch:
封装消息 MSG_STORAGE_SYNC_MESSAGE_BATCH ,写入每个从节点连接的消息队列client.ewt

2.NewSlaver 监听主节点(可选)

run:连接至主节点,连接成功发送 MSG_STORAGE_SYNC_BEGIN
循环读取消息:
MSG_STORAGE_SYNC_MESSAGE storage.SaveSyncMessage(emsg)
MSG_STORAGE_SYNC_MESSAGE_BATCH storage.SaveSyncMessageBatch(mb)

3.waitSignal 处理中断 SIGINT SIGTERM

storage.FlushPeerIndex() 将每个人最近消息的msgid写入文件
storage.FlushGroupIndex()

4.ListenSyncClient master监听 3334

处理从节点连接 RunLoop:
.(初始化同步)接受 MSG_STORAGE_SYNC_BEGIN 消息,从中取得msgid,
根据msgid LoadSyncMessagesInBackground 查询得到消息,并发送给从节点
.将从节点连接添加至 clients
.进入for循环,监听消息队列client.ewt并发送给从节点
.循环break后 RemoveClient

5.ListenRPCClient :13333

SyncMessage
SyncGroupMessage
SavePeerMessage
SaveGroupMessage
GetNewCount
由im调用

6.ListenClient() 3333

对于每个连接:
.init:创建写管道wt
.run :写线程,从wt管道取数据并发送
读线程,HandleMessage

7.HandleMessage

.MSG_LOAD_OFFLINE
对IM: storage_client.LoadOfflineMessage响应
.MSG_SAVE_AND_ENQUEUE
对IM:storage_client.SaveAndEnqueueMessage响应
.MSG_DEQUEUE
对IM: storage_client.DequeueMessage响应
*.MSG_LOAD_LATEST
对IM-StartHttpServer-LoadLatestMessage响应
*.MSG_LOAD_HISTORY
对IM-StartHttpServer-LoadHistoryMessage响应
.MSG_SAVE_AND_ENQUEUE_GROUP
对IM: storage_client.SaveAndEnqueueGroupMessage响应
.MSG_DEQUEUE_GROUP
对IM :storage_client.DequeueGroupMessage响应
.MSG_LOAD_GROUP_OFFLINE
对IM: storage_client.LoadGroupOfflineMessage响应 (上述除了4,,暂无被IM模块调用)
IMS架构

作者:JackieF777
链接:https://www.jianshu.com/p/8121d6e85282
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Gobelieve 架构(转载)的更多相关文章

  1. 基于k8s的集群稳定架构-转载

    基于k8s的集群稳定架构-转载 前言 我司的集群时刻处于崩溃的边缘,通过近三个月的掌握,发现我司的集群不稳定的原因有以下几点: 1.发版流程不稳定 2.缺少监控平台[最重要的原因] 3.缺少日志系统 ...

  2. 理解RESTful架构(转载)

    本文转载自:http://www.ruanyifeng.com/blog/2011/09/restful.html 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软 ...

  3. 基于AngularJS的企业软件前端架构[转载]

    这篇是我参加QCon北京2014的演讲内容: 提纲: 企业应用在软件行业中占有很大的比重,而这类软件多数现在也都采用B/S的模式开发,在这个日新月异的时代,它们的前端开发技术找到了什么改进点呢? B/ ...

  4. graylog2 架构--转载

    原文地址:http://docs.graylog.org/en/latest/pages/architecture.html Architectural considerations There ar ...

  5. 【Chromium中文文档】插件架构

    插件架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Plugin_A ...

  6. 【Chromium中文文档】Chromium多进程架构

    多进程架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//Start_Here_Background_Readin ...

  7. zabbix监控的基础概念、工作原理及架构(一)

    zabbix监控的基础概念.工作原理及架构 转载于网络 一.什么是zabbix及优缺点 Zabbix能监视各种网络参数,保证服务器系统的安全运营,并提供灵活的通知机制以让系统管理员快速定位/解决存在的 ...

  8. RESTful API架构和oauth2.0认证机制(概念版)

    1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的 ...

  9. Chromium

    Chromium多进程架构 多进程架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//Start_Here_Bac ...

随机推荐

  1. 数学建模三剑客MSN

    前言 不管是不是巴萨的球迷,只要你喜欢足球,就一定听说过梅西(Messi).苏亚雷斯(Suarez)和内马尔(Neymar)这个MSN组合.在众多的数学建模辅助工具中,也有一个犀利无比的MSN组合,他 ...

  2. 基于OpenMP的C++并行编程简单示例

    示例要求:在整数A和B之间找到符合条件的值X,使f(X)=C. 示例代码(需要在VS中开启OpenMP支持): #include<iostream> #include<time.h& ...

  3. web assembly是什么,能干什么

    web assembly混合javascript和另外底层语言编译的模块,共同运行.将js的高级,易用及c/c++的高效底层优势结合起来. 最可能的用处是提供一种可行的方法将原来的c/c++应用por ...

  4. Oracle EBS 新增OAFM个数

    在 $INST_TOP/ora/10.1.3/opmn/conf/opmn.xml中找到<process-type id="oafm" module-id="OC4 ...

  5. js拼接字符串,字符串转数组

    想要把字符串按一定的规则拼起来如 1,2,3 var a = []; a.push(1); a.push(2); a.push(3); a.join(','); =>> 1,2,3 想要把 ...

  6. Jquery Ajax 提交json数据

    在MVC控制器(这里是TestController)下有一个CreateOrder的Action方法 [HttpPost] public ActionResult CreateOrder(List&l ...

  7. MySQL学习分享--Thread pool实现

    基于<MySQL学习分享--Thread pool>对Thread pool架构设计的详细了解,本文主要对Thread pool的实现进行分析,并根据Mariadb和Percona提供的开 ...

  8. 企业生产环境集群稳定性-HA就行吗?

    在企业生产中,集群一旦运行,是要尽可能的将损失降到最低,现在所有的大数据技术都有HA,spark的.Hadoop的.HBase的等等, HA分冷备和热备,热备是集群自带的,冷备就是硬件的. 这样一种情 ...

  9. HBase性能优化 Java Api

    1. 使用“连接池” 如果每次和Hbase交互时都去新建连接的话,显然是低效率的,HBase也提供类连接池相关的API. 1.1. HTablePool 早期的API中使用它,但很不幸,现在它已经过时 ...

  10. uva 12508 - Triangles in the Grid(几何+计数)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011328934/article/details/35244875 题目链接:uva 12508 ...