百度iOS端长连接组件建设及应用实践

在这里插入图片描述

作者 | 百度消息中台团队

导读

在过去的十年里,移动端技术飞速发展,移动应用逐渐成为主要的便捷访问和使用互联网的方式,承接了越来越多的业务和功能,这也意味着对移动端和服务器之间的通信效率和稳定性提出了更高的要求。为了实现更高效的实时通信和数据同步,长连接逐渐成为一种关键技术,通过维持客户端和服务器之间的持久连接,实现了双方实时数据交换,避免了频繁的建连和断连开销,从而提高用户体验、服务稳定性、可靠性等方面的表现。

本文旨在探讨长连接技术在移动端的实践,针对百度iOS端在建设长连接过程中的技术选型和整体架构逻辑将做重点展开。同时结合IM即时通讯案例的介绍和分析,展示长连接是如何在移动应用领域为类似业务场景提供解决方案的。

本文将分为五个主要部分。首先,对长连接技术进行概述,包括定义、与短连接的对比以及在移动互联网领域的常见应用。接下来,会简单介绍百度长连接服务,包括搭建的背景以及建成后提供的服务核心主流程。然后,将重点讨论百度iOS端长连接SDK搭建过程中的挑战和解决方案,包含协议的选择、DNS解析优化、长连接保活机制的设计等。紧接着,以IM即时通讯场景中的长连接实践为例,展示了长连接SDK是如何为业务实现请求数据转发、接收服务器主动推送等功能的。最后,对本文的主要内容做了总结,以及对长连接在移动端应用中未来的发展趋势和前景进行了展望。

全文7193字,预计阅读时间18分钟。

01 长连接简介

1.1 认识长连接

长连接,指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。

图片

1.2 长连接与短连接对比

图片

1.3 长连接在移动互联网领域的应用

长连接在移动互联网领域有广泛的应用,特别是在实现实时通信和消息推送等功能方面发挥了关键作用。例如,常见的微信、QQ这样的即时通信软件,就是通过维持客户端和服务器的长连接,实现即时传输信息的需求。又如一些网络游戏、定位服务、新闻推送等,也会使用长连接,实时推送新的动态或者消息给用户。这样,无论用户在何时何地,只要连接到互联网,就能够接收到最新的信息,极大地提升了使用者的体验度并且使得移动互联网更加便捷。

总的来说,对实时性、数据传输效率、频繁通信等有强需求的应用,长连接都是一个好的选择。

02 百度长连接服务简介

2.1 搭建统一长连接的背景

此前,百度移动端都是由各业务自运维的长连接,往往搭建和维护成本都偏高,且可复用性不大,因此计划实现一套高并发、低时延、高触达的统一长连接组件,能够更灵活高效地支持各业务接入,能够对百度系的各APP独立输出长连接服务满足各业务的诉求,从而提升服务质量,降低资源成本。

2.2 长连接服务主流程图

百度长连接服务包含客户端的长连接SDK和服务端的长连接接入层两个部分,长连接接入层又包含访问控制模块和接入模块,负责维护长连接管理及业务数据转发。下图描述了长连接建连及心跳保活过程,业务登录和登录后推送过程,以及最终长连接SDK触发断连的过程。后文将针对iOS端长连接SDK的具体实现解决方案,和长连接SDK在百度APP中的业务应用落地进行更为详细的探讨。

图片

03 百度iOS端搭建长连接SDK的解决方案

3.1 客户端搭建长连接的挑战点概述

客户端从0到1搭建一套完整的长连接SDK,这个过程涉及到多个技术点的考虑,包括但不限于:连接的创建和维护,网络协议的选择,使用加密传输、验证数据来源等方式保证长连接的安全性,通过数据传输格式选择、数据压缩等方式减少数据量提高传输效率,错误异常处理机制等,需要开发者根据实际情况进行最优实现方案的选择。在这之中,最核心的可以拆解为以下两个部分:

1、连接的创建:完整建连流程的设计,网络协议的选择,设计时需要考虑长连接建连的成功率、时延等核心指标;

2、连接的维护:保证建连成功是第一步,长连接还需要保持维护双方连接才可达成持续通信的目的,这包括:在长时间无数据交互的情况下,需要定期发送心跳包进行连接的保活,以及长连接连接断开后需要及时进行断线重连恢复连接在线状态。

3.2 核心逻辑一:连接的创建

长连接建连即客户端与服务器建立连接,是长连接SDK要做的第一件事,所有业务方数据的传输(上下行)都要基于长连接建连成功的这个前提。长连接建连并不是一个单一简单的操作,而是一个分阶段进行的过程。本小节将主要讨论在设计开发长连接建连模块之前,需要重点考虑确认的几个技术点和实现方案,以及百度iOS端长连接SDK最终实现的长连接建连完整过程的架构。

3.2.1 挑战①:协议的选择

问题点:UDP还是TCP

对于网络编程这个话题,使用哪种数据传输层协议来实现通信是一个非常基础但一直争论不休的问题。UDP和TCP各有各的应用场景,TCP能提供可靠的数据传输,UDP则有更高的传输效率,此处不再赘述TCP与UDP的区别,最终选择哪种协议实现,是一个见仁见智的问题,需结合整体应用场景、开发代价、部署和运营成本等方面综合考虑。

解决方案:TCP为主,同时小流量探索QUIC的潜力

百度iOS端长连接SDK中现有两套数据传输方案:

方案一:在长连接SDK建设初期,根据业内成熟技术方案选型的调研结果,及开发成本、维护便捷性的考虑,第一个方案是参考CocoaAsyncSocket框架改写的,基于Socket原生开发,使用TCP协议,支持TLS/SSL安全传输,并且是线程安全的,该方案较为成熟,使用便捷,建连成功率较高。目前百度APP iOS端中90%的用户流量都是走的该方案实现的长连接逻辑。

方案二:一般稳定网络传输都是通过TCP,但在网络基建本身已经越来越完善的情况下,TCP一些设计本身的问题便暴露了出来,加之TCP是在操作内核和中间固件中实现的,因此对TCP进行重大更改几乎是很难的事情,类似建连过程握手耗时长、队头阻塞等问题没有得到很好地解决,让我们开始考虑一些新的可能性。长连接SDK后续引入了基于QUIC协议实现的第二套方案。QUIC协议是建立在UDP之上,并且实现了可靠传输,相比HTTP2+TCP+TLS协议,QUIC具有不少优点:减少了TCP三次握手及TLS握手时间,改进了拥塞控制,并且没有队头阻塞的多路复用,支持连接迁移等。百度iOS长连接SDK目前通过NWConnection引入了QUIC协议的实现。QUIC的协议虽然比较先进,但这也意味着在工程实现方面有更多可优化的空间,目前方案二还处于小流量实验阶段,仍有很多优化工作有待后续进一步去落地。就当前放量所得到的数据来看,在长连接建连成功率及时延指标上,QUIC实现方案都有较好的表现。

3.2.2 挑战②:DNS解析优化

问题点:国内移动端网络所面临的DNS疑难杂症

国内各ISP运营商的LocalDNS由于域名缓存、解析转发、LocalDNS递归出口NAT的原因,容易引起DNS被劫持造成服务不可用、DNS调度不准确导致性能退化等问题。DNS解析的效率和准确性,直接影响长连接建连的质量,进而影响公司的业务。

解决方案:HTTPDNS

因此在百度iOS端长连接SDK中,采用当前业界比较主流的解决方案:HTTPDNS,来替代LocalDNS解析。HTTPDNS是利用HTTP协议与DNS服务器进行交互,绕开了运营商的LocalDNS服务,有效防止了域名劫持,提高域名解析效率。

3.2.3 完整解决方案:百度iOS端长连接建连整体流程

建连时机

在百度APP中,统一维护了一系列系统事件和生命周期供各个组件监听。iOS长连接SDK根据百度APP的业务特性,选择在环境搭建完成事件后触发长连接建连,即等待APP启动必要数据比如首页资源等加载完成后,开始触发长连接建连。

建连完整过程

下图展示了长连接SDK建连的四个过程:

获取Token

  • 获取Token的意义:狭义上Token指的是长连接访问控制模块返回的access-token,后续随长连接登录请求上行到长连接接入层,由接入层向长连接访问控制模块进行鉴权用。广义上随此次Token请求下发的,还有传输协议及访问点等数据,包括但不限于:长连接协议使用QUIC还是TCP,是否优先ipv6,连接域名和端口,日志打点小流量开关等。

  • 获取Token的机制:获取Token优先走本地缓存,当本地缓存无有效数据时,才发出网络请求,该请求是基于NSURLSession实现的短连接请求;Token在服务端和客户端均有缓存,存在过期时间,若Token过期,会在下图中阶段四通过长连接登录请求失败体现,这时会清空本地Token缓存并触发重新建连。

DNS域名解析:如前所述,长连接SDK中使用HTTPDNS替代LocalDNS来防止DNS劫持、提高解析效率。同时在iOS Release环境下,为提高DNS解析效率,本地建立了缓存机制,HTTPDNS解析结果返回后会更新本地缓存,下次建连过程优先取缓存,缓存不合法才走网络请求。

建立Socket连接:Socket建连过程涉及到传输协议的选择,根据前面介绍,iOS长连接SDK目前是通过小流量实验的方式,10%的用户走QUIC建连,90%的用户走TCP建连。

长连接登录请求:携带Token中获取的access-token上行请求完成鉴权,长连接登录请求返回成功意味着整个建连过程完成,业务层可开始正常使用长连接进行通讯,若登录返回报错,则会触发重连。

顺利完成这四个阶段后,长连接会在该链路上持续发送心跳包进行连接保活,在异常断连或压后台等触发的主动断连之前,一直保持连接在线状态,为各个业务的数据传输提供通路。

图片

3.3 核心逻辑二:连接的维护

3.3.1 维护连接的意义

上个小节介绍了长连接连接建立的全过程,长连接建连成功后,实际已处于可用状态,即各业务基于长连接的通信已经可以正常进行。但在此之后,保持长连接的可用性也是非常重要的。如果长连接无法很好地保持,在连接已经失效的情况下服务端继续推送下行通知而端却收不到,造成资源的浪费,同时无法及时重新建连,对业务造成损失。

3.3.2 维护长连接的解决方案

针对可能导致长连接断开的几种主要原因,长连接SDK建立了对应的机制来保证连接的稳定性,可总结为两点:心跳保活和断线重连。

图片

解决方案①:心跳保活

心跳保活的定义:实现长连接保活的方式通常是采用应用层心跳,通过心跳包的超时或报错等来执行重连操作。心跳一般是指某端(通常是客户端)每隔一定时间向另一端(通常是服务端)发送自定义指令,以判断双方是否存活,因其按照一定间隔发送,类似于心跳,故被称为心跳保活。

百度iOS端长连接SDK心跳保活机制:长连接登陆请求成功后,解析返回数据,若服务端下发了心跳包的间隔时间,则以服务端下发的时间间隔持续发送心跳包进行连接保活,若没有下发心跳包间隔时间,客户端会默认60s间隔时间来触发心跳包的发送。具体心跳保活过程见下图。

图片

解决方案②:断线重连

断线重连原理:在长连接可能被断开的场景(压后台重进APP、网络状态变更等),检测长连接的可用状态,监测到连接不可用时,及时触发重连机制。

百度iOS端长连接SDK断线重连机制:具体触发断线重连的时机见下图,iOS长连接SDK内部维护有串行队列和统一的长连接状态监测记录,不会导致重复建连的发生。

图片

04 长连接在百度APP中的应用与实践

4.1 长连接在百度APP中的业务落地

长连接是客户端到服务端的一种全双工连接,建连完成后,可以为业务方提供请求转发、服务端主动推送等服务。在百度APP中,包括在线健康诊疗、高考志愿填报咨询、情感心理辅导等一系列实时咨询服务,发送直播弹幕、加入某大V粉丝群聊天、私信好友等多种用户实时沟通场景的落地,以及实现用户在线情况下云端可及时主动下发配置控制端的基础能力建设,都离不开长连接的支持。长连接为各个业务与自己服务端的数据交互提供了稳定便捷的方式和渠道。

下图为百度APP中长连接与落地业务的结构示意图。完整的长连接模块包括了客户端的长连接SDK和服务端的长连接接入层两个部分,作为各个业务与自己服务端数据交流的中间渠道,处理了包括连接建立与保活、实现各业务客户端与自己服务端的数据双向互发等逻辑。下面将重点关注长连接在IMSDK实时聊天通讯场景中的实践。

图片

4.2 长连接在IM即时通讯场景中的实践

4.2.1 背景介绍

IMSDK,即百度消息中台为百度APP及百度系其他产品打造的具备应用内即时通讯能力的客户端SDK,包括多种用户沟通场景:私聊、群聊、聊天室、直播弹幕等,并帮助业务推送消息通知触达用户,建立B端和C端的沟通渠道。目前主功能诸如拉取会话列表、拉取消息、发送消息、消息已读等均为长连接实现。本小节将通过介绍用户发送消息、用户收到新消息通知这两个IM及时通讯中的常见场景,展示长连接提供的数据转发和服务器主动推送能力是如何在业务场景落地的。

4.2.2 实践1:实时聊天场景下用户发送消息

实践场景

实时聊天场景下,用户在聊天框向自己好友发送一条消息,消息如果发送失败了,应用通常会在本条消息气泡旁展示一个红叹号,这个应用场景对于互联网用户应该都非常熟悉。从技术角度看,本质上是业务客户端向自己的服务器上行一个请求,服务器再将请求结果返回给客户端。这是一个典型的需要频繁点到点通信的场景,非常适合基于长连接来实现。长连接SDK对外提供了封装好的长连接请求类,外部业务方诸如IMSDK在上行长连接请求时通过创建该类的实例,将上行所需参数和数据赋值给请求实例,并设置回调闭包用于接收和处理请求回执数据和结果,最后将请求发出。业务不需要考虑数据传输及转发等逻辑,长连接会充当业务客户端和服务器之间的通路,黑盒处理这个过程。

技术难点

对于长连接SDK而言,在这条通路上最重要也是比较复杂的逻辑点在于,各个业务方的上行请求和下行通知都是并发进行的,长连接SDK如何有序地管理数据流向。上行请求即写流,接收下行数据即读流,下面就读写流的管理,与请求同回执数据的匹配问题的解决方案作简要的介绍。

技术实现

长连接SDK内就读写数据维护有两个队列:读队列和写队列,以及维护了一个缓存池用作请求实例和请求回执数据的匹配。业务方上行一个长连接请求,实际上是将请求任务添加到写队列中,如果此时处于可写流状态,还会触发写流。当socket建连成功以后,会取出写队列队头的任务,开始写流,写流完毕会检查写队列是否为空,不为空继续取队头任务执行,直至写队列为空为止。同时socket建连成功还会添加一次读任务到读队列中,并检查如果此时处于可读状态,便取出队头第一个读任务,开始读流,读流成功后会继续添加一个读任务到读队列,循环读流操作。

读流得到的服务端下行返回数据,通过serviceId(业务编号)+ methodId(长连接请求方法编号)+ 请求发起的时间戳组成唯一键值,去缓存区匹配到下行返回数据对应的请求体,通过回调的方式,将请求结果返回到调用方。该请求一旦被回调过一次,其实例将从缓存区被删除,及时释放缓存区内存,并且保证一次请求不会发生多次回调的情况。

图片

4.2.3 实践2:实时聊天场景下用户收到新消息通知

实践场景

实时聊天场景下,用户是如何收到别的用户发送给他的新消息通知的呢?其实是依靠服务器的下行通知到客户端。长连接不仅提供为业务客户端转发上行请求的能力,还提供了服务端主动推送的服务。比如在IM业务中,依靠IM服务器下行新消息通知,来完成消息的实时接收和拉取。这些通知又是如何到达IMSDK的呢?其实它与上一小节IMSDK上行长连接请求的过程类似。

技术实现

在IMSDK的长连接管理类初始化阶段,会对需要接收的下行通知方法进行注册,这里的注册实际上指的就是上行多个长连接请求,每个请求有对应的serviceID(业务编号)和methodID(需要注册的通知方法号码)。跟上一小节长连接请求不同的点在于,这些请求在收到回执数据后不会从长连接SDK请求缓存区里移除,而是会长期存在,只要读流时读到了对应methodID的数据,就能在请求缓存区找到对应请求,将下行数据传到IMSDK了。这样一来,只要长连接在线,业务方就能实时接收到其服务器下行的通知消息了。

05 结语

长连接服务的核心大致可分为:建连过程、连接维持过程以及数据传输过程。本文给出了搭建长连接服务过程中面临的一些挑战和解决方案,并结合长连接功能在百度APP即时通讯场景下的实践,简要介绍了百度iOS端长连接SDK的整体架构。

在移动端,长连接技术的应用前景非常广阔。随着5G和6G等高速移动网络的发展,将使得移动应用程序能够更加高效地使用长连接技术,从而实现更加实时和高效的数据交换。这也为对实时数据交换有强需求的应用场景提供了更广阔的想象空间,诸如物联网、智能家居、虚拟现实和增强现实等技术,长连接都将在其中发挥更加重要的作用。

——END——

推荐阅读:

百度App启动性能优化实践篇

扫光动效在移动端应用实践

Android SDK安全加固问题与分析

搜索语义模型的大规模量化实践

如何设计一个高效的分布式日志服务平台

视频与图片检索中的多模态语义匹配模型:原理、启示、应用与展望

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21592.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言实现简易通讯录

目录 普通版 功能需求 模块设计 test.c模块实现 contact.h模块实现 类型的声明 函数的声明 头文件、枚举、宏定义 contact.c 模块实现 初始化通讯录 增加联系人 显示所有联系人的信息 查找函数 删除指定联系人 查找指定联系人 修改指定联系人 进阶版通讯录&a…

基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件

系列文章目录 基于scrcpy的远程调试方案 基于scrcpy的Android群控项目重构 基于scrcpy的Android群控项目重构 进阶版 基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件(视频) 基于scrcpy的Android群控项目重构…

面向个人的免费组态软件:摩尔信使MThings

产品官网 现代工业自动化各行各业中均广泛应用工控上位机软件,但同时也面临着一系列挑战和复杂性。 多样化设备组网:工控系统包含不同厂家的各类硬件和设备,如传感器、执行器、PLC等。工控上位机软件需要与不同类型的设备进行集成和通信&am…

C++常用库函数 2.字符分类函数

函数名&#xff1a;isalnum 函数原型&#xff1a;int isalnum(int c)&#xff1b; 所需头文件&#xff1a;<cctype> 功能&#xff1a;测试 c 是否字母或数字。 返回值&#xff1a;如果 c 在 A&#xff5e;Z、a&#xff5e;z 或0&#xff5e;9的范围内&#xff0c;则返回…

[Linux] 最基础简单的线程池 及其 单例模式的实现

本篇文章主要用到线程相关内容, 下面是博主关于线程相关内容的文章: [Linux] 线程同步分析&#xff1a;什么是条件变量&#xff1f;生产者消费者模型是什么&#xff1f;POSIX信号量怎么用&#xff1f;阻塞队列和环形队列模拟生产者消费者模型 [Linux] 线程互斥分析: 多线程的问…

使用claude 2的文档分析功能

复制一段较长的文本内容&#xff0c;比如json文件。 https://zh.annas-archive.org/db/aarecord/md5:ba19176859126615bba9f35110f7492e.json 打开claude 2网页。 在输入框中粘贴内容&#xff0c;会自动生成一个past.txt图标。 输入要问的问题&#xff0c;按回车。 结果如下&a…

外网SSH远程连接linux服务器「cpolar内网穿透」

文章目录 1. Linux CentOS安装cpolar2. 创建TCP隧道3. 随机地址公网远程连接4. 固定TCP地址5. 使用固定公网TCP地址SSH远程 本次教程我们来实现如何在外公网环境下&#xff0c;SSH远程连接家里/公司的Linux CentOS服务器&#xff0c;无需公网IP&#xff0c;也不需要设置路由器。…

分层解耦-IOCDI-DI详解

目录 Bean注入 小结 依赖注入的注解 Resource和Autowired区别 Bean注入 Autowired注解&#xff0c;默认是按照类型进行依赖注入&#xff0c;如果存在多个相同类型的bean就会报错 解决方案 Primary&#xff08;设置bean的优先级&#xff09; Qualifier&#xff08;通过bean…

搭建Serv-U FTP服务器共享文件并外网远程访问「无公网IP」

文章目录 1. 前言2. 本地FTP搭建2.1 Serv-U下载和安装2.2 Serv-U共享网页测试2.3 Cpolar下载和安装 3. 本地FTP发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 科技日益发展的今天&#xff0c;移动电子设备似乎成了我们生活的主角&#xff0c;智能…

mp4视频太大怎么压缩?简单视频压缩方法分享

视频压缩是一种常见的操作&#xff0c;它可以起到很多有用的效果。通过压缩视频&#xff0c;我们可以减小视频文件的大小&#xff0c;从而节省存储空间和传输带宽。此外&#xff0c;压缩后的视频可以更快地加载和播放&#xff0c;提高观看体验&#xff0c;特别是对于网络传输较…

中国地图数据可视化制作,python的pyecharts模块读取excel中国着色地图可视化

数据格式如下&#xff1a; import pandas as pd from pyecharts import options as opts from pyecharts.charts import Map from pyecharts.globals import ChartType# 读取Excel数据 data pd.read_excel(C:\\Users\\Administrator\\Desktop\\国内数据.xlsx)# 创建地图实例 m…

性能测试 jmeter 的 beanshell 脚本的 2 个常用例子

目录 前言&#xff1a; Bean Shell 内置变量大全 例子 1 例子 2 技巧 前言&#xff1a; JMeter是一个功能强大的性能测试工具&#xff0c;而Beanshell是JMeter中用于编写脚本的一种语言。 在利用 jmeter 进行接口测试或者性能测试的时候&#xff0c;我们需要处理一些复杂…