“AI 技术+人才”如何成为企业增长新引擎?戳此了解>>> 了解详情
写点什么

境外业务性能优化实践

  • 2020-02-25
  • 本文字数:9968 字

    阅读完需:约 33 分钟

境外业务性能优化实践

前言

性能问题简介

应用性能是产品用户体验的基石,性能优化的终极目标是优化用户体验。当我们谈及性能,最直观能想到的一个词是“快”,Strangeloop 在对众多的网站做性能分析之后得出了一个著名的 3s 定律“页面加载速度超过 3s,57%的访客会离开”,可见页面加载速度对于互联网产品的重要性。速度在 Google、百度等搜索引擎的 PR 评分中也占有一定的比例,会影响到网站的 SEO 排名。“天下武功,唯快不破”,套在性能上面也非常适用。

性能指标

性能优化是个系统性工程,涉及到后端、前端、移动端、系统网络及各种基础设施,每一块都需要做各自的性能优化。当我们系统的分析性能问题时,可以通过以下指标来衡量:


  • Web 端:首屏时间、白屏时间、可交互时间、完全加载时间等。

  • 首屏时间是指从用户打开网页开始到浏览器第一屏渲染完成的时间,是最直接的用户感知体验指标,也是性能领域公认的最重要的核心指标。

  • 首屏时间 = DNS 时间 + 建立连接时间 + 后端响应时间 + 网络传输时间 + 首屏页面渲染时间

  • 移动端:Crash 率、内存使用率、FPS(Frames Per Second, 每秒传输帧数)、端到端响应时间等。

  • Native 相比于 H5 在交互体验方面有更多的优势,FPS 是体现页面顺畅程度的一个重要指标,另外移动端开发同学还需要关注 App 进程的 CPU 使用率、内存使用率等系统性能指标。端到端响应时间是衡量一个 API 性能的关键指标,比纯后端响应时间更全面,它会受到 DNS、网络带宽、网络链路、HTTP Payload 等多个因素的影响。端到端响应时间是 DNS 解析时间、网络传输时间及后端响应时间的总和。

  • 后端:响应时间(RT)、吞吐量(TPS)、并发数等。

  • 后端系统响应时间是指系统对请求做出响应的时间(应用延迟时间),对于面向用户的 Web 服务,响应时间能很好度量应用性能,会受到数据库查询、RPC 调用、网络 IO、逻辑计算复杂度、JVM 垃圾回收等多方面因素影响。对于高并发的应用和系统,吞吐量是个非常重要的指标,它与 request 对 CPU、内存资源的消耗,调用的外部接口及 IO 等紧密关联。

影响性能的因素

互联网产品是创意、设计、研发、系统、网络、硬件、运维等众多资源相互交织的集合体,性能受多方面因素影响,犹如一只木桶,木桶能盛多少水,取决于最短的那块木板,也可称之为短板效应。影响产品性能的因素有:


1. 产品逻辑与用户行为


产品逻辑过于复杂、功能交互过于丰富、产品设计过于绚丽、页面元素素材过多等都会影响产品性能。


2. 基础网络


中国的基础网络是世界上最复杂的基础网络,国内的网络运营商众多且各自为政,互联互通成本很高。对于境外业务来说更是要面对国内国际网络交互的情况,再加上 GFW 的存在,网络延迟、丢包现象非常严重。


3. 代码及应用


开发语言瓶颈、代码质量及系统架构等都会影响系统性能,常见的代码及应用问题有:


  • 架构不合理。业务发展超越架构支撑能力而导致系统负荷过载,进而导致出现系统奔溃、响应超时等现象。另外不合理的架构如:单点、无 cache、应用混部署、没有考虑分布式、集群化等也都会影响性能。

  • 研发功底和经验不足。开发的 App、Server 效率和性能较低、不稳定也是常见的事情。

  • 没有性能意识,只实现了业务功能不注意代码性能,新功能上线后整体性能下降,或当业务上量后系统出现连锁反应,导致性能问题叠加,直接影响用户体验。

  • 多数的性能问题发生在数据库上。由慢 SQL(详情可以参考美团技术团队博客的经典文章《MySQL索引原理及慢查询优化》)、过多查询等原因造成的数据库瓶颈,没有做读写分离、分库分表等。


4. 移动端环境


移动互联网时代,移动端环境的复杂性对产品的性能影响也很大,比如用户的设备类型、设备性能、操作系统类型、系统版本及网络类型(电信/移动/联通,Wi-Fi/4G/3G/2G)等。


5. 硬件及云环境


硬件的发展遵循着摩尔定律,生命周期一般都很短,服务器老化或其他硬件问题经常会导致应用故障。IDC、机架、服务器、内存、磁盘、网卡等不同硬件和操作系统上运行的应用性能差距可以达到数十倍之多。



关于性能优化这个主题,美团技术团队博客之前也发表过不少系统阐述的文章,比如《常见性能优化策略的总结》《性能优化模式》,可以参考。

境外业务的特点

美团旅行境外业务主要包含商户信息、用户评论、特色美食、出境线路、境外当地玩乐、购物优惠券等 6 大板块,满足用户行前到行中的出境场景。在覆盖城市上,目前已经 100%覆盖全球热门旅游目的地,大家出境游玩时都可以体验使用。根据官方提供的数据,超过 30%的自由行游客在出境时会选择使用美团,当前美团已经成为除微信之外,国人在境外最喜欢打开的移动 App 之一。


境外业务与其他境内业务相比,区别主要表现在以下及方面:


用户在境外访问


境外业务很大一部分流量来自境外访问,国外网络情况十分复杂,一些国家的网络基础设施很差,4G 覆盖率很低,从国外访问国内机房,不仅网络链路长,还涉及到跨网跨运营商跨 GFW 的访问情况,访问延迟、网络丢包等情况非常严重。


大量使用 Hybrid 实现


由于业务发展很快,业务新增及变更也相对频繁,为适应业务的快速发展,我们大量采用的是 H5 方式实现,大量使用 Hybrid 模式。H5 相比 Native 页面需要加载的内容更多,对网络环境的要求更高。


与境外商家对接


除了用户在境外访问,境外业务还会和很多境外的商家、供应商或代理商有合作对接,同样面临着跨国网络访问的问题。


基于以上背景,如何提升产品性能,做到像国内业务一样,其中面临了很多的技术挑战。本文将从网络优化、前端优化、后端优化几个方面来介绍境外业务在性能优化方面的做过的一些事情。

网络优化

网络问题

影响网络性能的问题有很多,常见的网络问题有以下几类:


问题一:DNS 问题


DNS 问题最容易被大家所忽视,而实际上 DNS 出问题的概率非常大,DNS 问题主要有 2 类:


一类是 DNS 解析慢或解析失败,我们统计过一些数据,我们的域名在国内 DNS 解析耗时大概在 30-120ms 之间,而国外网络下耗时达到 200-300ms 左右。在 2G/3G 等弱网环境下,DNS 解析失败非常常见。DNS 对于首次网络访问的耗时及网络成功率会有很大的影响。


下图是我们利用页面测速工具(GTmatrix)在加拿大温哥华节点测试的一个页面首次访问时的网络请求情况,可以看出当用户在加拿大第一次访问且运营商 LocalDNS 无 NS 缓存记录时,DNS 解析耗时 2.36s。



另一类常见问题是 DNS 劫持或失效,乌云(WooYun)上曾报过多起因域名服务商安全漏洞被黑客利用导致网站 NS 记录被篡改的 case。而更多的 DNS 劫持问题则是来自于网络运营商的作恶,主要有以下几种:


  1. 本地缓存,各运营商确保网内访问,同时减少跨网结算,运营商在网内搭建了内容缓存服务器,把用户域名强行指向内容缓存服务器。

  2. 内容劫持,有部分 LocalDNS 会把部分域名解析指向内容缓存,并替换成第三方广告联盟的广告。

  3. 解析转发,运营商的 LocalDNS 还存在解析转发的形象。指运营商自身不进行域名递归解析,而是把域名解析请求转发到其他运营商的递归 DNS 上,解析请求的来源 IP 成了其他运营商的 IP,从而导致用户请求跨网访问,性能变差。


问题二:网络链路问题


链路过长、请求经过的路由转发跳数过多、跨网访问等都是影响网络传输性能的关键因素。另外网络攻击(主要是 DDoS、CC 攻击等洪水攻击)流量也影响着网络链路的稳定性。据统计,骨干网上每天有数百 G 的流量为攻击流量。


问题三:传输 Payload 大小


移动设备的网络在非 Wi-Fi 环境下时通常不太稳定,再加上有 TCP 拥塞策略的限制,数据传输量越大,传的就越慢。我们需要尽量的减少数据传输量。通常的做法有:数据压缩、图片压缩、选择更高效的序列化算法(比如 Protocol Buffers)等。


我们在网络优化方面主要做了以下几件事情:


  1. CDN 优化:海外 CDN 加速、CDN 缓存预热。

  2. DNS Prefetch:DNS 预热,刷新移动设备系统/VM 的 DNS 缓存。

  3. 长连接:“代理长连接”Shark,专线链路优化,并且有效解决了 DNS 的瓶颈问题。

  4. 网络链路优化:通过专线和代理,解决公网链路长及网络抖动不稳定的问题。


接下来,我们分别详细阐述一下。

CDN 优化

CDN 服务的好坏主要取决于节点部署的覆盖程度、带宽以及调度算法。对国内业务而言,使用蓝汛、网宿、帝联等老牌 CDN 服务商或腾讯云、阿里云、UPYUN 等云 CDN 服务商性能都很好,但这些 CDN 服务商在境外的节点很少。为了提升境外的静态资源加速效果,我们尝试对接了很多国外的知名 CDN 服务商。通过智能 DNS 解析用户的 IP 来源,如果是境外访问则 CNAME 到国外 CDN,国内访问时仍然走的是国内 CDN。


CDN 也是一种缓存,是缓存就不得不谈命中率的问题。 如果用户在境外访问时 CDN 未命中,静态资源从境外回源到国内源站获取,成本非常高。为了提升缓存命中率,我们的做法是在香港搭了一个 CDN 中间源,在前端资源发布时会调用 CDN 的 push 接口把资源预热到中间源,保证当境外边缘节点缓存未命中时无需再回源到国内 IDC,只需从中间源获取。


DNS Prefetch

由于 DNS 的种种问题,腾讯推出了 HttpDNS 服务,使用 HTTP 协议向 DNS 服务器的 80 端口进行请求,代替传统的 DNS 协议向 DNS 服务器的 53 端口进行请求,绕开 Local DNS,避免网络劫持和跨网访问等问题。但 HttpDNS 需要能够获取 CDN 边缘节点的 IP,这就限制了只有像腾讯、阿里这种有自建 CDN 的大厂才能实现。


另外 W3C 也提供了 DNS 预读的方案,可以通过在服务器端发送 X-DNS-Prefetch-Control 报头,或是在文档中使用值为 http-equiv 的 <meta> 标签:


<meta http-equiv=“x-dns-prefetch-control” content=“on”>


的方式来打开浏览器的 DNS 预读取功能,但是该 API 功能目前在移动端浏览器内核中实现支持的较少。


我们采取的是一种轻量级的方案,如下:


  1. 利用 App 启动时的 config 接口,下发 DNS Prefetch 的配置参数:开关、时间间隔、需要进行 prefetch 的域名列表等。

  2. 监听 App 启动、网络变化、定位城市变化、配置文件变化、前后台切换等事件,在独立的线程中执行 DNS Prefetch 的逻辑。

  3. 如果开关打开,且上次 Prefetch 的时间距离当前的时间大于阈值,则刷新 DNS,触发操作系统/VM 层的缓存功能。



DNS Prefetch 上线后境外域名解析时间 RT90 从 350ms 下降至 250ms 左右。

长连接

HTTP 请求重度依赖 DNS,DNS 劫持、移动端网络不稳定使建连失败,以及公网链路质量差等因素,导致移动端的网络成功率一直不高。HTTP 2.0 可以通过 SSE、WebSocket 等方式与服务端保持长连接,并且可以做到请求多路复用,但 HTTP 2.0 对运维、前端、后端的改造成本非常高。基于此背景美团自研了 Shark 服务。一种“代理长连接”的模式,主要用于解决移动设备网络通信质量差的问题。


  • Shark 在国内和境外部署了多个接入点,类似于 CDN 的就近访问,用户可以就近连接到 Shark 节点。

  • Shark 各节点的 IP 会在 App 启动时加载到设备,客户端通过“跑马测试”(ping 各节点)的方式选择最优节点,建立并保持 TCP 长连接。

  • Shark 节点和 IDC 之间通过专线连接,从而保证了网络链路的质量。

  • 客户端 Shark 的网络层会拦截 App 内的 HTTP 请求,通过特定的协议格式将 HTTP 请求信息转化成 TCP 包传到 Shark 节点,Shark 节点再将 TCP 请求“还原”成 HTTP,再通过专线请求后端服务。

  • 当 Shark 通道出问题的时候,可以 failover 到普通的 HTTP 模式,从而实现高可用。


这种“代理长连接”的模式,对后端业务是无感知的,业务无需做任何改造。另外也巧妙的绕开了 DNS、公网质量差等问题,极大的提升了 Native API 请求的网络成功率。



关于 Shark 的详情,可以参考之前发表的文章《美团移动网络优化实践》

Ajax 接长连

目前美团大部分的 App 都接入了 Shark SDK 基础网络库,Native API(我们内部叫 Mobile API,MAPI)的网路请求由 Shark SDK 统一解决,使用的是自定义的序列化方式(内部称 DPObject,比 JSON 效率高)。但对于 H5 页面中的 Ajax 请求,是没法直接享受到 Shark 带来的“福利”的。先看一下 Hybrid 模式下一次 Ajax 请求的过程:



上图可以看出,一次普通的 Ajax 请求会由 WebView 的内置浏览器内核来发送接受请求,一般是 JSON 格式的数据,和 PC 浏览器的一次 HTTP 请求过程差别不大,都是要经过 DNS、TCP 建连以及要面对公网链路差等问题,另外 Ajax 请求没法复用 TCP 连接,意味着每次请求都要重新建连。有了 MAPI 的经验,我们很容易想到,能否像 MAPI 一样利用长连通道来提升性能呢?


一种方式是在 WebView 中拦截页面的 HTTP 请求,在容器层做请求代理并处理序列化反序列化等事情。这种方式对业务比较友好,业务方几乎不需要做什么事情。但 WKWebView 的限制比较多,所以该方案目前很难推行。另一种方式是通过 JsBridge 来实现,缺点是对业务侵入性较高,业务方需要手动控制桥 API 的调用,一期我们选择的是“较笨拙”的方案二。


网络链路优化

用户境外访问

Ajax 接长连解决了 Hybrid 模式下 App 内的 H5 场景,而对于 App 外的入口场景,如 M 站(针对手机的网站)、微信朋友圈分享等,我们没法使用到 Shark 长连接,跨网跨国访问的问题依然存在。这种情况下我们的优化主要是“利用专线”:


  • 我们的后台应用和数据部署在上海机房,在香港机房(香港 IDC 是个租用机房,未部署数据和应用,非“异地多活”)内部署了一组 SLB(反向代理和七层负载均衡,基于 tenginx 实现)。

  • 利用专线连接上海和香港的机房,解决了 GFW 拦截过滤、跨境网络访问及公网链路差的问题。

  • 当用户在境外访问时,智能 DNS 会解析出香港机房的 IP,请求经香港 SLB 走专线转发到境内服务器;而当用户在境内访问时,则直接请求到上海的机房。


境外直连对接

另一个场景是,我们和很多的境外供应商有直连对接,通过 HttpClient 的方式后端发起调用对方的 Open API 接口,这种场景优化前接口延迟及网络成功率都非常不理想(很多和国外对接的业务应该都遇到过类似的问题),我们的优化方案是:


在香港部署一个正向代理 Squid,请求先由内网专线转发到香港的 Squid 服务器,再从香港机房的网络出口出去。以与香港迪士尼的对接为例,优化前的 API 接口 RT95:9s+(迪士尼接口传输的数据非常多),优化后降到 2.3s,效果非常明显。


CDN 动态加速

除了专线方案,我们还测试 CDN 动态加速。


CDN 不仅可以用来对静态资源做缓存加速,也可以对动态数据接口起加速作用,原理如下:



用户请求耗时=用户和边缘交互的时间 + 1*RTT(边缘到源站)+ 源站处理时间


HTTP 请求中,建连是个非常耗时的事,普通 HTTP 请求 TCP 3 次握手要消耗 2 个 RTT 时间,如果用户和服务器位置很远,比方说用户在美国,服务在中国,请求走海底光缆的话一次 RTT 理论值是 150ms 左右(光波信号传输速度结合物理距离计算得出),实际肯定大于理论值。


CDN 动态加速主要在以下几方面起到优化效果:


  1. 用户与服务器的建连改成与 CDN 边缘节点建连(就近访问),缩短了建连时间,同时也提升了建连成功率。

  2. CDN 与源站之间通信相比公网网络链路质量有保证。

  3. CDN 节点和源站的连接可复用。


我们实测下来 CDN 动态加速在部分国家和地区有明显的加速效果,但整体的效果不够明显,所以最终未投入规模使用。

前端优化

前端优化我们主要做了下面几件事情:


  • 前后端分离

  • 图片优化

  • 域名收敛、减少请求

  • 离线化

  • 首屏 Node 后端同构渲染

前后端分离

在之前的项目中,页面是“Java 直出”的方式,由 Java 后端项目中通过 FTL 模板引擎拼装,前端团队会维护另外一个前端的项目,存放相应的 CSS 和 JS 文件,最后通过公司内部的 Cortex 系统打包发布。


这个流程的问题在于前端对于整个页面入口没有控制力,需要依赖后端的 FTL 拼装,页面的内容需要更改时,前后端同学就要反复沟通协调,整体效率比较差,容易出错,也不方便实现前端相关的优化,前端做模块组件化的成本较高。


前后端分离的关键点在于前端拥有完整独立的开发、测试、部署的流程,与后端完全分离。我们把页面的组装完全放置到了前端项目,后端只提供 Ajax 的接口用于获取和提交数据。前端页面完全静态化,构建完毕之后连同相应的静态资源通过 CI 直接发布到 CDN。这样的好处有:


  1. 前后端同学的开发工作解耦,只需要约定好 API,两边即可并行开发。

  2. 后端 API 可以做到多端复用,比如 PC、H5、M 站、小程序等。

  3. 前端主文档 HTML 页面可以利用 CDN 加速。


前后端分离架构有诸多的优点,但有一个坑需要注意:SEO 的问题,无法提供给搜索引擎可收录的页面,因为主文档 HTML 基本为空页面,需要搜索引擎蜘蛛拥有执行 JavaScript 的能力才行,现实是大部分的搜索引擎都不支持。所以对于一些需要搜索引擎引流的页面不推荐用前后端分离。

图片优化

在一些重体验的网页上,图片资源的占比通常较大,一些高清大图动则几十上百 K 大小。 针对图片这块我们主要做了以下几点优化:


  • 图片尺寸按屏幕大小自适应。原先我们图片的尺寸都是由后端控制,由服务在代码中写死下发给前端,这样带来问题是:

  • 不同设备不同大小的屏幕上使用的图片尺寸一样,无法满足所有设备。

  • 一些没经验的开发同学经常乱用尺寸,比如我们 POI 列表页的商户头图只需要 200 * 200 就够了。

  • 而新手工程师可能使用的是 800 * 800 的图片,导致页面加载慢、用户流量白白被浪费且客户端还需要做图片压缩剪裁。

  • 美团云的图片服务提供了实时剪裁功能,后端在下发图片 URL 时不需要指定尺寸,由客户端根据屏幕尺寸做自适应计算,这样可保证每台设备上的图片都“刚好合适”。

  • CDN 加速:前面 CDN 优化章节已介绍,通过接入境外 CDN 服务商及 CDN 预热的方式做 CDN 加速。

  • 图片压缩:境外业务内部已在全面使用 WebP,经测试 WebP 格式能够优化图片大小 25%-50%,清晰度基本没有影响。

  • 懒加载:图片资源通常比较大,选用懒加载可有效缩短页面可交互时间。

域名收敛、减少请求

域名和请求数过多会带来以下问题:


  1. DNS 解析成本高。

  2. CDN 加速一般都是按域名来做配置,过多的域名无形增加了 CDN 接入的成本。

  3. 浏览器的并发加载数限制,浏览器对单域名的并发度是有限的,超过限制的请求需要等待串行加载,页面加载速度会变慢。


我们做了以下几件事:


  1. 去掉一些直接引入的第三方脚本,将脚本直接打包到我们的代码中(可以利用 CDN)。

  2. 所有静态资源共用一个域名。

  3. 将一些尺寸较小的脚本和 CSS 构建过程中内联到主文档中。


通过域名收敛/减少请求数,我们商品详情页的页面请求数从 8 个减少到 4 个、域名数也减少一半,页面完全加载时间下降了约 1000ms。

离线化

离线化可以减少网络请求,加速页面加载速度。另外当用户网络不稳定或断网时也可以访问已被缓存的页面和资源,我们先后使用了 2 种离线化方案:


  1. AppCache(HTML Application Cache API),在前端项目构建流程中,通过分析页面资源依赖关系,自动生成资源 manifest 文件,这样就能够确保页面及资源发生变更时,manifest 文件内容同步更新。当浏览器监测到 manifest 文件有更新时,会自动重新下载 manifest 里面的文件。AppCache 的一个缺点是缓存文件会越来越多,缓存不容易清理。AppCache 未来会逐步被 Service Worker 所取代,无论从灵活性还是可扩展性而言,SW 都更胜一筹。

  2. 目前在使用的是公司平台自研的离线包框架,相比于 AppCache,离线包框架在资源更新,离线配置,内存管理等方面都做了很大的改善。另外 AppCache 对于用户第一次加载页面是没有加速效果的,因为只有第一次访问之后才会把资源缓存下来。而离线包框架则可以做到真正的预加载,它会监听 APP 正常启动事件,当 APP 启动后即可开始加载更新离线资源。

Node 服务端同构渲染

前面介绍了前后端分离的架构,HTML 主文档可以利用 CDN 加速,另外前后端同学很好的解耦开了,前端可以更方便的做组件化沉淀。但这种架构除了 SEO 时的问题还有另外一个问题,先看一下前后端分离下的一个页面加载过程:



当遇到页面引入的外部依赖很多时,这种架构性能可能还不如”Java 直出”:



同构渲染,结合了 Java 直出和前后端分离的优势:


  1. 通过在 Java API 之前加入 Node 层,Node 由前端同学来维护,这样仍然可以做到前后端解耦,后端同学只需要写 Ajax 返回 JSON,甚至只需要通过 RPC 接口。

  2. 缩短并优化了前端串行请求的链路,首屏数据可以更早的展示。

  3. 相比于服务端,移动端设备的性能较弱,页面在服务端渲染比在前端渲染会快很多。配合上 Ajax 长连等网络优化技术,Node 同构首屏后端渲染提升了首屏加载速度。


Node 同构和一开始的 Java freemark 后端渲染 Java 直出的方式对比,最大的区别在于:Node 项目可由前端同学来维护,用的是前端工程师熟悉的 JS 语言。另外前端生态较好,React、Vue 等框架都提供了丰富的渲染模板供前端工程师选择。

后端优化

后端优化的思路相对比较比较通用,和境外业务的特点关系性并不大,文中的前言部分“影响性能的因素”章节有简单描述,本文将不对各种后端优化手段做详细介绍, 只挑几件我们做过的事情做下简单介绍:



1. 硬件升级


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


2. 缓存化


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


3. 产品逻辑优化


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


举个例子,我们的商家系统有一个商家导出历史订单的功能,接口经常超时。排查下来是由于功能上默认是导出商家的全部历史订单,数据量过大导致。而实际业务上几个月之前已完成的订单对商家来说并没有什么意义,如果是要看统计数据我们有专门的统计功能。后来和 PM 商量后在导出时增加了时间段选择项,默认只会导出最近 3 个月的订单,超时问题顺利解决。


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


4. 服务化


我们做服务化最基础的是按业务做服务拆分,避免跨业务间的互相影响,数据和服务同时拆分。同一个业务内部我们还按计算密集型/IO 密集型的服务拆分、C 端/B 端服务拆分、核心/非核心服务拆分、高频服务单独部署等原则做拆分。


5. 异步化


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


另一种是通过 NIO 实现异步化,一切网络 IO 皆可异步:RPC 框架、Servlet 3.0 提供的异步技术、Apache HttpAsyncClient、缓存异步接口等等。


6. 搜索引擎


复杂查询以及一些聚合计算不适合在数据库中做,可以利用搜索引擎来实现,另外搜索引擎还可以帮我们很好的解决跨库、跨数据源检索的场景。

服务架构

问题背景

美团在上海、北京两地都有机房,以我们的商品服务为例,商品服务会同时被上海和北京的两侧的应用依赖调用。一开始我们的服务只部署在上海机房,由于上海、北京两地机房间地理间隔较远(北京-上海专线 ping 延迟 30ms 左右),当北京的应用调服务时就会有较高的延迟,如果一个 API 内多次跨地域调用则性能会非常差。


为此我们做了如下的缓存双集群加异地模式部署:


  1. 商品静态信息全缓存,缓存未命中时再查 DB。

  2. DB 以主从的方式部署,北京机房也部署了一套从库。

  3. 缓存数据更新使用 Databus,基于 binglog 数据同步的方式,保障 DB 和 Redis 数据的“准实时”同步。

  4. 服务、缓存、DB 均两地部署,调用方就近访问(RPC、Cache、DAL 等基础组件支持就近路由)。

  5. 缓存更新利用 Client 提供的双写模式。当 DB 数据有变更,Databus 监听到数据更新后,消费程序通过缓存 Client 提供的双写功能往两个缓存集群同时写入,服务层读数据时会选择就近的缓存集群。


通过这种双缓存加异地部署的“异地多活”模式(实际是异地只读),提升了我们服务在跨地域场景下调用时的性能。


总结

结合境外业务特点,本文从网络优化、前端优化、后端优化几个角度介绍了境外业务在性能优化上的一些实践,重点篇幅放在了网络优化部分。性能优化是一个系统性工程,需要前端、后端和 SRE 一起协作才能做好。得益于公司强大的高性能前端框架、BGP 网络、高性能应用组件、云平台等基础设施,以及在靠谱的运维保障 SRE 团队、基础架构团队以及平台团队支持下,我们境外业务的性能优化取得了阶段性的成果,后续还要继续努力。


作者简介

  • 云霜,美团后台开发工程师,美团旅行境外度假业务交易后台组技术负责人,2012 年加入原大众点评。


2020-02-25 20:33847

评论

发布
暂无评论
发现更多内容

肝了一周的 UDP 基础知识终于出来了。

cxuan

计算机网络 计算机基础

《华为数据之道》读书笔记:第 4 章 面向“业务交易”的信息架构建设

方志

数据中台 数字化转型 数据治理

推荐几款MySQL相关工具

Simon

MySQL 工具 percona server

java: Compilation failed: internal java compiler error解决办法

LSJ

IDEA

Java踩坑记系列之Arrays.AsList

Java老k

Java

讯飞推出充电宝式便携拾音器,重新定义传统拾音

Talk A.I.

表格控件Spread.NET V14.0 发布:支持 .NET 5 和 .NET Core 3.1

葡萄城技术团队

「干货总结」程序员必知必会的十大排序算法

bigsai

排序 排序算法 快速排序

MyBatis-技术专题-拦截器原理探究

洛神灬殇

以 Kubernetes 为代表的容器技术,已成为云计算的新界面

阿里巴巴云原生

云计算 Kubernetes 容器 云原生

架构师训练营 - 第五周学习总结

joshuamai

甲方日常 57

句子

工作 随笔杂谈 日常

Alibaba官方发文:阿里技术人的成长路径与方法论

Java架构师迁哥

架构师训练营 - 第五周课后练习

joshuamai

熬夜不睡觉整理ELK技术文档,从此摆脱靠百度的工作(附源码)

996小迁

Java 编程 架构 面试 ELK

Architecture Phase1 Week10:Summarize

phylony-lu

极客大学架构师训练营

大厂经验:一套Web自动曝光埋点技术方案

阿亮

埋点 曝光埋点 点击埋点 自动化埋点

SpringBoot-技术专题-如何提高吞吐量

洛神灬殇

前端高效开发必备的 js 库梳理

徐小夕

Java GitHub 大前端 js

面试者必看:Java8中的默认方法

Silently9527

java8 默认方法

成德眉资现代农业园区大联动促发展,“1链3e”引领四市农业产业数字化建设

CNG农业公链

京东千亿订单背后的纵深安全防御体系

京东科技开发者

安全 网络 云服务 云安全

Thread.start() ,它是怎么让线程启动的呢?

小傅哥

Java 线程 JVM 小傅哥 Thread

“奋斗者”号下潜10909米:我们为什么要做深海探索?

脑极体

802.11抓包软件对比之Microsoft Network Monitor

IoT云工坊

wifi 嵌入式 抓包

跨语言跨平台聚合OpenAPI文档从来没有这么简单过

Knife4j

微服务 OpenAPI Knife4j Knife4jAggregation

计算机核心课程必读书目——《高级数据结构:理论与应用》

计算机与AI

数据结构 算法

Java踩坑记系列之BigDecimal

Java老k

BigDecimal

开源认证和访问控制的利器keycloak使用简介

程序那些事

开源 程序那些事 授权框架 keycloak 认证授权

关于 AWS Lambda 中的冷启动,你想了解的信息都在这!

donghui

Serverless Faas 函数计算

架构师训练营 W06 作业

Geek_f06ede

境外业务性能优化实践_文化 & 方法_美团技术团队_InfoQ精选文章