境外业务性能优化实践

本文根据第16期美团技术线上沙龙OnLine演讲内容整理而成。

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

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

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

1.产品逻辑与用户行为

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

2.基础网络

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

3.代码及应用

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

4.移动端环境

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

5.硬件及云环境

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

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

用户在境外访问

境外业务很大一部分流量来自境外访问,国外网络情况十分复杂,一些国家的网络基础设施很差,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劫持问题则是来自于网络运营商的作恶,主要有以下几种:

问题二:网络链路问题

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

问题三:传输Payload大小

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

我们做了以下几件事:

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

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

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

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

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

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

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

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

1.硬件升级

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

2.缓存化

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

3.产品逻辑优化

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

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

4.服务化

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

5.异步化

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

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

6.搜索引擎

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

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

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

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

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

THE END
1.前端和后端的区别前端和后端有什么区别常见问题前端:代码在用户的浏览器中执行,主要在客户端运行。 后端:代码在服务器端执行,通常在服务器上部署和运行。 总的来说,前端主要关注用户界面和用户交互,而后端则负责处理数据和业务逻辑,二者相互配合构建完整的Web应用程序。 前端入门到VUE实战笔记:立即学习 ...https://m.php.cn/faq/713299.html
2.前端常见面试题vue优点:一次加载后,后面都是本地浏览器缓存,有点像客户端软件,交互快。 通过异步请求方式交互数据,有效的前后端分离,后端只关心接口处理, 减轻服务端的压力,展示和渲染都在前端浏览器完成。 后端的接口可以复用,通过json格式,可以在pc移动端都通用 缺点:首屏加载慢,很多资源都要第一次一次性加载完,容易白屏 ...https://www.jianshu.com/p/8522cfd5aee7
3.im由于历史原因,现在主流的 http 协议是无状态协议(HTTP2 暂时应用不广泛),一般情况是由客户端主动发起请求,然后服务端去响应。那么为了实现服务端向客户端推送信息,就需要前端主动向后端去轮询,这种方式低效且容易出错,在之前我们的管理端首页确实是这么做的(5s 一次)。 https://gitee.com/colala/im-server/
4.前端,后台,后端,前台他们区别是什么?小辣椒樱桃前台和后台都是在客户端或者浏览器上浏览者浏览的界面和管理者管理的界面 3.前端 这个是编程时候的概念,基本包括所有可见部分的代码编写,如果三层架构的话,可以看做是UI层. 4.后端 这个是对应前端而言的,编写的代码基本上都是提供给前端调用,而不需要处理UI的内容.例如逻辑层,或者存储过程. ...https://www.cnblogs.com/aaaazzzz/p/13023372.html
1.服务端和客户端以及前后端相关概念区分服务端和客户端到底是什么服务端和客户端以及前端和后端是两组相关但不完全相同的概念。 一、服务端(Server-side)和客户端(Client-side) 服务端和客户端是指在分布式系统或网络应用中相对的两个部分。是指在计算机网络中不同角色的两个主要实体。 服务端:服务端是指提供服务的计算机或服务器。它接受来自客户端的请求,并根据请求提供相应的...https://blog.csdn.net/m0_62006803/article/details/136151175
2.客户端服务端前台前端后端后台区别在哪?今天来聊一聊网站开发的基础知识:客户端、服务端、前端、前台、后端、后台之前有什么区别和联系。 首先是客户端、客户端也常被叫做用户端、顾名思义、就是用户使用的终端、例如你电脑上的QQ、微信、钉钉等软件、当然手机上也是一样、这些都是客户端(Client)。与之相对应的就是服务端了、服务端是为客户端提供数据...https://blog.51cto.com/u_11541173/5763222
3....也是奔波于各种面试。我自己总结了很多方向的前端面试题,服务器为了提高网站访问速度,对之前访问的部分页面指定缓存机制,当客户端在此对这些页面进行请求,服务器会根据缓存内容判断页面与之前是否相同,若相同便直接返回304,此时客户端调用缓存内容,不必进行二次下载。 状态码304不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应。 https://juejin.cn/post/7149438206419664927
4.关于前端和后端:说一说前端路由与后端路由的区别后端路由与服务端渲染 前面说了,「刀耕火种」的年代里,网页通常是通过后端路由直出给客户端浏览器的。也就是网页的html一般是在后端服务器里通过模板引擎渲染好再交给前端的。至于一些其他的效果,是通过预先写在页面里的jQuery、Bootstrap等常见的前端框架去负责的。 https://maimai.cn/article/detail?fid=1749517863&efid=RknOuyXMMmiLjUJ7SWEFTg
5.三明市第一医院生态新城院区智慧医院智能化项目院区楼宇智能化...10、支持安全组服务,可以对进出虚拟机端口的网络报文进行安全过滤规则设置。虚拟机端口与安全组关联后,安全组规则可对进出虚拟机端口的网络报文进行过滤,只有规则允许的报文可通过。 11、支持对访问负载均衡的客户端IP进行白名单安全控制,如果使用访问控制能力,则只有被允许的IP能通过ELB访问后端云服务器/物理机;如果不...http://zfcg.cz.sm.gov.cn/upload/document/20221024/df8e2d7d2af449fbbe8f17d25733ff6d.html
6.全面讨论后端前端客户端的区别全面讨论 后端、前端、客户端的区别 帖子背景 楼主看到今年不少友友暑期实习都或多或少,被客户端岗位打捞起来面试;也有很多友友本来是投的后端,结果拿了客户端的offer,不知道改不改转客户端。 楼主之前在字节的CapCut做过半年的客户端开发实习生,对客户端有一个基本的了解,再加上后端楼主也实习过,所以两个方向...https://m.nowcoder.com/discuss/616306212254015488
7.后端测试和前端测试的区别后端测试和前端测试的区别 后端测试是对服务器端应用程序进行测试,例如 API 接口、数据库操作等。后端测试需要掌握服务器端编程语言(如 Java、Python、PHP 等)、数据库等相关技术,主要关注服务器端的逻辑、性能和安全性。 前端测试则是测试应用程序的客户端部分,即用户界面、页面布局、交互设计、功能实现等,需要掌握...https://www.hxsd.com/content/31353/
8.服务端开发和前端有什么区别前端 职位描述 1. 负责产品服务端模块的设计和开发 2. 负责产品服务端框架设计和开发 3. 负责服务器相关工具开发和维护 4. 负责深入优化服务端性能,保证系统服务端的质量和性能 5. 同策划及客户端人员进行有效沟通,分析、解决各种服务器的问题 职位要求 ...https://www.jobui.com/gangwei/pk/fuwuduankaifa-qianduan/
9.一口气说出前后端10种鉴权方案~腾讯云开发者社区Session-Cookie认证是利用服务端的Session(会话)和浏览器(客户端)的 Cookie 来实现的前后端通信认证模式。 在理解这句话之前我们先简单了解下什么是 Cookie以及什么是 Session? 2.1 什么是 Cookie 众所周知,HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息)...https://cloud.tencent.com/developer/article/2144184
10.服务端渲染(SSR)Vue.js然而,Vue 也支持将组件在服务端直接渲染成 HTML 字符串,作为服务端响应返回给浏览器,最后在浏览器端将静态的 HTML“激活”(hydrate) 为能够交互的客户端应用。 一个由服务端渲染的 Vue.js 应用也可以被认为是“同构的”(Isomorphic) 或“通用的”(Universal),因为应用的大部分代码同时运行在服务端和客户端。https://cn.vuejs.org/guide/scaling-up/ssr