[转] 携程App网络服务通道治理和性能优化@2016

App网络服务的高可靠和低延迟对于无线业务稳定发展相当重要,过去两年来咱们一直在持续优化App网络服务的性能,到今年Q2结束时基本完成了App网络服务通道治理和性能优化的阶段性目标,特此撰文总结其中的经验教训,为之后的工做打下基础。算法

携程App无线网络服务架构

2014年携程为无线服务开发了Mobile Gateway,有两种类型:TCP Gateway和HTTP Gateway。 TCP Gateway设计用于App中Native业务网络服务,基于TCP协议之上设计了应用层协议,相似于RPC机制。TCP Gateway兼具了接入层和服务动态路由的功能,接入层的功能基于Netty实现,管理客户端的TCP长链接或者短链接;动态路由的功能基于Netfix开源的Zuul实现(Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more. ),能够在TCP Gateway上实现服务路由、监控、反爬和用户鉴权等功能。sql

每一个TCP服务请求到达TCP Gateway以后,会根据报文头中的服务号,转发到后端对应的业务服务集群上,从而实现后端服务的解耦。TCP Gateway到后端业务服务集群之间的转发使用HTTP协议的接口形式实现,一个TCP服务请求的完整报文会做为HTTP请求的Payload转发到后端业务服务集群,接收到HTTP响应后,会将其Payload完整的返回到对应的TCP链接中。后端

HTTP Gateway用于App中Hybrid和H5 Web站点的网络服务,采用HTTP Restful接口形式提供服务,其逻辑相对简单,核心是HTTP服务动态转发的功能。性能优化

Mobile Gateway的更多设计实现细节能够参考王兴朝同窗在2015上海QCon的演讲《携程无线Gateway》。网络

基于TCP协议实现App网络服务

带宽和延迟是影响网络服务性能的两个因素,带宽受网络通道上最小带宽的网段限制,延迟是网络包在客户端和服务端之间的来回传输时长,不一样网络类型上的带宽和延迟差异很是大(见下图)。架构

咱们要实现更好性能的网络服务,对于网络自身的带宽和延迟这两点而言,能作只是尽量选择最合适的网络通道,其余只能在如何使用网络通道上进行优化。框架

传统的非IM即时消息类App一般都是使用HTTP协议来实现网络服务的(Restful API形式),携程使用TCP协议来实现,确实会增长不少开发成本,例如须要设计应用层协议、管理网络链接、处理异常等,但下面几点缘由仍是让咱们最终选择基于TCP协议来实现App网络服务:异步

  1. 携程用户有时会在网络环境很是差的景区使用,须要针对弱网进行特别的优化,单纯HTTP应用层协议很难实现。ide

  2. HTTP请求首次须要进行DNS域名解析,咱们发现国内环境下针对携程域名的失败率在2-3%(包含域名劫持和解析失败的状况),严重影响用户体验。性能

  3. HTTP虽然是基于TCP协议实现的应用层协议,优点是封装性好,客户端和服务端解决方案成熟。劣势是可控性小,没法针对网络链接、发送请求和接收响应作定制性的优化,即便是HTTP的特性如保持长链接KeepAlive或者管道Pipeline等都会受制于网络环境中的Proxy或者服务端实现,很难充分发挥做用。

基于TCP协议实现可让咱们可以完整控制整个网络服务生命周期的各个阶段,包括以下几个阶段:

  1. 获取服务端IP地址

  2. 创建链接

  3. 序列化网络请求报文

  4. 发送网络请求

  5. 接受网络响应

  6. 反序列化网络响应报文

咱们的网络服务通道治理和优化工做就是从这几个方面展开的。

TCP网络服务通道治理和性能优化

1. 告别DNS,直接使用IP地址

若是是首次发送基于HTTP协议的网路服务,第一件事就是进行DNS域名解析,咱们统计过DNS解析成功率只有98%,剩下2%是解析失败或者运营商DNS劫持(Local DNS返回了非源站IP地址),同时DNS解析在3G下耗时200毫秒左右,4G也有100毫秒左右,延迟明显。咱们基于TCP链接,直接跳过了DNS解析阶段,使用内置IP列表的方式进行网络链接。

携程App内置了一组Server IP列表,同时每一个IP具有权重。每次创建新链接,会选择权重最高的IP地址进行链接。App启动时,IP列表的全部权重是相同的,此时会启动一组Ping的操做,根据Ping值的延迟时间来计算IP的权重,这么作的原理是Ping值越小的IP地址,链接后的网络传输延迟也应该相对更小。业界也有使用HTTP DNS方式来解决DNS劫持问题,同时返回最合适用户网络的Server IP。然而HTTP DNS的开发和部署须要不小的开发成本,咱们目前没有使用。

内置Server IP列表也会被更新,每次App启动后会有个Mobile Config服务(支持TCP和HTTP两种网络类型服务)更新Server IP列表,同时支持不一样产品线的Server IP列表更新。所以,传统DNS解析可以解决多IDC导流的功能也能够经过此方法解决。

2. Socket链接优化,减小链接时间

和HTTP协议中的Keepalive特性同样,最直接减小网络服务时间的优化手段就是保持长链接。每次TCP三次握手链接须要耗费客户端和服务端各一个RTT(Round trip time)时间才能完成,就意味着100-300毫秒的延迟;TCP协议自身应对网络拥塞的Slow Start机制也会影响新链接的传输性能。

携程App使用了长链接池的方式来使用长链接,长链接池中维护了多个保持和服务端的TCP链接,每次网络服务发起后会从长链接池中获取一个空闲长链接,完成网络服务后再将该TCP链接放回长链接池。咱们没有在单个TCP链接上实现Pipeline和Multiplexing机制,而是采用最简单的FIFO机制,缘由有二:1. 简化Mobile Gateway的服务处理逻辑,减小开发成本;2. 在服务端同时返回多个响应时,若是某个响应报文很是大,使用多个长链接方式能够加快接收服务响应报文速度。

若是发起网络服务时长链接池中的TCP链接都正在被占用,或者TCP长链接的网络服务失败,则会发起一个TCP短链接实现网络服务。这里长链接和短链接的区别仅仅是服务完成后是否直接关闭这个TCP链接。

附:Pipeline和Multiplexing是有区别的,如HTTP/1.1支持Pipeline,客户端可否同时发送多个请求,可是服务端返回响应时也要按照请求的发送次序来返回响应;SPDY和HTTP/2协议支持Multiplexing,即支持响应报文的乱序返回,发送请求和接收响应互不干扰,所以避免了HTTP/1.1 Pipeline也没能彻底解决的Head of line blocking问题。参考资料:1, 2。参考资历2中提到HTTP/1.1的Pipeline特性只是部分解决了Head of line blocking问题,由于a large or slow response can still block others behind it。

3. 弱网和网络抖动优化

携程App引入了网络质量参数,经过网络类型和端到端Ping值进行计算,根据不一样的网络质量改变网络服务策略:

  1. 调整长链接池个数:例如在2G/2.5G Egde网络下,会减小长链接池个数为1(运营商会限制单个目标IP的TCP链接个数);WIFI网络下能够增长长链接池个数等机制。

  2. 动态调整TCP connection、write、read的超时时间。

  3. 网络类型切换时,例如WIFI和移动网络、4G/3G切换至2G时,客户端IP地址会发生变化,已经链接上的TCP Socket注定已经失效(每一个Socket对应一个四元组:源IP、源Port、目标IP、目标Port),此时会自动关闭全部空闲长链接,现有网络服务也会根据状态自动重试。

4. 数据格式优化,减小数据传输量和序列化时间

传输数据量越小,在相同TCP链接上的传输时间越短。携程App曾经使用自行设计的一套数据格式,后来和Google ProtocolBuffer对比后发现,特定数据类型下数据包大小会下降20-30%,序列化和反序列化时间能够下降10-20%,所以目前核心服务都在逐步迁移到到ProtocolBuffer格式。另外Facebook曾分享过他们使用FlatBuffer数据格式提升性能的实践,咱们分析后不太适合携程的业务场景于是没有使用。

5. 引入重试机制,提高网络服务成功率

受TCP协议重传机制来保证可靠传输的机制启发,咱们在应用层面也引入了重试机制来提升网络服务成功率。咱们发现90%以上的的网络服务失败都是因为网络链接失败,此时再次重试是有机会链接成功并完成服务的;同时咱们发现前面提到的网络服务生命周期处于1创建链接、序列化网络请求报文、发送网络请求这三个阶段失败时,都是能够自动重试的,由于咱们能够确信请求尚未达到服务端进行处理,不会产生幂等性问题(若是存在幂等性问题,会出现重复订单等状况)。当网络服务须要重试时,会使用短链接进行补偿,而再也不使用长链接。

实现了上述机制后,携程App网络服务成功率由原先的95.3%+提高为现在的99.5%+(这里的服务成功率是指端到端服务成功率,即客户端采集的服务成功数除以请求总量计算的,而且不区分当前网络情况),效果显著。

6. 其余网络服务机制 & Tricks

携程App也实现了其余一些网络服务机制方便业务开发,如网络服务优先级机制,高优先级服务优先使用长链接,低优先级服务默认使用短链接;网络服务依赖机制,根据依赖关系自动发起或取消网络服务,例如主服务失败时,子服务自动取消。

开发过程当中咱们也发现一些移动平台上的TCP Socket开发tricks:

  1. iOS平台上的原生Socket接口建立链接并不会激活移动网络,这里原生Socket接口是指POSIX Socket接口,必须使用CFSocket或者再上层的网络接口尝试网络链接时才会激活网络。所以携程App启动时会优先激活注册一些第三方SDK以及发送HTTP请求来激活移动网络。

  2. 合理设置Socket的几个参数:SOKEEPALIVE参数确保TCP链接保持(注:此KeepAlive是TCP中的属性,和HTTP的KeepAlive是两个场景概念),SONOSIGPIPE参数关闭SIGPIPE事件,TCP_NODELAY参数关闭TCP Nagle算法的影响。

  3. 因为iOS要求支持IPv6-Only网络,所以使用原生Socket必须支持IPv6。

  4. 若是使用select来处理nonblocking IO操做,确保正确处理不一样的返回值和超时参数。

  5. 保持TCP长链接可用性的心跳机制:对于非IM类应用而言,心跳机制的做用不大,由于用户会不断触发请求去使用TCP链接,尤为在携程业务场景下,经过数据统计发现使用心跳与否对服务耗时和成功率影响极小,所以目前已经关闭心跳机制。原先的心跳机制是TCP长链接池中的空闲TCP链接每60秒发送一个心跳包到Gateway,Gateway返回一个心跳响应包,从而让双方确认TCP链接有效。

Hybrid网络服务优化

携程App中有至关比例的业务是使用Hybrid技术实现的,运行在WebView环境中,其中的全部网络服务(HTTP请求)都是由系统控制的,咱们没法掌控,也就没法进行优化,其端到端服务成功率也仅有97%左右(注:这里指页面中业务逻辑发送的网络服务请求,而非静态资源请求)。

咱们采用了名为『TCP Tunnel for Hybrid』的技术方案来优化Hybrid网络服务,和传统HTTP加速产品的方法不一样,咱们没有采用拦截HTTP请求再转发的方式,而是在携程Hybrid框架中的网络服务层进行自动切换。

如图所示,该技术方案的流程以下:

  1. 若是App支持TCP Tunnel for Hybrid,Hybrid业务在发网络服务时,会经过Hybrid接口转发至App Native层的TCP网络通信层,该模块会封装这个HTTP请求,做为TCP网络服务的Payload转发到TCP Gateway;

  2. TCP Gateway会根据服务号判断出是Hybrid转发服务,解包后将Payload直接转发至HTTP Gateway,此HTTP请求对HTTP Gateway是透明的,HTTP Gateway无需区分是App直接发来的仍是TCP Gateway转发来的HTTP请求;

  3. 后端业务服务处理完成后,HTTP响应会经HTTP Gateway返回给TCP Gateway,TCP Gateway将此HTTP响应做为Payload返回给App的TCP网络通信层;

  4. TCP网络通信层会再将该Payload反序列化后返回给Hybrid框架,最终异步回调给Hybrid业务调用方。整个过程对于Hybrid业务调用方也是透明的,它并不知道TCP Tunnel的存在。

采用该技术方案后,携程App中Hybrid业务的网络服务成功率提高至99%以上,平均耗时降低了30%。

海外网络服务优化

携程目前没有部署海外IDC,海外用户在使用App时须要访问位于国内的IDC,服务平均耗时明显高于国内用户。咱们采用了名为『TCP Bypass for Oversea』的技术方案来优化海外网络服务性能,主要是使用了Akaima的海外专属网络通道,同时在携程国内IDC部署了局端设备,使用专用加速通道的方式来提高海外用户体验。

海外用户启动App后先经过Akaima定制域名获取Server IP,全部网络服务优先走Akaima通道;若是Akaima通道的网络服务失败而且重试机制生效时,会改走传统Internet通道进行重试。相比只用传统Internet通道,在保持网络服务成功率不变的状况下,使用Akaima通道Bypass技术后平均服务耗时降低了33%。

其余网络协议探讨

过去两年咱们的网络服务优化工做都是基于TCP协议实现的,基本达到了优化目标。不过这两年来新的应用层网络协议SPDY和HTTP/2逐步迈入主流,基于UDP的QUIC协议看起来也很是有趣,值得跟进调研。

SPDY & HTTP/2

SPDY是Google基于TCP开发的网络应用层协议,目前已经中止开发,转向支持基于SPDY成果设计的HTTP/2协议,HTTP/2协议的核心改进其实就是针对HTTP/1.x中影响延迟性能的痛点进行优化:

  1. Header压缩:压缩冗余的HTTP请求和响应Header。

  2. 支持Multiplexing:支持一个TCP链接上同时实现多个请求和响应。

  3. 保持长链接(比HTTP/1.x更完全):减小网络链接时间。

  4. 支持推送:能够由服务端主动推送数据到客户端。

官方性能测试结果显示使用SPDY或者HTTP/2的页面加载时间减小30%左右,不过这是针对网页的测试结果,对于App中的网络服务,具体优化效果咱们还在进行内部测试,不过其优化手段看和目前咱们使用TCP协议的优化手段相似,所以性能优化效果可能不会很显著。

QUIC

QUIC是Google基于UDP开发的应用层协议,UDP协议无需链接,不存在重传机制,所以应用层须要保证服务的可靠性。目前国内腾讯有针对弱网络尝试过QUIC协议,咱们也在进行测试,最终是否会采用还须要看测试的结果。

综述

技术只是手段,最终仍是要反映在业务效果上。咱们已经实现除静态资源等须要访问CDN的网络请求外,其余App网络服务使用统一的TCP通道,从而具有更好的性能调优和业务监控能力。携程目前基于TCP协议的各类App网络服务优化,也是各类技术方案的平衡,虽然目前HTTP/2等新协议逐步成熟,可是TCP协议自身的灵活性支持有针对性的性能优化,仍是具有其特别的优点,但愿咱们的实践总结能对国内无线技术从业者有一些借鉴价值。

相关文章
相关标签/搜索