前端学 Serverless 系列 -- 性能调优

阅读数:386 2019 年 11 月 6 日 17:08

前端学Serverless系列--性能调优

Serverless 云函数的优点是支持高并发,理论上无限自动扩容,但也有其自身的缺点,如冷启动特性导致冷启动的时延比较高。那么实际上性能如何,是否还有性能优化的空间和手段呢?

最近试点 Serverless 的一个项目是从原有的 node 服务迁移到腾讯云函数 Serverless 的。既然是项目迁移,那么就要对比一下迁移前后的性能了。

压测方案

从测试同事那很快就找到压测大师这个工具,压测大师配置和报告都还算比较完善,是腾讯出的。

缺点是:发请求的时间间隔有限制,最大只能隔 1 分钟,那就无法纯测试云函数的冷启动了,不过每个阶段都有自动增加人数,也能间接测试到冷启动到性能,看到测试结果时不时飙升到高耗时,那就多数就是冷启动的耗时。

如果测 200 以内的并发人数,可以直接测试。如果需要测高于 200 人数的并发量,需要先进行域名验证 (具体可以看压测大师提示并操作即可),就是放一个 key 到你的域名根目录下,可以让压测大师可以访问到。

这就带来了新难题,因为腾讯云自动生成的 api 网关链接下必然会有 http://yourdomain/release/ 这个环境的路径,根本无法将 key 放到根目录下。

腾讯云也提供了一个路径映射的功能,可以将这个 /release/ 的路径去掉,但是这个功能绑定在了自定义域名中,就是说,首先你得有一个自己的域名。

前端学Serverless系列--性能调优

和腾讯云的产品反馈这个问题之后,产品同学将这个需求加到了排期中。

我暂时从同事那借用了一个子域名,继续将测试工作进行下去。

注意:需要在腾讯云备案了的域名。可以绑定一个子域名,在个人的域名管理界面中,通过 cname 指向腾讯云的 API 网关域名即可。

如果你要支持 https 的话,还需要申请个证书。有免费的可以申请,同一个主域名可以申请 20 个。申请完成之后,将证书上传到腾讯云即可。

前端学Serverless系列--性能调优

如果不需要 https,直接选 http 就可以了,准备工作都 OK 了。

评测及优化

选择测试的 CGI,初步是要比较两者的链路,所以选取一个简单的逻辑,只有一个数据库查询的 CGI,压力从低到高进行尝试。

刚尝试到 200 并发人数到时候,成功率就有点不对劲了,只有 80% 多?

前端学Serverless系列--性能调优

分析问题

后来查了一下云函数的日志,问题就比较明了了。

前端学Serverless系列--性能调优

虽然说是理论上可以无限扩容,但是也要配置给不给这个上限。

将耗时比较长的部分和云函数开发一起分析,发现耗时主要集中在:

1. 函数调用:代码本身执行时间为 70ms~115ms 左右,路径耗时从 5ms~600ms 不等。
2. 热启动:也就是代码本身执行的时间,这个主要是逻辑和需要调用第三方应用的耗时。这个压测例子的耗时就会在 50ms 之内,20ms 左右。腾讯云同学反馈启动性能很快就有大的改善。
3. 现在有一些大于 5s 的,那些耗时都在路径上或者有可能在单节点处理能力上。具体消耗在哪里暂时看不出来。

优化方案

进行了代码的优化,实际上耗时最大的请求的确有所改善,但是平均值和 90% 的值还是被一些高耗时拉高。

前端学Serverless系列--性能调优

但是实际上压测大师测的结果依然没有达到很理想,下面汇总一下截止目前阶段的结果。

前端学Serverless系列--性能调优

进一步分析

理论上云函数服务该做的优化都做了,而且理论表现应该不会这么差?

后来腾讯云的同事用 python 写了脚本来自己压测,发现 200 并发的平均耗时在 200ms 之内,而且超过 200ms 的请求也在可数之内。

由于两个测试的结果不一致,从自己写的脚本和 wetest 压测方案两方展开分析。

a. 脚本尽量去还原 wetest 的方案,如异地部署,阶梯增加并发,并且每个阶段维持 30s。

b. 直接找到了 wetest 的后台同事进行问题沟通,尝试了长连接、短连接、多 IP 压力源、去掉日志打印等操作。

结果:这个压测结果其实已经达到了我们预设的优化目标,平均在 200ms 之内。

以下还是 wetest 的压测结果(短连接 + 多 IP)。

前端学Serverless系列--性能调优

其中还有一个很有意思的结果,长连接下的压测结果:

前端学Serverless系列--性能调优

那么到底是什么原因导致了这个结果的差异呢?

答案为:“网络连接耗时”。

在这个例子中,将长连接改成短连接,从一地压测改成多 IP 压测,效果最为明显,去掉日志打印也一定程度减少了压测源的性能损耗。

用户侧对比评测

既然地域不同,网络不同,耗时差异这么大,那么真实的用户耗时到底如何呢?

前端学Serverless系列--性能调优

红色的是 Serverless,黄色的是原来的 NodeServer。

分析问题

1、针对 Serverless 做了优化:将非简单请求改成简单请求,减少一次“预检”请求,加上 dns-prefetch,并加上了 NodeServer 原来的请求耗时进行对比。

刚开始是因为设置了 header 头,浏览器认为这个是非简单请求。

非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为 " 预检 " 请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。更详细可以查阅跨域资源共享 CORS 详解: http://www.ruanyifeng.com/blog/2016/04/cors.html

前端学Serverless系列--性能调优

图为一个请求产生了两个请求,第一个是预检请求,其中 method 为 OPTION, 返回状态码是 204。

如果要用到非简单请求的时候,服务端响应 CORS 的设置要注意到:

前端学Serverless系列--性能调优

如果单选具体的 GET,POST,可以在 API 网关中的 API 管理中设置是否支持 CORS,如果需要支持多个的请求方法的话,就只能后端业务处理。

2、优化之后,发现 Serverless 的请求依然比 NodeServer 慢 100ms 左右。

继续分析发现:Serverless 的请求会比 NodeServer 请求多一个 Initial connection 和 SSL 的时间。

为什么 NodeServer 没有呢,因为测试的页面和发请求的页面是同域的,所以这部分时间省了。为什么之前 Serverless 没有发现呢,因为 socket 连接之后没有那么快销毁,在页面重复刷新的时候,反而看不到这个耗时。

需清理一下 socket: chrome://net-internals/#sockets

就可以复现了,那么这个耗时差距的原因就很明显了。

我做了一个简单页面进行测试,发现这样的结果。Serverless 和 NodeServer 的全程耗时其实差不太多,但是 TCP 连接和 SSL 时间会长很多。

这是为什么呢?因为测试的这个 Serverless 是部署在上海的,而我是在深圳进行测试的。

之后再做了一个测试,加了一个部署在广州的云函数。

结果很明显。

异地访问部署的问题,因为原有的 NodeServer 接入了 STGW。

STGW 全称 Secure Tencent Gateway,腾讯安全云网关,是一套实现多网统一接入,支持自动负载均衡的系统。由于 STGW 提供了就近接入和 SSL 加速,所以这两部分时间都相应有不少的优化。

那么 Serverless 能不能用多地部署,就近接入来解决这个问题呢。

目前 Serverless 的云函数和 API 网关都是地域隔离的。也就是说广州的 API 网关对应广州的云函数,不能一个网关对多个地域的云函数。这个需求和腾讯云的产品沟通之后,也纳入到了以后的规划建设当中。

那么我们目前有没有折中的方案呢?

我们设想了一些中转的方案:

前端学Serverless系列--性能调优

最后我们选择了最右侧的方案,主要是简单。

而且还可以继续通过在 header 中设置 preconnect 减少 TCP 握手和 SSL 的时间。

复制代码
<link rel="preconnect" href="//example.com">

preconnect 的兼容性情况:

前端学Serverless系列--性能调优

使用之前:

前端学Serverless系列--性能调优

使用了之后的效果:

前端学Serverless系列--性能调优

可以看到 Initial connection 和 SSL 的时间是可以直接节省掉了,在网络差的情况下,这部分节省的时间更为显著。

小结

Serverless 云函数性能评测和优化结果:

在 API 网关监控到到耗时(不包括网络时间和握手时间)

前端学Serverless系列--性能调优

目前腾讯云 Serverless 云函数的响应性能已经达到了需要即时返回场景的可用状态,期待未来更优秀的性能。

1、压测方案、问题分析

1)wetest 是腾讯公司支持的通用压测方案,要用好也要对里面提供的设置了解清楚用法和用途。
2)测试不限于压测工具,本地脚本、浏览器 network 分析、线上用户 test 等等都可以尝试用来评测分析。

2、性能优化方案

  • 期待云方面的优化:
    允许客户设置并发上限
    冷启动、热启动、实例保留策略的优化
    架构升级(测试中)
    就近接入(待规划)

  • 代码方面的优化:
    代码逻辑和第三方调用
    拆分不常用功能,减少代码量
    使用预加载减少 connect 的时间(preconnect)
    接入 STGW 进行转发

写在最后

1、云函数在国内处于高速发展阶段,应用的过程中还会遇到各种问题,不过腾讯云的同事们积极响应,主动和我们一起寻找问题解决问题,最终一起共同成长。
2、云函数目前的特点不适合有状态的应用,但是这个不是必然的,这个问题有了合适的方案之后,就不会再是问题。

作者介绍:
龙永霞,腾讯高级前端开发工程师。目前在在线教育负责企鹅辅导业务的开发工作。对前端性能优化,全栈开发有浓厚的兴趣。

本文转载自公众号云加社区(ID:QcloudCommunity)。

原文链接:

https://mp.weixin.qq.com/s/jVQ35U-Y_nl1CFeIPacb0A

评论

发布