网络通信的响应时长优化

5,136 阅读13分钟

原文地址

网络是用物理链路将各个孤立的工作站或主机相连在一起,组成数据链路,从而达到资源共享和通信的目的。

通信是人与人之间通过某种媒体进行的信息交流与传递。

网络通信是通过网络将各个孤立的设备进行连接,通过信息交换实现人与人,人与计算机,计算机与计算机之间的通信。

客户端在应用打开之后都会与服务端进行网络通信,以获取最新的数据,并把数据展示在界面上供用户操作。

今天我们来聊聊客户端与服务端之间通信的优化,主要是如何缩短响应延时为目标。

通信过程介绍

下面简单介绍一下客户端与服务端的通信过程。 如果忽略其中硬件部分和部分细节,手机APP网络通信的大体过程如下图所示:

  • 客户端拼接好网络请求之后,通过DNS解析服务找到对应的IP
  • 客户端发出网络请求,请求通过一些列的交换机、路由等硬件设备之后到达服务端
  • 服务端会有一个请求分发的服务,会把请求发送给对应的业务方,业务方会对这次请求做独特的数据- 封装,而数据来源于数据机房
  • 封装好业务数据之后把数据返回给客户端,
  • 客户端接收到响应数据之后,对CDN上的资源进行请求

我们要想提升网络访问成功率,本质上是减少每一步出错的概率 我们要想缩短一次网络访问的响应时间,本质上是提高数据的返回速度,说的直白一点就是要把请求数据过程中的各个步骤提高速度,这样整体下来响应时间就会缩短。

DNS预解析

所有网络请求的第一步都要找到域名对应的IP地址,DNS解析的效率直接决定了请求的延迟多少。而Cache的存在使得解析过程减少了很多延迟。但是缓存策略在不同系统上不一样,在iOS系统上,缓存策略一般是,24小时之后会过期、飞行模式的开启关闭、开关机、重置网络等,都会导致cache的清除,所以新的DNS请求又会导致请求耗时。 在这里简单介绍一下手机中DNS的查询过程:

  • 优先本地Cache查询
  • 查询本地DNS服务器
  • 查询根域名服务器
  • 查询顶级域名服务器
  • 查询域名服务器

在整个查询过程中大概要持续20ms到120ms左右的时间,而这段时间是可以优化的。

方案很简单:我们可以在客户端上存储自己的DNS映射表。在程序冷启时拉取”api.xxxxxx.com”对应的所有的IP列表;对所有IP进行跑马测试,找到速度最快的IP。后续所有的请求都将域名更换为跑马最快的IP即可。

那如何设计一份DNS映射表?几点要求如下:

  • APP打包时就加入一个默认映射文件,避免首次去服务器获取数据的延迟
  • 开启一个定时器,每隔一段时间就从服务器获取最新的映射表
  • 如果映射文件中没有相应信息,就需要回滚使用默认的DNS解析服务
  • 如果一个映射后的IP持续导致请求失败,需要一个淘汰机制将无效域名删除,并及时上报服务器,及时发现问题更新文件

网络间传输信息

中国的基础网络是世界上最复杂的基础网络,国内的网络运营商众多且各自为政,互联互通成本很高。信息在基础网络上的流通是不可靠的。

整个通信过程的响应时间取决于很多因素:HTTP请求是基于Socket设计的,请求发起之前会经历三次握手,在请求时会有一个慢启动,路由器的路由策略是否最优,整个过程通过的网关数据量,需要跨网络运营商,物理路径较长,服务器带宽是否足够,有时候甚至还会遇到GFW的拦截等等。这些因为都会直接导致通信时间的增长,甚至导致通信的失败。

那么改如何改善这种情况呢?把数据放在离用户越近的地方响应时间越快。举两个栗子:1)异地多活 2)长连模式 3)

异地多活架构的关键点就是异地、多活,其中异地就是指地理位置上不同的地方,类似于“不要把鸡蛋都放在同一篮子里”;多活就是指不同地理位置上的系统都能够提供业务服务,这里的“活”是活动、活跃的意思。 这里要注意一点:要把数据机房和业务机房做到地域对齐,否则跨地域跨机房调用的话延时是比较高的。如:北京到北京的网络延时是1ms,而北京到上海的网络延时大概在30ms左右。

长连模式是指在客户端与业务服务器之间架设代理长连服务器,而代理服务器负责与业务服务器进行HTTP请求,请求的结果通过长连通道送回客户端。代理服务器与业务服务器之间的网络通道也可以进行优化,通过租用腾讯云乃至架设专线等方式可以大大提升通道服务质量。与部署业务服务器相比,部署代理长连服务器的代价就小了很多,可以在全国甚至全世界多地部署代理长连服务器 再比如说压缩数据、数据分级等等都能够保证数据传输的性能。

服务端性能优化

对于服务端服务,一般用QPS(Query Per Second:每秒请求数)CT(Response Time:响应时间)、并发数、服务可用性四个指标作为性能优化的业务指标。

正常情况下响应时间(RT)越短,一秒钟处理的请求数(QPS)自然也就会越多,这在单线程处理的情况下看起来是线性的关系,即只要把每个请求的RT降到最低,那么性能就会最高。

但是,响应时间(RT)总会有一个极限,不可能无限下降,所以又出现了另外一个维度,即通过多线程,来处理请求。 理论上就变成了“总 QPS =(1000ms / 响应时间(RT))× 线程数量”,这样性能就和两个因素相关了,一个是一次响应的服务端耗时,一个是处理请求的线程数。

但是在某些情况下,降低响应时间(RT)、提高QPS和提高服务可用性三者相互矛盾,不可兼得。例如:增加缓存可以降低平均响应时间,但是处理线程数量会因为缓存过大而有所限制,从而降低QPS;为了提高服务可用性,对异常请求重复调用是一个常用的做法,但是这会提高响应时间并降低QPS。 那么常规的优化手段都有哪些呢?

代码优化

之所以把代码放到第一位,是因为这一点最容易引起技术人员的忽视。

  • 架构不合理。业务发展超越架构支撑能力而导致系统负荷过载,进而导致出现系统奔溃、响应超时等现象。另外不合理的架构如:单点、无cache、应用混部署、没有考虑分布式、集群化等也都会影响性能
  • 研发功底和经验不足。开发的server效率和性能较低、不稳定也是常见的事情
  • 没有性能意识,只实现了业务功能不注意代码性能,新功能上线后整体性能下降,或当业务上量后系统出现连锁反应,导致性能问题叠加,直接影响用户体验

缓存优化

缓存可以称的上是性能优化的利器,使用缓存时需要考虑缓存命中率、缓存丢失、缓存更新、数据一致性、缓存穿透及雪崩、Value过大等问题,可以通过mutiGet将多次请求合并一次、异步访问等方式来提升缓存读取的性能。

产品逻辑优化

业务逻辑优化经常会容易被忽略,但效果却往往比数据库调优、JVM调优之类的来的更明显。

举一个例子,12306春运抢火车票的场景,由于访问的人多,用户点击“查票”之后系统会非常卡,进度条非常慢,作为用户,会习惯性的再去点“查票”,可能会连续点个好几次。假设平均一个用户点5次,则后端系统负载就增加了5倍!而其中80%的请求是重复请求。这个时候我们可以通过产品逻辑的方式来优化,比如,在用户点击查询之后将“按钮置灰”,或者通过JS控制xx秒只能只能提交一次请求等,有效的拦截了80%的无效流量。

硬件优化

硬件问题对性能的影响不容忽视。 举一个例子:一个DB集群经常有慢SQL报警,业务排查下来发现SQL都很简单,该做的索引优化也都做了。后来DBA同学帮忙定位到问题是硬件过旧导致,将机械硬盘升级成固态硬盘之后报警立马消失了,效果立竿见影!

数据库优化

  • SQL调优

这是最常用、每一个技术人员都应该掌握基本的SQL调优手段(包括方法、工具、辅助系统等)。

  • 架构层面的调优

这一类调优包括读写分离、多重库负载均衡、水平和垂直分库分表等方面,一般需要的改动较大,但是频率没有SQL调优高,而且一般需要DBA来配合参与。

  • 连接池调优

这一类调优是为了实现数据库连接的高效获取、对数据库连接的限流等目的,通常会采用连接池类的方案,即每一个应用节点都管理了一个到各个数据库的连接池。 但是复杂查询以及一些聚合计算不适合在数据库中做,可以利用搜索引擎来实现,另外搜索引擎还可以帮我们很好的解决跨库、跨数据源检索的场景。

并发优化

并发可以利用线程池、消息队列等方式实现。 使用线程池的时候一定要注意核心参数的设置,可以通过监控工具去观测实际创建、活跃、空闲的线程数,结合CPU、内存的使用率情况来做线程池调优。

CDN加速优化

CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使终端用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。

给大家放一张直观图,给大家对比下 CDN 服务部署前后的区别:

CDN 系统设计的最大目标是尽量减少用户的访问响应时间。 为达到这一目标,CDN 系统应该尽量将用户所需要的内容存放在距离用户最近的位置。也就是说,负责为用户提供内容服务的 Cache 设备应部署在物理上的网络边缘位置,我们称这一层为CDN边缘层。CDN 系统中负责全局性管理和控制的设备组成 中心层,中心层同时保存着最多的内容副本,当边缘层设备未命中时,会向中心层请求,如果在中心层仍未命中,则需要中心层向源站回源。 使用CDN后的http请求处理流程如下图,其中左边为DNS解析过程,右边为内容访问过程:

CDN基于这样的原理:

  • 挑选最优设备为用户提供服务;
  • 如果某个内容被很多用户所需要,它就被缓存到距离用户最近的节点中。

CDN 公司在整个互联网上部署数以百计的CDN服务器(Cache),这些服务器通常在运营商的 IDC (互联网数据中心Internet Data Center)中,尽量靠近接入网络和用户。CDN在Cache中复制内容,当内容的提供者更新内容时,CDN 向Cache重新分发这些被刷新的内容。CDN提供一种机制,当用户请求内容时,该内容能够由以最快速度交付的Cache 来向用户提供,这个挑选"最优"的过程就叫做负载均衡。被选中的最优 Cache 可能最靠近用户,或者有一条与用户之间条件最好的路径。

总结

性能优化的过程首先要从监控开始。客户端的网络通信监控和服务端的网络通信监控是不同的。

客户端的网络访问是从请求发出开始,经过基础网络到达服务端,服务端处理好数据之后回吐给客户端,客户端接收到响应数据之后结束网络通信。服务端监控的是从接收到请求,到回吐数据的过程也就是说服务端的网络监控是客户端网络监控的一个子集。

今天简单梳理了一下客户端的网络通信,介绍的一些优化措施。除此之外,还可以在减少数据、数据分级(动静分离),以及减少中间环节、增加预处理等这些环节上做优化。

首先是减少数据,事实上,有两个地方特别影响性能,一是服务端在处理数据时不可避免地存在字符到字节的相互转化,二是 HTTP 请求时要做 Gzip 压缩,还有网络传输的耗时,这些都和数据大小密切相关。

再次,就是数据分级,也就是要保证首屏为先、重要信息为先,次要信息则异步加载,以这种方式提升用户获取数据的体验。

最后就是要减少中间环节,减少字符到字节的转换,增加预处理(提前做字符到字节的转换)去掉不需要的操作。