Jack Jiang

我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
posts - 490, comments - 13, trackbacks - 0, articles - 1

本文由钉钉技术专家尹启绣分享,有修订和重新排版。

1、引言

短短的几年时间,钉钉便迅速成为一款国民级应用,发展速度堪称迅猛。

IM作为钉钉最核心的功能,每天需要支持海量企业用户的沟通,同时还通过 PaaS 形式为淘宝、高德等 App 提供基础的即时通讯能力,是日均千亿级消息量的 IM 平台。

在钉钉的IM中,我们通过 RocketMQ实现了系统解耦、异步削峰填谷,还通过定时消息实现分布式定时任务等高级特性。同时与 RocketMQ 深入共创,不断优化解决了很多RocketMQ本身的问题,并且孵化出 POP 消费模式等新特性,使 RocketMQ 能够完美支持对性能稳定性和时延要求非常高的 IM 系统。本文将为你分享这些内容。

学习交流:

本文已同步发布于:http://www.52im.net/thread-4106-1-1.html

2、系列文章

本文是系列文章的第9篇,总目录如下:

3、钉钉IM面临的巨大技术挑战

3.1 概述

钉钉作为企业级 IM 领先者,面临着巨大的技术挑战。市面上DAU过亿的App里,只有钉钉是2B产品,我们不仅需要和其他 2C 产品一样,支持海量用户的低时延、高并发、高性能、高可用,还需保证企业级用户在使用钉钉时能够提升沟通协同效率。

下图是概括的是钉钉的主要能力:

3.2 技术挑战1:ToB与ToC的差异

作为企业级应用,需要保证帮助用户提升沟通体验。

ToB 的工作沟通和 ToC 的场景生活沟通存在较大差异, ToC的IM产品比如微信,在有完整的关系链后,只需满足大部分用户需求即可。

然而微信的很多体验其实并不友好:比如聊天消息中的视频图片在固定时间内没有打开则会无法下载,卸载重装之后聊天记录全部丢失。

而 ToB 场景下:聊天记录是非常重要的内容,钉钉为保证用户消息不丢失,提供了多端同步和消息云端存储的能力,用户任意换端都能查看完整的聊天记录。

在工作过程中,大量会议是工作效率杀手,钉钉还提供了已读、Ding 等效率套件,为工作沟通提供新选项。

3.3 技术挑战2:安全要求高

在ToB 的工作场景下,用户对信息安全要求非常高,信息安全是企业的生命线。

钉钉提供了人和组织架构打通的工作群,用户离开组织后自动退出企业工作群,这样就很好地保障了企业信息的安全。

同时,在已经支持的全链路加密能力上提供了三方加密能力,可以最大程度保障企业用户的信息安全性。

3.4 技术挑战3:稳定性要求高

企业用户对稳定性的要求也非常高,如果钉钉出现故障,深度使用钉钉的企业都会受到巨大影响。

因此,钉钉 IM 系统在稳定性上也做了非常深入的建设,架构上对依赖和流量做了深入治理,核心能力所有依赖都为双倍。

比如虽然 RocketMQ 已经非常稳定,也没有发生过故障,但是对 RocketMQ 可能出现故障的产品依然做了很好的保护,使用 RocketMQ 定时消息和堆积能力做热点治理和流量防护,让系统面对大规模流量时能从容应对,并且建设了异地多活和可弹性扩缩容能力,疫情期间很好地保证了学生们的在线课堂。

在稳定性机制上,常态化容灾演练、突袭演练、自动化健康巡检等也能很好地保证线上稳定性。比如波浪式流量就是在做断网演练时发现。

3.5 技术挑战4:业务多样性

针对不同行业的业务多样性,还要尽可能地满足用户的通用性需求,比如万人群、全员群等,目前钉钉已经做到能够支持 10 万人级别的群。

更多的业务需求将依赖于我们抽象出的通用开放能力,将 IM 能力尽可能地开放给企业和三方 ISV,使得不同形态的业务都能在钉钉平台上得到满足 。

4、消息队列在钉钉IM系统中的重要作用

4.1 概述

在如此丰富的企业级能力下,钉钉IM要与微信等 ToC 产品一样,支持亿级用户低时延沟通,系统架构需要具备高并发、高性能、高可用的能力,挑战非常之大。

IM 本身是异步化沟通系统,与开会或者电话沟通相比,让沟通双方异步处理消息能够减少打断次数,提升沟通效率。这种异步的特性和消息队列的能力很契合,消息队列可以很好地帮助 IM 完成异步化解耦、失败重试、削峰填谷等能力。

这里,我们以钉钉IM系统最核心的发消息和已读链路简化流程(如下图所示),来详细说明消息队列在系统里的重要作用。

 

4.2 发消息链路

钉钉IM系统的发消息链路流程如下:

  • 1)处于登录状态的钉钉用户发送一条消息时,首先会将请求发送到 receiver 应用;
  • 2)为保证发消息体验和成功率,receiver 应用只做这条消息能否发送的校验,其他如消息入库、接收者推送等都交由下游应用完成;
  • 3)校验完成之后将消息投递给消息队列,成功后即可返回给用户;
  • 4)消息发送成功,processor 会从消息队列里订阅到这条消息,并对消息进行入库处理,再通过消息队列将消息交给同步服务 syncserver 做处理,将消息同步给在线接收者。

上述过程中,对于不在线的用户:可以通过消息队列将消息推给离线 push 系统。离线 push 系统可以对接接苹果、华为、小米等推送系统进行离线推送。

用户发消息过程中的每一步,失败后都可通过消息队列进行重试处理。如 processor 入库失败,可将消息打回消息队列,继续回旋处理,达到最终一致。同时,可以在订阅的过程中对消费限速,避免线上突发峰值给系统带来灾难性的后果。

4.3 消息已读链路

钉钉IM系统的消息已读链路流程如下:

  • 1)用户对一条消息做读操作后,会发送请求到已读服务;
  • 2)已读服务收到请求后,直接将请求放到消息队列进行异步处理,同时可以达到削峰填谷的目的;
  • 3)已读服务处理完之后,将已读事件推给同步服务,让同步服务将已读事件推送给消息发送者。

从上面两个链路可以看出,消息队列是 IM 系统里非常重要的组成部分。

5、钉钉IM选择RocketMQ的原因

阿里内部曾有 notify、RocketMQ 两套应用消息中间件,也有其他基于 MQTT 协议实现的消息队列,最终都被 RocketMQ 统一。

IM 系统对消息队列有如下几个基本要求:

  • 1)解耦和削峰填谷(这是消息队列的基础能力);
  • 2)高性能、低时延;
  • 3)高可用性。

对于第 3)点:要求消息队列的高可用性方面不仅包括系统可用性,也包括数据可用性,要求写入消息队列时消息不丢失(钉钉 IM 对消息的保证级别是一条都不丢)。

RocketMQ 经过多次双 11 考验,其堆积性能、低时延、高可用已成为业届标杆,完全符合对消息队列的要求。

同时它的其他特性也非常丰富,如定时消息、事务消息,能够以极低的成本实现分布式定时任务,消息可重放和死信队列提供了后悔药的能力,比如线上系统出现 bug ,很多消息没有正确处理,可以通过重置位点、重新消费的方式,订正之前的错误处理。

另外:消息队列的使用场景非常丰富,RocketMQ 的扩展能力可以在消息发送和消费上做切面处理,实现通用性的扩展封装,大大降低开发工作量。 Tag & SQL 过滤能让下游针对性地订阅定业务需要的消息,无需订阅整个 topic 里的所有消息,大幅降低下游系统的订阅压力。

RocketMQ 至今从未发生故障,集群峰值 TPS 可达 300w/s,从生产到消费时延能够保证在 10 ms 以内,支持 30 亿条消息堆积,核心指标数据表现抢眼,性能异常优秀。

6、RocketMQ的消息必达3重保险

如上图所示,发消息流程中,很重要的一步是 receiver 应用做完消息能否发送的校验之后,通过 RocketMQ 将消息投递给 processor做消息入库处理。

投递过程中,将提供三重保险,以保证消息发送万无一失。

第一重保险:receiver 将消息写进 RocketMQ 时, RocketMQ SDK 默认会重试五次(每次尝试不同的 broker ,保障了消息写失败的概率非常小)。

第二重保险:写入 RocketMQ 失败的情况下,会尝试以 RPC 形式将消息投递给 processor 。

第三重保险:如果 RPC 形式也失败,会尝试将本地 redoLog 通过 Crontab 任务定时将消息回放到 RocketMQ 里面。

此外,如何在系统异常的情况下做到消息最终一致?

Processor 收到上游投递的消息时,会尝试对消息做入库处理。即使入库失败,依然会将消息投给同步服务,将消息下发,保证实时消息收发正常。异常情况时会将消息重新投递到异常 topic 进行重试,投递过程中通过设置RocketMQ 定时消息做退避处理,对异常 topic 做限速消费。

重试写不同的 topic 是为了与正常流量隔离,优先处理正常流量,防止因为异常流量消费而导致真正的线上消息处理被延迟。

另外:Rocket MQ 的一个 broker 默认只有一个 Retry 消息队列,如果消费失败量特别大的情况下,会导致下游负载不均,某些机器打死。

此外:如果系统持续发生异常,则会不断地进行回旋重试,如果不做限速处理,线上容易出现流量叠加,导致整个系统雪崩。

7、RocketMQ的独门绝技——分布式定时任务

在几千人的群里发一条消息,假设有 1/4 的成员同时开着聊天窗口,如果不对服务端已读服务和客户端需要更新的已读数做合并处理,更新的 QPS 会高达到 1000/s。钉钉能够支持十几万人的超大群,超大群的活跃对服务端和客户端都会带来很大冲击,而实际上用户的需求只需实现秒级更新。

针对以上场景:可以利用 RocketMQ 的定时消息能力实现分布式定时任务。

以已读流程为例(如下图所示),用户发起请求时,会将请求放入集中式请求队列,再通过 RocketMQ 定时消息生成定时任务,比如 5 秒后批量处理。5秒之后,RocketMQ 订阅到任务触发消息,将队列里面所有请求都取出处理。

▲ 用 RocketMQ 实现分布式定时任务的流程原理

我们抽象了一个分布式定时任务的组件,提供了很多其他实时性可达秒级的功能,如万人群的群状态更新、消息扩展更新都接入了此组件。通过组件的定时合并处理,大幅降低系统压力。

如上图(右边部分),在一些大群活跃的时间点成功地让流量下降并保持平稳状态。

8、钉钉IM使用RocketMQ遇到的技术问题

8.1 概述

RocketMQ 的生产端策略如下:

  • 1)生产者获取到对应 topic 所有 broker 和 Queue 列表,然后轮询写入消息;
  • 2)消费者端也会获取到 topic 所有 broker 和Queue列表;
  • 3)还需要要从 broker 中获取所有消费者 IP 列表进行排序(按照配置负载均衡,如哈希、一次性哈希等策略计算出自己应该订阅哪些 Queue)。

上图中:ConsumerGroupA的Consumer1被分配到MessageQueue0和MessageQueue1,则它订阅MessageQueue0和MessageQueue1。

在RocketMQ的使用过程中,我们面临了诸多问题,下面我们来逐一分享。

8.2 问题1:波浪式流量

我们发现订阅消息集群滚动时,CPU 呈现波浪式飙升。

经过深入排查发现,断网演练后进行网络恢复时,大量 producer 同时恢复工作,同时从第一个 broker 的第一个 Queue 开始写入消息,生产消息波浪式写入 RocketMQ ,进而导致消费者端出现波浪式流量。

最终,我们联系 RocketMQ 开发人员,调整了生产策略,每次生产者发现 broker 数量或状态发生变化时,都会随机选取一个初始Queue写入消息,以此解决问题。

另一个导致波浪式流量的问题是配置问题。

排查线上问题时,从 broker 视角看,每个 broker 的消息量都是平均的,但 consumer 之间流量相差特别大。最终通过在 producer 侧尝试抓包得以定位到问题,是由于 producer 写入消息时超时率偏高。

梳理配置后发现,是由于 producer 写入消息时配置超时太短,Rocket MQ 在写消息时会尝试多次,比如第一个 broker 写入失败后,将直接跳到下一个 broker 的第一个 Queue ,导致每个 broker 的第一个 Queue 消息量特别大,而靠后的 partition 几乎没有消息。

8.3 问题2:负载均衡维度太粗

负载均衡只能到Queue维度,导致需要不时地关注 Queue 数量。

比如线上流量增长过快,需要进行扩容,而扩容后发现机器数大于 Queue 数量,导致无论怎么扩容都无法分担线上流量,最终只能联系 RocketMQ 运维人员调高 Queue 数量来解决。

虽然调高 Queue 数量能解决机器无法订阅的问题,但因为负载均衡策略只到 Queue 维度,负载始终无法均衡。从下图可以看到, consumer 1 订阅了两个 Queue 而 consumer 2 只订阅了一个 Queue。

8.4 问题3:单机夯死导致消息堆积

单机夯死导致消息堆积,这也是负载均衡只能到 Queue 维度带来的副作用。

比如 Broker A 的 Queue 由 consumer 1 订阅,出现宿主机磁盘 IO 夯死但与 broker 之间的心跳依然正常,导致 Queue 消息长时间无法订阅进而影响用户接收消息。最终只能通过手动介入将对应机器下线来解决。

8.5 问题4:rebalance

Rocket MQ 的负载均衡由 client 自己计算,导致有机器异常或发布时,整个集群状态不稳定,时常会出现某些 Queue 有多个 consumer 订阅,而某些 Queue 在几十秒内没有 consumer 订阅的情况。

因而导致线上发布的时候,出现消息乱序或对方已回消息但显示未读的情况。

8.6 问题5:C++ SDK 能力缺失

钉钉IM的核心处理模块Receiver、processor 等应用都是通过 C++ 实现,而RocketMQ 的 C++ SDK 相比于 Java 存在较大缺失。经常出现内存泄漏或 CPU 飙高的情况,严重影响线上服务的稳定。

9、钉钉IM与RocketMQ的相互促进

面对以上困扰,在经过过多次讨论和共创后,最终孵化出 RocketMQ 5.0 POP 消费模式。

这是 RocketMQ 在实时系统里程碑式的升级,解决了大量实时系统使用 RocketMQ 过程中遇到的问题(如下图所示)。

1)Pop消费模式下,每一个 consumer 都会与所有 broker 建立长连接并具备消费能力,以 broker 维护整个消息订阅的负载均衡和位点。重云轻端的模式下,负载均衡、订阅消息、位点维护都在客户端完成,而新客户端只需做长链接管理、消息接收,并且通用 gRPC 协议,使得多语言比如 C++、Go、 Python 等语言客户端都能轻松实现,无需持续投入力去升级维护 SDK 。

2)broker能力升级更简单。重云轻端很好地解决了客户端版本升级问题,客户端改动的可能性和频率大大降低。以往升级新特性或能力只能推动所有相关 SDK 应用进行升级发布,升级过程中还需考虑新老兼容等问题,工作量极大。而新模式只需升级 broker 即可完成工作。

3)单机夯死消息能继续被消费。新模式下 consumer 和 broker 进行网状连接和消息订阅,由 broker 通过负载均衡策略平均分配消息给 consumer 进行消费,以往宕机夯死导致的 Queue 消息堆积问题也迎刃而解。如果 broker 发现 consumer 长时间没有进行消息 ACK ,则将不再对其投递消息,彻底解决单机夯死问题。

4)无需关注partition数量。

5)彻底解决rebalance。

6)负载更均衡。通过新的订阅模式,不管上游流量如何偏移,只要不超过单个 broker 的容量上限,消费端都能实现真正意义上的负载均衡。

POP 模式消费模式已经在钉钉 IM 场景磨合得非常成熟,在对可用性、性能、时延方面要求非常高的钉钉 IM 系统证明了自己,也证明了不断升级的 RocketMQ 是即时通讯场景消息队列的不二选择。

10、相关资料

[1] 现代IM系统中聊天消息的同步和存储方案探讨

[2] 企业级IM王者——钉钉在后端架构上的过人之处

[3] 深度解密钉钉即时消息服务DTIM的技术设计

[4] 钉钉——基于IM技术的新一代企业OA平台的技术挑战(视频+PPT)

[5] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

[6] IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

本文已同步发布于:http://www.52im.net/thread-4106-1-1.html

posted @ 2022-12-30 12:05 Jack Jiang 阅读(112) | 评论 (0)编辑 收藏

1、引言

在社区中,分享了很多篇基于Netty编写的IM聊天入门文章(比如《跟着源码学IM》系列、《基于Netty,从零开发IM》系列等),在这些文章中分享了各种IM通信算法原理和功能逻辑的实现。但是这样简单的IM聊天系统是比较容易被窃听的,如果想要在里面说点悄悄话是不太安全的。

怎么办呢?学过密码学的朋友可能就想到了一个解决办法,聊天的时候对消息加密,处理的时候再对消息进行解密。是的,道理就是这样。

但密码学本身的理论就很复杂,加上相关的知识和概念又太多太杂,对于IM入门者来说,想要快速理清这些概念并实现合适的加解密方案,是比较头疼的。

本文正好借此机会,以Netty编写的IM聊天加密为例,为入门者理清什么是PKI体系、什么是SSL、什么是OpenSSL、以及各类证书和它们间的关系等,并在文末附上简短的Netty代码实示例,希望能助你通俗易懂地快速理解这些知识和概念!

补充说明:本文为了让文章内容尽可能言简意赅、通俗易懂,尽量不深入探讨各个技术知识和概念,感兴趣的读者可以自行查阅相关资料进一步学习。

学习交流:

本文已同步发布于:http://www.52im.net/thread-4104-1-1.html

2、相关文章

  1. 即时通讯安全篇(一):正确地理解和使用Android端加密算法
  2. 即时通讯安全篇(二):探讨组合加密算法在IM中的应用
  3. 即时通讯安全篇(三):常用加解密算法与通讯安全讲解
  4. 即时通讯安全篇(四):实例分析Android中密钥硬编码的风险
  5. 即时通讯安全篇(五):对称加密技术在Android平台上的应用实践
  6. 即时通讯安全篇(六):非对称加密技术的原理与应用实践
  7. 即时通讯安全篇(十):IM聊天系统安全手段之通信连接层加密技术
  8. 即时通讯安全篇(十一):IM聊天系统安全手段之传输内容端到端加密技术

3、什么是PKI?

我们需要先了解一下公钥和私钥的加密标准体系PKI。

3.1 基本概念

PKI的全称是Public Key Infrastructure,是指支持公钥管理体制的基础设施,提供鉴别、加密、完整性和不可否认性服务。

通俗讲:PKI是集机构、系统(硬件和软件)、人员、程序、策略和协议为一体,利用公钥概念和技术来实现和提供安全服务的、普适性的安全基础设施。

在公钥密码中,发送者用公钥(加密密钥)加密,接收者用私钥(解密密钥)解密。公钥一般是公开的,不再担心窃听,这解决了对称密码中的密钥配送问题。但是接收者依然无法判断收到的公钥是否合法(有可能是中间人假冒的)。

事实上,仅靠公钥密码本身,无法防御中间人攻击。于是,需要(认证机构)对公钥进行签名,从而确认公钥没有被篡改。加了数字签名的公钥称为公钥证书,一般简称证书。

有了证书来认证,可以有效防御中间人攻击,随之带来了一系列非技术性工作。

例如:谁来发证书?如何发证书?不同机构的证书怎么互认?纸质证书作废容易,数字证书如何作废?解决这些问题,需要制定统一的规则,即PKI体系。

PKI体系是通过颁发、管理公钥证书的方式为终端用户提供服务的系统,最核心的元素是证书。

围绕证书构成了PKI体系的要素:

  • 1)使用PKI的用户;
  • 2)颁发证书的机构(Certificate Authority,CA);
  • 3)保存证书的仓库。

总之:PKI是一个总称,既包括定义PKI的基础标准,也包括PKI的应用标准。

3.2 PKI体系现状

事实上PKI已经有两代了。

第一代的PKI标准主要是由美国RSA公司的公钥加密标准PKCS、国际电信联盟的ITU-T X.509、IETF的X.509、WAP和WPKI等标准组成。但是因为第一代PKI标准是基于抽象语法符号ASN.1进行编码的,实现起来比较复杂和困难,所以产生了第二代PKI标准。

第二代PKI标准是由微软、VeriSign和webMethods三家公司在2001年发布的基于XML的密钥管理规范也叫做XKMS。

事实上现在CA中心使用的最普遍的规范还是X.509系列和PKCS系列。

X.509系列主要由X.209、X.500和X.509组成,其中X.509是由国际电信联盟(ITU-T)制定的数字证书标准。在X.500基础上进行了功能增强,X.509是在1988年发布的。

X.509证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。

而PKCS是美国RSA公司的公钥加密标准,包括了证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。它定义了一系列从PKCS#1到PKCS#15的标准。

其中最常用的是PKCS#7、PKCS#12和PKCS#10。PKCS#7 是消息请求语法,常用于数字签名与加密,PKCS#12是个人消息交换与打包语法主要用来生成公钥和私钥(题外话:iOS程序员对PKCS#12不陌生,在实现APNs离线消推送时就需要导出.p12证明,正是这个)。PKCS#10是证书请求语法。

4、什么是SSL?

4.1 基本概念

SSL(全称 Secure Socket Layer)安全套接层是网景公司(Netscape)率先采用的网络安全协议。它是在传输通信协议(TCP/IP)上实现的一种安全协议,采用公开密钥技术。

通俗地说:SSL被设计成使用TCP来提供一种可靠的端到端的安全服务,它不是单个协议,而是二层协议。低层是SSL记录层,用于封装不同的上层协议,另一层是被封装的协议,即SSL握手协议,它可以让服务器和客户机在传输应用数据之前,协商加密算法和加密密钥,客户机提出自己能够支持的全部加密算法,服务器选择最适合它的算法。

SSL特点是:它与应用层协议独立无关。上层的应用层协议(例如:HTTP、FTP、Telnet等)能透明的建立于SSL协议之上。SSL协议在应用层协议通信之前就已经完成加密算法、通信密钥的协商以及服务器认证工作。在此之后应用层协议所传送的数据都会被加密,从而保证通信的私密性。

4.2 与TLS的关系

SSL是网景公司(Netscape)设计,但IETF将SSL作了标准化,即RFC2246,并将其称为TLS(Transport Layer Security),其最新版本是RFC5246、版本1.2。

实际上:TLS是IETF在SSL3.0基础上设计的,相当于SSL的后续版本。所以我们通常都是SSL/TLS放一起说。

5、什么是OpenSSL?

5.1 基本概念

 

OpenSSL是一个开放源代码的软件库,应用程序可以使用这个包来进行安全通信,它包括代码、脚本、配置和过程的集合。例如:如果您正在编写一个需要复杂安全加密的软件,那么只有添加一个安全加密库才有意义,这样您就不必自己编写一大堆复杂的加解密函数(而且密码学本身很复杂,要写好它们并不容易)。

其主要库是以 C 语言所写成,实现了基本的加密功能,实现了 SSL 与 TLS 协议。

OpenSSL整个软件包大概可以分成三个主要功能部分:

  • 1)SSL协议库;
  • 2)应用程序;
  • 3)密码算法库。

OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。

OpenSSL 可以运行在 OpenVMS、 Microsoft Windows 以及绝大多数类 Unix 操作系统上。

5.2 具体来说

密钥和证书管理是PKI的一个重要组成部分,OpenSSL为之提供了丰富的功能,支持多种标准。

OpenSSL实现了ASN.1的证书和密钥相关标准,提供了对证书、公钥、私钥、证书请求以及CRL等数据对象的DER、PEM和BASE64的编解码功能。

OpenSSL提供了产生各种公开密钥对和对称密钥的方法、函数和应用程序,同时提供了对公钥和私钥的DER编解码功能。并实现了私钥的PKCS#12和PKCS#8的编解码功能。

OpenSSL在标准中提供了对私钥的加密保护功能,使得密钥可以安全地进行存储和分发。

在此基础上,OpenSSL实现了对证书的X.509标准编解码、PKCS#12格式的编解码以及PKCS#7的编解码功能。并提供了一种文本数据库,支持证书的管理功能,包括证书密钥产生、请求产生、证书签发、吊销和验证等功能。

5.3 发展历程

OpenSSL 计划在 1998 年开始,其目标是发明一套自由的加密工具,在互联网上使用。

OpenSSL 以 Eric Young 以及 Tim Hudson 两人开发的 SSLeay 为基础,随着两人前往 RSA 公司任职,SSLeay 在 1998 年 12 月停止开发。因此在 1998 年 12 月,社群另外分支出 OpenSSL,继续开发下去。

▲ 上图为 Tim Hudson

OpenSSL 管理委员会当前由 7 人组成有 13 个开发人员具有提交权限(其中许多人也是 OpenSSL 管理委员会的一部分)。只有两名全职员工(研究员),其余的是志愿者。

该项目每年的预算不到 100 万美元,主要依靠捐款。 TLS 1.3 的开发由 Akamai 赞助。

5.4 下载方法

OpenSSL可以从其官网上下载,地址是:https://www.openssl.org/source/,感兴趣的读者可以自行下载安装研究。

6、各类证书

6.1 证书类型

操作过证书的朋友可能会对各种证书类型眼花缭乱,典型的体现就是各种不同的证书扩展名上,一般来说会有DER、CRT、CER、PEM这几种证书的扩展名。

以下是最常见的几种:

  • 1)DER文件:表示证书的内容是用二进制进行编码的;
  • 2)PEM文件:是一个文本文件,其内容是以“ - BEGIN -” 开头的,Base64编码的字符;
  • 3)CRT和CER文件:基本上是等价的,他们都是证书的扩展,也是文本文件,不同的是CRT通常用在liunx和unix系统中,而CER通常用在windows系统中。并且在windows系统中,CER文件会被MS cryptoAPI命令识别,可以直接显示导入和/或查看证书内容的对话框;
  • 4)KEY文件:主要用来保存PKCS#8标准的公钥和私钥。

6.2 常用OpenSSL命令

下面的命令可以用来查看文本证书内容:

openssl x509 -incert.pem -text -noout

openssl x509 -incert.cer -text -noout

openssl x509 -incert.crt -text -noout

下面的命令可以用来查看二进制证书内容:

openssl x509 -incert.der -inform der -text -noout

下面是常见的PEM和DER相互转换。

PEM到DER的转换:

openssl x509 -incert.crt -outform der-out cert.der

DER到PEM的转换:

openssl x509 -incert.crt -inform der -outform pem -out cert.pem

补充说明:上述命令中用到的openssl程序,就是本文中提到的OpenSSL开源库提供的程序。

7、Netty中的聊天加密代码示例

7.1 关于Netty

Netty是一个Java NIO技术的开源异步事件驱动的网络编程框架,用于快速开发可维护的高性能协议服务器和客户端,事实上用Java开发IM系统时,Netty是几乎是首选。

有关Netty的介绍我就不啰嗦了,如果不了解那就详读以下几篇:

史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!

新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析

史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战

基它有关Netty的重要资料:

Netty-4.1.x 源码 (在线阅读版)

Netty-4.1.x API文档 (在线查阅版)

7.2 启动SSL Server代码示例

事实上这个标题是不对的,Netty中启动的server还是原来那个server,只是对发送的消息进行了加密解密处理。也就是说添加了一个专门进行SSL操作的Handler。

netty中代表ssl处理器的类叫做SslHandler,它是SslContext工程类的一个内部类,所以我们只需要创建好SslContext即可通过调用newHandler方法来返回SslHandler。

让服务器端支持SSL的代码:

ChannelPipeline p = channel.pipeline();

  SslContext sslCtx = SslContextBuilder.forServer(...).build();

  p.addLast("ssl", sslCtx.newHandler(channel.alloc()));

让客户端支持SSL的代码:

ChannelPipeline p = channel.pipeline();

   SslContext sslCtx = SslContextBuilder.forClient().build();

   p.addLast("ssl", sslCtx.newHandler(channel.alloc(), host, port));

netty中SSL的实现有两种方式,默认情况下使用的是OpenSSL,如果OpenSSL不可以,那么将会使用JDK的实现。

要创建SslContext,可以调用SslContextBuilder.forServer或者SslContextBuilder.forClient方法。

这里以server为例,看下创建流程。

SslContextBuilder有多种forServer的方法,这里取最简单的一个进行分析:

publicstaticSslContextBuilder forServer(File keyCertChainFile, File keyFile) {

    returnnewSslContextBuilder(true).keyManager(keyCertChainFile, keyFile);

}

该方法接收两个参数:

  • 1)keyCertChainFile是一个PEM格式的X.509证书文件;
  • 2)keyFile是一个PKCS#8的私钥文件。

熟悉OpenSSL的童鞋应该知道使用openssl命令可以生成私钥文件和对应的自签名证书文件。

具体openssl的操作可以查看我的其他文章,这里就不详细讲解了。

除了手动创建证书文件和私钥文件之外,如果是在开发环境中,大家可能希望有一个非常简单的方法来创建证书和私钥文件,netty为大家提供了SelfSignedCertificate类。

看这个类的名字就是知道它是一个自签名的证书类,并且会自动将证书文件和私钥文件生成在系统的temp文件夹中,所以这个类在生产环境中是不推荐使用的。默认情况下该类会使用OpenJDK's X.509来生成证书的私钥,如果不可以,则使用 Bouncy Castle作为替代。

7.3 启动SSL Client代码示例

同样的在client中支持SSL也需要创建一个handler。

客户端的SslContext创建代码如下:

// 配置 SSL.

finalSslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

上面的代码我们使用了一个InsecureTrustManagerFactory.INSTANCE作为trustManager。

什么是trustManager呢?

当客户端和服务器端进行SSL连接的时候,客户端需要验证服务器端发过来证书的正确性。

通常情况下,这个验证是到CA服务器中进行验证的,不过这样需要一个真实的CA证书环境,所以在测试中,我们使用InsecureTrustManagerFactory,这个类会默认接受所有的证书,忽略所有的证书异常。

当然:CA服务器也不是必须的,客户端校验的目的是查看证书中的公钥和发送方的公钥是不是一致的,那么对于不能联网的环境,或者自签名的环境中,我们只需要在客户端校验证书中的指纹是否一致即可。

netty中提供了一个FingerprintTrustManagerFactory类,可以对证书中的指纹进行校验。

该类中有个fingerprints数组,用来存储安全的授权过的指纹信息。通过对比传入的证书和指纹,如果一致则校验通过。

使用openssl从证书中提取指纹的步骤如下:

openssl x509 -fingerprint -sha256 -inmy_certificate.crt

8、小结一下

上面我们对Netty聊天用到的加密技术和相关概念进行了梳理,我来简单这些概念之间的关系。

这些概念之间的关系,简单来说就是:

  • 1)PKI:是一套加密体系和标准的合集,它是理论方案;
  • 2)SSL:是利用了PKI理论体系,针对Socket网络这个场景设计的一套安全通信标准,属于是PKI的一个具体应用场景;
  • 3)OpenSSL:是PKI体系及SSL标准的算法和代码实现,它包括了具体的开源代码、工具程序等;
  • 4)各种证书:是在SSL或其它基于PKI体系的安全协议标准中需要使用的到一些加密凭证文件等。

而具体到Netty中的聊天加密,那就是应用了上述的PKI体系,基于SSL协议,在OpenSSL等开源库的帮助下实现的安全程序。

9、参考资料

[1] 公钥基础设施(PKI)国际标准进展

[2] 一篇文章让你彻底弄懂SSL/TLS协议

[3] 什么是OpenSSL?它有什么用途

[4] OpenSSL是什么软件

[5] netty系列之对聊天进行加密

[6] 跟着源码学IM

[7] 基于Netty,从零开发IM

[8] TCP/IP详解(全网唯一在线阅读版)

[9] 快速理解TCP协议一篇就够

[10] Netty-4.1.x 源码(在线阅读版)

[11] Netty-4.1.x API文档(在线版)

本文已同步发布于http://www.52im.net/thread-4104-1-1.html

posted @ 2022-12-22 17:34 Jack Jiang 阅读(101) | 评论 (0)编辑 收藏

     摘要: 本文由陶文分享,InfoQ编辑发布,有修订和改动。1、前言本系列的前几篇主要是从各个角度讲解Protobuf的基本概念、技术原理这些内容,但回过头来看,对比JSON这种事实上的数据协议工业标准,Protobuf到底性能到底高多少?本篇将以Protobuf为基准,对比市面上的一些主流的JSON解析库,通过全方位测试来证明给你看看Protobuf到底比JSON快几倍。学习交流:- 移动端IM开发入门文...  阅读全文

posted @ 2022-12-16 12:43 Jack Jiang 阅读(123) | 评论 (0)编辑 收藏

关于MobileIMSDK

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。

工程开源地址是:

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► 版本更新记录:http://www.52im.net/thread-1217-1-1.html
► 全部运行截图:Android端iOS端
► 在线体验下载:专业版(TCP协议)专业版(UDP协议)      (关于 iOS 端,请:点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

* RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架  MobileIMSDK 实现)。

v8.3 版更新内容

此版更新内容更多历史更新日志):

(1)Android端主要更新内容bug修复及优化!】:

  • 1)[bug] 当首页“消息”列表所有的item都是置顶时,取消其中任一个置顶,都会错误地将其排在列表首位而不是列表末尾;
  • 2)[bug] 解决了从首页“消息”列表中遗留的陌生人聊天信息无法重置消息未读数的问题;
  • 3)[bug] 解决了聊天界面中底部面板和输入法软键盘切换时ui发生弹跳的问题;
  • 4)[优化] 重构了APP包名、应用名,防止被某些手机误报成恶意软件。
  • 5)[优化] 重构了搜索功能相关的代码,使之更易理解和维护;
  • 6)[优化] 优化了APP中各种文本输入框UI效果,以及其它UI细节;
  • 7)[优化] 解决了自定义长按菜单在某些机型上item文字会换行的问题;
  • 8)[优化] 大文件发送时,选择的图片、视频文件可以自动以图片消息和短视频消息的形式发送;
  • 9)[优化] 优化了APP处于后台时,收到实时语音/视频请求的通知形式(用高优先级的系统Notification方式提醒用户)。 

(2)服务端主要更新内容:

  • 1)[bug] 解决了uid登陆时的sql注入风险;
  • 2)[优化] 升级MobileIMSDK至v6.2正式版

此版主要功能运行截图更多截图点此查看): 

posted @ 2022-12-07 15:17 Jack Jiang 阅读(101) | 评论 (0)编辑 收藏

     摘要: 本文由腾讯PCG后台开发工程师的SG4YK分享,进行了修订和和少量改动。1、引言近日学习了 Protobuf 的编码实现技术原理,借此机会,正好总结一下并整理成文。接上篇《由浅入深,从根上理解Protobuf的编解码原理》,本篇将从Base64再到Base128编码,带你一起从底层来理解Protobuf的数据编码原理。本文结构总体与 Protobuf 官方文档相似,不少内容也来自官方文档,并在官方...  阅读全文

posted @ 2022-12-02 12:33 Jack Jiang 阅读(134) | 评论 (0)编辑 收藏

     摘要: 本文由码农的荒岛求生陆小风分享,为了提升阅读体验,进行了较多修订和排版。1、引言搞即时通讯IM方面开发的程序员,在谈到通讯层实现时,必然会提到网络编程。那么计算机网络编程中的一个非常基本的问题:到底该怎样组织Client与server之间交互的数据呢?本篇文章我们不讨论IM系统中的那些高端技术话题,我们回归到通讯的本质——也就是数据在网络中交互时的编解码原理,并由浅入深从底...  阅读全文

posted @ 2022-11-24 11:43 Jack Jiang 阅读(137) | 评论 (0)编辑 收藏

本文由vivo技术团队Li Guanyun分享,为了提升阅读体验,行了较多修订和重新排版。

1、引言

Protobuf 作为一种跨平台、语言无关、可扩展的序列化结构数据通讯协议,已广泛应用于网络数据交换的场景中(比如IM通信、分布式RPC调用等)。

随着互联网的发展,分布式系统的异构性会愈发突出,跨语言的需求会愈加明显,同时 gRPC 也大有取代Restful之势,而 Protobuf 作为gRPC 跨语言、高性能的法宝,我们技术人有必要深入理解 Protobuf 原理,为以后的技术更新和选型打下基础。

借此机会,我将个人的Protobuf学习过程以及实践经验,总结成文,与大家一起探讨学习。本篇主要从Protobuf的基础概念开始,包括技术背景、技术原理、使用方法和优缺点。

PS:本篇本跟上篇《Protobuf从入门到精通,一篇就够!》类似,都适合作为Protobuf的入门文章,但本篇力求简洁,尽量不涉及Protobuf的具体技术细节,目的是降低阅读的门槛、提升阅读效果,希望对你有用。

学习交流:

(本文已同步发布于:http://www.52im.net/thread-4081-1-1.html

2、系列文章

本文是系列文章中的第 2 篇,本系列总目录如下:

  • IM通讯协议专题学习(一):Protobuf从入门到精通,一篇就够!
  • IM通讯协议专题学习(二):快速理解Protobuf的背景、原理、使用、优缺点》(* 本文
  • 《IM通讯协议专题学习(三):由浅入深,从通信编解码原理上理解Protobuf》(稍后发布..)
  • 《IM通讯协议专题学习(四):从Base64到Protobuf,详解Protobuf的数据编码原理》(稍后发布..)
  • 《IM通讯协议专题学习(五):Protobuf到底比JSON快几倍?请看全方位实测!》(稍后发布..)
  • 《IM通讯协议专题学习(六):手把手教你如何在Android上从零使用Protobuf》(稍后发布..)
  • 《IM通讯协议专题学习(七):手把手教你如何在NodeJS中从零使用Protobuf》(稍后发布..)
  • 《IM通讯协议专题学习(八):金蝶随手记团队的Protobuf应用实践(原理篇)  》(稍后发布..)
  • 《IM通讯协议专题学习(九):金蝶随手记团队的Protobuf应用实践(实战篇) 》(稍后发布..)

3、什么是Protobuf?

Protobuf(全称是Protocol Buffers)是一种跨平台、语言无关、可扩展的序列化结构数据的方法,可用于网络通信数据交换及存储。

在序列化结构化数据的机制中,Protobuf是灵活、高效、自动化的,相对常见的XML、JSON,描述同样的信息,Protobuf序列化后数据量更小、序列化/反序列化速度更快、更简单。

一旦定义了要处理的数据的数据结构之后,就可以利用Protobuf的代码生成工具生成相关的代码。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言(proto3支持C++, Java, Python, Go, Ruby, Objective-C, C#)或从各种不同流中对你的结构化数据轻松读写。

PS:类似的介绍,在上篇《Protobuf从入门到精通,一篇就够!》中也有涉及,有兴趣可以一并阅读之。

4、为什么是 Protobuf?

4.1 技术背景

大家可能会觉得 Google 发明 Protobuf 是为了解决序列化速度的,其实真实的原因并不是这样的。

Protobuf最先开始是 Google用来解决索引服务器 request/response 协议的。

在没有Protobuf之前,Google 已经存在了一种 request/response 格式,用于手动处理 request/response 的编解码。

这种sstk式也能支持多版本协议,不过代码不够优雅:

if(protocolVersion=1) {

    doSomething();

} elseif(protocolVersion=2) {

    doOtherThing();

} ...

如果是非常明确的格式化协议,会使新协议变得非常复杂。因为开发人员必须确保请求发起者与处理请求的实际服务器之间的所有服务器都能理解新协议,然后才能切换开关以开始使用新协议。

这也就是每个服务器开发人员都遇到过的低版本兼容、新旧协议兼容相关的问题。

为了解决这些问题,于是Protobuf就诞生了。

4.2 Protobuf 诞生了

Protobuf 最初被寄予以下 2 个期望:

  • 1)更容易引入新的字段,并且不需要检查数据的中间服务器可以简单地解析并传递数据(而无需了解所有字段);
  • 2)数据格式更加具有自我描述性,可以用各种语言来处理(比如C++, Java 等各种语言)。

但这个版本的 Protobuf 仍需要自己手写解析的代码。

随着Protobuf的发展、演进,它具有了更多的特性:

  • 1)自动生成的序列化和反序列化代码(避免了手动解析的需要。官方提供自动生成代码工具,各个语言平台的基本都有);
  • 2)除了用于数据交换之外,Protobuf也被用作某些持久化数据的便捷自描述格式。

Protocol Buffers 命名的由来:

Why the name "Protocol Buffers"?

The name originates from the early days of the format, before we had the protocol buffer compiler to generate classes for us. At the time, there was a class called ProtocolBuffer which actually acted as a buffer for an individual method. Users would add tag/value pairs to this buffer individually by calling methods like AddValue(tag, value). The raw bytes were stored in a buffer which could then be written out once the message had been constructed.

Since that time, the "buffers" part of the name has lost its meaning, but it is still the name we use. Today, people usually use the term "protocol message" to refer to a message in an abstract sense, "protocol buffer" to refer to a serialized copy of a message, and "protocol message object" to refer to an in-memory object representing the parsed message.

4.3 Protobuf 在谷歌业务中的地位

Protobuf 现在是 Google 用于数据交换和存储的通用语言。

谷歌代码树中定义了 48162 种不同的消息类型,包括 12183 个 .proto 文件。它们既用于 RPC 系统,也用于在各种存储系统中持久存储数据。

Protobuf 诞生之初是为了解决服务器端新旧协议(高低版本)兼容性问题,名字也很体贴——“协议缓冲区”,只不过后期慢慢发展成用于传输数据。

5、Protobuf 协议的工作原理

如下图所示:可以看到,对于序列化协议来说,使用方只需要关注业务对象本身,即 idl 定义,序列化和反序列化的代码只需要通过工具生成即可。

6、Protobuf 协议的消息定义

Protobuf 的消息是在idl文件(.proto)中描述的。

下面是本次样例中使用到的消息描述符 customer.proto

syntax = "proto3";

 

package domain;

 

option java_package = "com.Protobuf.generated.domain";

option java_outer_classname = "CustomerProtos";

 

message Customers {

    repeated Customer customer = 1;

}

 

message Customer {

    int32 id= 1;

    string firstName = 2;

    string lastName = 3;

 

    enum EmailType {

        PRIVATE = 0;

        PROFESSIONAL = 1;

    }

 

    message EmailAddress {

        string email = 1;

        EmailType type= 2;

    }

 

    repeated EmailAddress email = 5;

}

上面的消息比较简单,Customers包含多个Customer(Customer包含一个id字段、一个firstName字段、一个lastName字段以及一个email的集合)。

除了上述定义外,文件顶部还有三行可帮助代码生成器的申明:

  • 1)syntax = "proto3":用于idl语法版本,目前有两个版本proto2和proto3,两个版本语法不兼容,如果不指定,默认语法是proto2(由于proto3比proto2支持的语言更多,语法更简洁,本文使用的是proto3);
  • 2)package domain:此配置用于嵌套生成的类/对象;
  • 3)option java_package:生成器还使用此配置来嵌套生成的源(此处的区别在于这仅适用于Java,在使用Java创建代码和使用JavaScript创建代码时,使用了两种配置来使生成器的行为有所不同。也就是说,Java类是在包com.Protobuf.generated.domain下创建的,而JavaScript对象是在包domain下创建的)。

Protobuf 提供了更多选项和数据类型,本文不做详细介绍,感兴趣可以参考官方文档

7、Protobuf 的代码生成

首先安装 Protobuf 编译器 protoc(点这里有详细的安装教程)。

安装完成后,可以使用以下命令生成 Java 源代码:

1protoc --java_out=./src/main/java./src/main/idl/customer.proto

上述命令的意图是:从项目的根路径执行该命令,并添加了两个参数 java_out(即定义 ./src/main/java/ 为Java代码的输出目录;而 ./src/main/idl/customer.proto 是.proto文件所在目录)。

生成的代码非常复杂,但幸运的是它的用法却非常简单:

CustomerProtos.Customer.EmailAddress email = CustomerProtos.Customer.EmailAddress.newBuilder()

        .setType(CustomerProtos.Customer.EmailType.PROFESSIONAL)

        .setEmail("crichardson@email.com").build();

 

CustomerProtos.Customer customer = CustomerProtos.Customer.newBuilder()

        .setId(1)

        .setFirstName("Lee")

        .setLastName("Richardson")

        .addEmail(email)

        .build();

// 序列化

byte[] binaryInfo = customer.toByteArray();

System.out.println(bytes_String16(binaryInfo));

System.out.println(customer.toByteArray().length);

// 反序列化

CustomerProtos.Customer anotherCustomer = CustomerProtos.Customer.parseFrom(binaryInfo);

System.out.println(anotherCustomer.toString());

8、Protobuf 的性能数据

我们简单地以上述Customers为模型,分别构造、选取小对象、普通对象、大对象进行性能对比。

序列化耗时以及序列化后数据大小对比:

反序列化耗时:

更多性能数据可以参考官方的测试Benchmark

9、Protobuf 的优点

9.1效率高

从序列化后的数据体积角度,与XML、JSON这类文本协议相比,Protobuf通过 T-(L)-V(TAG-LENGTH-VALUE)方式编码,不需要", {, }, :等分隔符来结构化信息。同时在编码层面使用varint压缩。

所以描述同样的信息,Protobuf序列化后的体积要小很多,在网络中传输消耗的网络流量更少,进而对于网络资源紧张、性能要求非常高的场景。比如在移动网络下的IM即时通讯应用中,Protobuf协议就是非常不错的选择(PS:这也是我为什么着手分享Protobuf系列文章的原因啦)。

我们来简单做个对比。

要描述如下JSON数据:

1{"id":1,"firstName":"Chris","lastName":"Richardson","email":[{"type":"PROFESSIONAL","email":"crichardson@email.com"}]}

使用JSON序列化后的数据大小为118byte:

7b226964223a312c2266697273744e616d65223a224368726973222c226c6173744e616d65223a2252696368617264736f6e222c22656d61696c223a5b7b2274797065223a2250524f46455353494f4e414c222c22656d61696c223a226372696368617264736f6e40656d61696c2e636f6d227d5d7d

而使用Protobuf序列化后的数据大小为48byte:

0801120543687269731a0a52696368617264736f6e2a190a156372696368617264736f6e40656d61696c2e636f6d1001

从序列化/反序列化速度角度,与XML、JSON相比,Protobuf序列化/反序列化的速度更快,比XML要快20-100倍。

9.2支持跨平台、多语言

Protobuf是平台无关的,无论是Android、iOS、PC,还是C#与Java,都可以利用Protobuf进行无障碍通讯。

proto3支持C++、Java、Python、Go、Ruby、Objective-C、C#(详见《Protobuf从入门到精通,一篇就够》)。

9.3扩展性、兼容性好

Protobuf具有向后兼容的特性:更新数据结构以后,老版本依旧可以兼容,这也是Protobuf诞生之初被寄予解决的问题,因为编译器对不识别的新增字段会跳过不处理。

9.4使用简单

Protobuf 提供了一套编译工具,可以自动生成序列化、反序列化的样板代码,这样开发者只要关注业务数据idl,简化了编码解码工作以及多语言交互的复杂度。

10、Protobuf 的缺点

Protobuf的优点很突出,但缺点也很明显。

Protobuf的缺点主要是:

  • 1)不具备自描述能力:跟XML、JSON相比,这两者是自描述的,而ProtoBuf则不是;
  • 2)数据可读性非常差:ProtoBuf是二进制协议,如果没有idl文件,就无法理解二进制数据流,对调试非常不友好。

不过:Charles已经支持Protobuf协议,导入数据的描述文件即可,详情可参考 Charles Protocol Buffers

然而:由于没有idl文件无法解析二进制数据流,ProtoBuf在一定程度上可以保护数据,提升核心数据被破解的门槛,降低核心数据被盗爬的风险(也算是缺点变优点的典型范例)。

11、参考资料

[1] Protobuf官方网站

[2] Protobuf从入门到精通,一篇就够!

[3] 如何选择即时通讯应用的数据传输格式

[4] 强列建议将Protobuf作为你的即时通讯应用数据传输格式

[5] APP与后台通信数据格式的演进:从文本协议到二进制协议

[6] 面试必考,史上最通俗大小端字节序详解

[7] 移动端IM开发需要面对的技术问题(含通信协议选择)

[8] 简述移动端IM开发的那些坑:架构设计、通信协议和客户端

[9] 理论联系实际:一套典型的IM通信协议设计详解

[10] 58到家实时消息系统的协议设计等技术实践分享

(本文已同步发布于:http://www.52im.net/thread-4081-1-1.html

posted @ 2022-11-17 10:52 Jack Jiang 阅读(92) | 评论 (0)编辑 收藏

为了更好地分类阅读52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第5 期。

* 评语:本系列文章尽量使用最浅显易懂的文字、图片来组织内容,力求通信技术零基础的人群也能看懂。但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获。特别推荐即时通讯开发者来阅读,因为针对移动弱网的问题,确实可以找到很多有价值的答案。


[- 1 -] IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)

[链接]http://www.52im.net/thread-2354-1-1.html

[摘要] 本文(上下两篇)将带你了解当今通信交换技术最初的模样以及发展过程。学习技术更要了解技术的前世今生,技术本无聊,故事很有趣。


[- 2 -]IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

[链接]http://www.52im.net/thread-2356-1-1.html

[摘要] 接上篇,本篇里我们需要暂停一下,回过头来看看我们国家的交换机发展情况。


[- 3 -] IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

[链接] http://www.52im.net/thread-2360-1-1.html

[摘要] 本文通过大量珍贵历史图片,从中国第一条电报线路,到如今触手可及的5G网络,回顾过去、展望未来,一起来看国人通信方式的百年历史变迁。


[- 4 -]IM开发者的零基础通信技术入门(四):手机的演进,史上最全移动终端发展史

[链接] http://www.52im.net/thread-2369-1-1.html

[摘要] 本文将通过大量历史图片,讲述手机这种移动终端的演化过程,为您呈现如今已深度融入人类生活的智能手机本来的样子。了解过去,才能更好地展望未来。


[- 5 -] IM开发者的零基础通信技术入门(五):1G到5G,30年移动通信技术演进史

[链接] http://www.52im.net/thread-2373-1-1.html

[摘要] 今天的5G,3.5GHz+大规模MIMO+波束赋形,还有固定无线应用,不禁让人看到了当年3G时代WiMax的影子,但WiMax为何输给了LTE,难道命运也喜欢对技术开玩笑吗?一部跨越三十年惊心动魄的移动通信史,为你揭晓答案。


[- 6 -] IM开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术

[链接] http://www.52im.net/thread-2375-1-1.html

[摘要]自上个世纪70年代末移动通信网络诞生以来,移动通信基站已经陪伴人类40年了,为人类社会带来了空前的变革,但你知道它的故事吗?


[- 7 -] IM开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”

[链接] http://www.52im.net/thread-2382-1-1.html

[摘要] 本文将回归到无线通信的技术之魂——“电磁波”,尽量用通俗易懂的文字讲述这个稍显枯燥的通信技术基础知识。


[- 8 -] IM开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲

[链接] http://www.52im.net/thread-2385-1-1.html

[摘要] 实际生活中,无线通信中的天线都长什么样?有哪些用途?更重要的是,天线的技术原理是怎样的?本文将通过大量的图片,为你讲述这些内容。本文力求通俗易懂,面向零基础读者,希望继续给即时通讯网的开发者带来更多通信技术方面的收获。


[- 9 -] IM开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”

[链接]http://www.52im.net/thread-2391-1-1.html

[摘要] 对于通信专业的人来说,几乎每个人都认为核心网难(不只是难,而且是非常难),很难有人能通俗易懂地讲明白它是什么东西。所以本文想借此机会,为零基础的IM开发者或其他移动端应用层程序员们,讲清楚这个话题。


[- 10 -] IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲

[链接] http://www.52im.net/thread-2394-1-1.html

[摘要] 作为IM开发者,或者移动端开发者来说,提前了解5G技术显然是很有必要的。那么什么是5G技术?技术原理是怎么样的?5G技术将带来哪些技术革新?本文将以零基础的应用程序开发者为阅读对象,帮你找到这些问题的答案。


[- 11 -] IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

[链接] http://www.52im.net/thread-2402-1-1.html

[摘要] 为什么WiFi信号会受影响?什么情况下该使用何种方式组网?如何改善WiFi信号差的问题?等等,本文将通俗易懂地为你找到这些问题的答案。


[- 12 -] IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

[链接]http://www.52im.net/thread-2406-1-1.html

[摘要] 本文将详细介绍生活中遇到的常见网络问题,及可能的解决方法,虽说是一篇技术文章,但内容将一如既往地通俗易懂,简单实用。


[- 13 -] IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

[链接] http://www.52im.net/thread-2415-1-1.html

[摘要] 关于手机信号的问题真的不是大家想象得那么简单。本文正好收集整理了这一块的通信技术知识,一如既往的力求通俗易懂,希望对你有用。


[- 14 -] IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

[链接] http://www.52im.net/thread-2419-1-1.html

[摘要] 为什么在高铁上手机信号会这么差?这个无线通信难题真的无法解决吗?今天,作为通信老司机的笔者,就详细和大家聊聊这个问题。


[- 15 -] IM开发者的零基础通信技术入门(十五):理解定位技术,一篇就够

[链接]http://www.52im.net/thread-2428-1-1.html

[摘要] 定位技术到底是怎么实现的?技术原理怎样?有哪些局限性?貌似我们平时也没有做更多了解,既然这样,那就跟着本文来一窥究竟吧。


👉52im社区本周新文:《IM通讯协议专题学习(一):Protobuf从入门到精通,一篇就够! http://www.52im.net/thread-4080-1-1.html》,欢迎阅读!👈

我是Jack Jiang,我为自已带盐!https://github.com/JackJiang2011/MobileIMSDK/

posted @ 2022-11-11 11:33 Jack Jiang 阅读(219) | 评论 (0)编辑 收藏

     摘要: 本文由IBM开发者社区分享,有较多修订和改动。1、引言在当今移动网络时代,手机流量和电量是宝贵的资源,对于移动端最常见的即时通讯IM应用,由于实时通信基于Socket长连接,它对于流量和电量的需求较一般应用来说更高(详见《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》)。在IM应用中,优化数据流量消耗过多的基本方法就是使用高度压缩的通讯协议,而数据压缩后流量减小带来的自然结果也就...  阅读全文

posted @ 2022-11-10 11:49 Jack Jiang 阅读(115) | 评论 (0)编辑 收藏

关于MobileIMSDK

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。

工程开源地址是:

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► iOS端更新记录:http://www.52im.net/thread-2735-1-1.html
► 全部运行截图:iOS端全部运行截图 (另:Android端运行截图 点此查看
► 在线体验下载:App Store安装地址 (另:Android端下载体验 点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架 MobileIMSDK 实现)。

v6.1 版更新内容

此版更新内容更多历史更新日志):

  • 1)[bug] 在聊天信息界面中查找消息时,点击查看指定消息,在聊天界面中不能自动滚动到这条消息;
  • 2)[bug] 点击首页“消息”列表中遗留的陌生人聊天信息时,无法重置消息未读数的问题;
  • 3)[bug] 在聊天界面中进入别的界面再回来时,底部面板没有自动关闭/收起;
  • 4)[优化] 优化了标题栏弹出菜单的圆角效果(使之更符合最新iOS美感设计);
  • 5)[优化] 优化了APP中各种文本输入框UI效果,以及其它UI细节;
  • 6)[优化] 优化了短视频录制界面在iOS16“灵动岛”手机上的ui适配。

此版主要功能运行截图更多截图点此查看):

 

posted @ 2022-11-05 17:42 Jack Jiang 阅读(90) | 评论 (0)编辑 收藏

仅列出标题
共49页: First 上一页 14 15 16 17 18 19 20 21 22 下一页 Last 
Jack Jiang的 Mail: jb2011@163.com, 联系QQ: 413980957, 微信: hellojackjiang