goim 文章系列(共5篇):

  • goim 架构与定制
  • 从goim定制, 浅谈 golang 的 interface 解耦合与gRPC
  • goim中的 bilibili/discovery (eureka)基本概念及应用
  • goim 的 data flow 数据流
  • goim的业务集成(分享会小结与QA)

有个 slack 频道, 不少朋友在交流 goim , 欢迎加入slack #goim

[简述] goim.io 是 非常成功的 IM (Instance Message) 即时消息平台 , 本文介绍 goim 中的数据定义与 data flow 数据流转

1. goim 中的 data flow 数据流转

1.1 架构中的数据流转

看图

数据流转

  1. http 接口向 logic 发送数据
  2. logic 从 redis 中获取会话数据, 以 protobuf 序列化数据, 发送到 MQ
  3. job 从 MQ 中订阅数据, 取出 im 发送数据中的 server / room 向指定 server 的 comet 发送数据
  4. comet 接收 job 分发的数据后, 存入 指定 channel 的 ring buffer , 再转为 tcp/websocket 数据包, 发送到指定 channel 的客户端

1.2 简化后的数据流转细节

上示意图标注了 goim 中的关键数据结构:

  1. 标注了 im 发送数据构成, 注意, 这个数据结构是被logic 以 protobuf 序列化后发到 MQ , 并在 job 中反序列化后, 分发到 comet
  2. 这里的会话信息, 主要是 mid --> server 与 room-->server 的对应关系, 存在 redis 中
  3. comet 中的 im 信息, 由 job 从 MQ 中反序列化后, 取出 server / room / keys( 一到多个key , 对应 channel ) 发送到指定 comet server
  4. comet 以 tcp / websocket 封装数据包, 发送给终端用户, 终端解包后显示

2. goim 中的数据定义

2.1. logic 发送 im 信息

发布 im 信息定义( 在 protobuf 中的定义)

message PushMsg {enum Type {PUSH = 0;ROOM = 1;BROADCAST = 2;}Type type = 1;int32 operation = 2;int32 speed = 3;string server = 4;string room = 5;repeated string keys = 6;bytes msg = 7;
}
复制代码

2.2 会话数据

当 tcp client 或 websocket client 连接 comet server 时, comet 以 gRPC 向 logic 进行内部通讯, 生成会话数据, 存在 redis 中, 具体细节不展开, 看代码

当 http client 向 logic 发送 im 消息时, logic 向 redis 查询会话数据, 对于已经存在的 room--> server / mid ( memberID) --> server 即发送消息到 MQ , 该部分代码比较清楚, 也不再加说明

2.3. tcp / websocket 数据包定义

推送 im 信息, 对象名称为 proto, 在 protobuf 中定义

message Proto {int32 ver = 1 [(gogoproto.jsontag) = "ver"];int32 op = 2 [(gogoproto.jsontag) = "op"];int32 seq = 3 [(gogoproto.jsontag) = "seq"];bytes body = 4 [(gogoproto.jsontag) = "body"];
}
复制代码

protobuf 文件 github.com/Terry-Mao/g… 中第12行

tcp / websocket 数据包组包/折包操作在 /api/comet/grpc/protocol.go

由上图可见, goim 在 tcp /websocket 数据包的数据包定义, 与 go 中 proto 定义, 多了, 数据包总长度 / 包头长度两个字段

3. comet 中的处理

简化数据流转, 从发送端数据到 接收端数据, 可以看到, serverID / roomID / channel ( 用 mid 或 key 来指示) 的主要作用作为分流/分发用, 在最后推送数据包中, 就不在包含这三个字段了.

同时, comet 中使用了 ring buffer 来缓存一个 channel 送达的多条信息并推送到终端, 这里, 并没有看到对推送下发的信息作更多处理.

_

_


看代码, 补充细节

// Channel used by message pusher send msg to write goroutine.
type Channel struct {c        *conf.CometConfigRoom     *RoomCliProto Ringsignal   chan *grpc.ProtoWriter   xbufio.WriterReader   xbufio.ReaderNext     *ChannelPrev     *ChannelMid      int64   // #########   memberID  Key      stringIP       stringwatchOps map[int32]struct{}mutex sync.RWMutex
}
复制代码

这里:

  1. mid 就是 memberID , 当前 channel ( 用户端与 comet 的长连接) 是哪个用户连接上的 该长连接使用 key 作为长连接的会话标识, 换个方式说, key 也就标定了一个 im 信息要发给哪个/哪几个在线长连接对端的用户
  2. key 就是长连接的会话ID, 可以这么理解, 就算是 sessionID 吧
  3. watchOps 是一个map 映射表, 其中的 int32 是房间号. map 多个房间号, map 结构是用来查询房间号是否在 map 中存在或不存在. watchOps 是当前长连接用户用来监听当前客户端接收哪个房间的 im 消息推送, 换个方式说, 一个 goim 终端可以接收多个房间发送来的 im 消息
  4. watchOps 初始化是在 tcp / websocket 客户端进行首次连接时处理的, 细节看代码.

_

_

从 logic 自 http 的 post 请求中, 获取发布 im 信息后, 序列化发到 MQ, 在 job 中拆包反序列化, 再组包, 这一步骤对性能是否有影响, 需发测试数据来定位, 但个人感觉, 这几次拆包组包, 有点重复.

4. 小结

以上, 应开源社区的朋友要求, 对内部数据结构作了一个简化分析, 花时不多,水平有限, 或有考虑不周或分析不当, 欢迎批评指点.

最后, goim.io 在网络上相关文章不少, 好文不少, 给我启迪, 一并感谢.

推荐以下文章:

  • alexstocks.github.io/html/im.htm… 作者 AlexStcks, 非常棒的文章, 集思践行, 很有深度
  • github.com/LinkinStars… 作者: LinkinStars, 这个值得一看
  • moonshining.github.io/2018/03/09/… 写得很细致

再一次, 感谢 www.bilibili.com 的开源 & 毛剑 及众多开源社区的前辈们,朋友们

_

关于我

网名 tsingson (三明智, 江湖人称3爷)

原 ustarcom IPTV/OTT 事业部播控产品线技术架构湿/解决方案工程湿角色(8年), 自由职业者,

喜欢音乐(口琴,是第三/四/五届广东国际口琴嘉年华的主策划人之一), 摄影与越野,

喜欢 golang 语言 (商用项目中主要用 postgres + golang )

_

_ tsingson 写于中国深圳 小罗号口琴音乐中心, 2019/05/07

转载于:https://juejin.im/post/5cd12fa16fb9a0320b40ec32

goim 中的 data flow 数据流转及思考相关推荐

  1. 深度学习编译器Data Flow和Control Flow

    深度学习编译器Data Flow和Control Flow 本文介绍了一下深度学习框架的Data Flow和Control Flow,基于TensorFlow解释了TensorFlow是如何在静态图中 ...

  2. 利用设备上下线状态数据流转到TSDB的方法实现监测设备历史在线情况

    在进行今天的正题前,先举个小例子: 甲和乙是同一公司的同事,两个人办公室离得很远,但可以通过单面窗看到公司大门口,当对方上班和下班时都能看到,只是从大门口看不到办公室内的情况.假如甲先到公司,乙后到公 ...

  3. SAP LSMW 物料主数据Basic Data Text数据的导入

    SAP LSMW 物料主数据Basic Data Text数据的导入 笔者所在的D项目上,业务要求每个物料主数据能有一个remark字段,用以在物料描述之外为物料做更多更详细的描述,比如一些备品备件物 ...

  4. 如何在数据库中存储大的数据文件

    1. 什么是大的数据? 所谓大的数据,就是大的字节数据,或大的字符数据.标准SQL中提供了如下类型来保存大数据类型: 类型 长度 tinyblob 28–1B(256B) blob 216-1B(64 ...

  5. Spring Cloud Data Flow 中的 ETL

    来源:SpringForAll社区 1 概述 Spring Cloud Data Flow是一个用于构建实时数据管道和批处理过程的云原生工具包. Spring Cloud Data Flow已准备好用 ...

  6. 微软BI 之SSIS 系列 - 理解Data Flow Task 中的同步与异步, 阻塞,半阻塞和全阻塞以及Buffer 缓存概念...

    开篇介绍 在 SSIS Dataflow 数据流中的组件可以分为 Synchronous 同步和 Asynchronous 异步这两种类型. 同步与异步 Synchronous and Asynchr ...

  7. 数据可视化 —— 数据流图(Data Flow Diagram)

    数据流图(Data Flow Diagram):简称 DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能.数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表 ...

  8. idea中analysis之analyze data flow功能体验

    周末没啥事,就看了看idea的文档,其中发现了一个感觉挺不错的功能,可以用来分析代码的影响范围,在这里分享记录一下 官方文档说明地址 https://www.jetbrains.com/help/id ...

  9. pandas使用select_dtypes函数移除dataframe中指定数据类型的数据列(exclude columns based on the data type in dataframe)

    pandas使用select_dtypes函数移除dataframe中指定数据类型的数据列(exclude columns based on the data type in dataframe) 目 ...

最新文章

  1. linux系统分析命令,Linux操作系统基础解析之(四)——Linux基本命令剖析(2)
  2. OpenCascade Primitives BRep-Cylinder
  3. jQuery之事件绑定
  4. 路由器01---k2刷Pandora
  5. 网易容器云平台的微服务化实践
  6. 【汇总】C#数据类型及转换
  7. hacker_Hacker Public Radio上的免费软件
  8. 字符串反转的进一步应用----单词反转
  9. 大数据时代亟需消除八大“疑云”
  10. C#SHA1算法及注意事项
  11. Cadence SPB安装及重装
  12. Java-RPC通信--HSF框架
  13. 9008刷机 小米max2_小米max2线刷包_小米max2刷机包_小米max2固件包_小米max2救砖包 - 线刷宝ROM中心...
  14. hdu 5053(水题)
  15. python计算决策树误差_《统计学习方法》第五章决策树 练习题解答
  16. iOS开发之Tom猫
  17. python手绘效果图_用Python做个海量小姐姐素描图
  18. http://zjj2816.cnblogs.com/?Contact=1
  19. 多种方法爬取猫眼电影并分析(附代码)
  20. 秋裤传奇html5,匈牙利门神不服老 基拉利,一条秋裤写传奇

热门文章

  1. 3-7:常见任务和主要工具之文本处理
  2. C/C++静态库编译报错(/usr/bin/ld:cannot find -lpthread,/usr/bin/ld:cannot find -lc)
  3. mysql刻度转时分秒
  4. Python环境安装脚本,拷贝环境脚本,命令迁移模块(pip freeze requirements.txt)
  5. ubuntu安装java8
  6. TCP/IP四层模型及各层协议首部详述(包含IOS7层)
  7. Element ui select同时获取value和label的值
  8. 将sql 结果导出到文件
  9. WPF设置全局快捷键
  10. 物化视图 sql server 1