如同iPhone当年颠覆了诺基亚,Serverless的出现也带来了一种全新的、颠覆式的云开发架构模式。在Serverless出现前,开发者们根本无法想象几分钟就能快速部署一个Web应用上线。近日,亚马逊云科技TechTalk特别邀请了资深无服务器技术专家孙华带来分享《如何高效、极简构造无服务器Web应用》。孙华以AmazonLambda的视角介绍了无服务器Web应用的构造方式,并讲述了如何利用最新发布的LambdaFunctionURLs和LambdaAdapter进一步简化无服务器Web应用的开发和调试并且实现Web应用在Lambda,Fargate和EC2等计算平台之间平滑迁移。
Serverless时代的应用开发年,Iron公司首次提出Serverless的概念。年亚马逊云科技发布AmazonLambda第一次让Serverless从概念走向落地,也标志着Serverless时代的开启。孙华认为,AmazonLambda作为无服务器计算服务,主要有以下四个特点。
无需部署管理基础设施:无服务器计算并不代表真的没有服务器,而是不需要管理部署服务器。
自动扩展:不用考虑扩容、容量规划的问题,底层的服务会自动实现按需扩容。
按需付费:按照时间和使用量收费,避免为闲置计算资源浪费。
高度可靠与安全:基于高可用架构开发,可用性高。
AmazonLambda的出现为应用开发和部署提供了极简的模型。目前,AmazonLambda已有数十万用户,用户的调用峰值通常超过每秒超过百万级。
可口可乐公司就是AmazonLambda的用户之一。在疫情期间,可口可乐通过AmazonLambda仅用一周时间就快速把mobilepour应用的原型上线,实现手机与饮料机毫秒级的通讯,从创意到交付的时间缩短了50%。
Babble是一家线上教育服务商。疫情期间,线上学习访问量激增2-3倍。Babble通过将服务迁移到AmazonLambda服务器,P95性能提高了ms(降低近50%),且通过提高利用率,成本降低了四分之一。
无服务器Web应用使用场景Serverless架构常见的应用场景有数据处理、IT运维自动化等,不少用户还会将Serverless应用到前端的Web应用上,包括Flask、Django、Express.js、Rails等应用。Serverless可以渲染相应的Web页面到客户端,同时也支持提供json的RESTAPI,进行前后端的分离,静态的React、Angular、Vue前端通过HTTP请求,来调用后端的API,获取数据,从而展示给客户。此外,手机后端应用也经常会使用Serverless开发小程序的后端。
无服务器Web应用有哪些特点呢?首先,最常见的Web应用开发方式,服务器里面运行的是Web应用进程,此时,Web应用会监听到一个端口。并且,在AmazonLambda里面每个请求都是由一个单独的计算实例来处理的,不管CPU还是内存,都专门为这一个请求服务。这种方式的优势在于,可以将每个请求全部隔离开,不会出现某一个请求崩溃,影响其他用户的并发需求。
其次,Web应用在AmazonLambda里面运行,需要是无状态的应用。因为AmazonLambda请求会随机分发到多个计算实例上,每个计算实例在本地缓存数据,下一个请求进入,可能不会分配到同一个实例上。所以,如果需要共享状态,可以存储在Redis或者数据库中。
第三,在AmazonLambda的计算环境上,每次调用的请求处理完毕后,计算环境会被冻结到下一次请求来之前。在这段时间里是没有CPU资源的,后台任务不能运行,所以不能在AmazonLambda里面运行后台的进程。
最常见的基于前后端分离的Web应用架构,通常会把前端的SPEA应用放在AmazonS3上做HTTP、Django等,前端用CDN加速。用户下载了前端后,前端会通过APIGateway,来调用后端动态的数据。APIGateway提供相应的HTTP的入口,触发Lambda函数,从而运行Web应用。Web应用可以访问数据库或者任何后端。
新功能:LambdaFunctionURLs亚马逊云科技经常会收到客户的反馈。客户希望在AmazonLambda上学习运行Web应用或者将单独的应用运行在LambdaFunction里面。在LambdaFunction里面处理所有URL相应的业务逻辑,只需要暴露一个HTTP入口就可以了,几乎不需要任何额外的学习成本。上个月,亚马逊云科技推出了AmazonLambda内置的FunctionURLs端口,在Lambda函数里配置一个FunctionURL,就可以提供HTTPSEndpoint。目前该功能仅在AmazonGlobal提供,在中国区会于近期上线。FunctionURLs指向AmazonLambda的最新版本,或者是AmazonLambda别名。AmazonLambda别名可以指向1~2个AmazonLambda的版本,因此可以通过指向alias的方式进行灰度发布或者蓝绿部署。
LambdaFunctionURLs与APIGateway之间有什么区别?
首先,FunctionURLs是非常简单地内置提供HTTP入口的方式。它是暴露在公网上的HTTP入口,其入口方式是HTTPS的,认证方式可以采用IAM的权限控制或者在公网上实现。FunctionURLs不提供Customdomain支持,但是提供CORS支持,因此可以跨站请求,比如,浏览器发来Option,FunctionURLs会主动根据配置,返回相应的结果,不会触犯Lambda函数。但是,FunctionURLs只具备一些简单的功能,对于一些高级的功能没办法实现,比如,使用UsagePlans,基于WAF的集成和在内部提供PrivateEnedpoint,目前FunctionURLs是无法实现的。因此,如果想使用WAF、UsagePrivate、PrivateEnedpoint等功能,请使用APIGateway的RestAPI。
其次,LambdaFunctionURLs的超时时间是与函数的超时时间是一样的,比如,函数最长要运行15分钟,LambdaFunctionURLs请求就可以运行15分钟,而RestAPI和HTTPAPI的超时时间仅为29-30s。在PayloadSize上,FunctionURLs跟AmazonLambda是一样的,均为6MB。
第三,采用LambdaFunctionURLs不需要支付额外的费用,但是采用RestAPI与HTTPAPI都需要支付相应的费用。
很多用户需要Web应用有相应的自定义域名访问网站。这时,可以在前面通过CDN的方式,加上自定义域名,比如,在CloudFront上加上自己的域名,同时结合AmazonWAF进行相应集成应用的防护。因为FunctionURLs只提供HTTPS的入口,在CDN回源的时候,是通过HTTPS回到源站的,不能把HostHeader传回源站,不能获得用户真正访问的自定义域名。如果域名是固定的,可以在应用里通过配置了解,但如果域名不是固定的,那么就需要根据二级域名确定是哪个租户在做相应的处理。这种情况下,就可以利用CloudFrontFunction的功能。CloudFrontFunction可以在用户请求端获取域名,加到另外的Header里面,再把Header传回源站,在源站的应用里面就可以通过这个Header获得用户访问的真实的域名。
如果基于LambdaFunctionURLs部署单函数的的Web应用,前面通过CloudFront做动态请求的代理,静态资源放在AmazonS3,就会统一为如下架构,也就不需要APIGateway了。
新工具:LambdaAdapterLambdaFunctionURLs为大家提供了一个非常简单就可以获得HTTP入口的方式,但是AmazonLambda的开发方式是基于事件驱动的方法来进行开发的,会将事件源过来的事件转换为json对象。对于熟悉Web应用开发的开发者,会有额外的学习成本,一般采用的做法是在应用里面写一个Handler函数,进行一层转换,把json转成Web应用需要的格式,但是这种方式可以进一步简化。
亚马逊云科技推出的新工具LambdaAdapter作用就是帮助用户完成转化。采用LambdaAdapter无需修改代码即可在AmazonLambda上运行Web应用。LambdaAdapter从AmazonLambda获得相应的json对象,把它转换成HTTP请求,发送到Web应用上,Web应用处理之后通过HTTPResponse回到LambdaAdapter,LambdaAdapter会将它转换成Lambda需要的jsonResponse的格式。这样不管用什么语言,什么样的Web框架,开发Web应用或者HTTPAPI,都可以通过这样的方式,不需要修改代码,也不需要添加任何的依赖,就可以在AmazonLambda上运行,且不需要用特殊的工具,就可以用熟悉的方法在本地开发调试API。
此外,LambdaAdapter支持APIGateway的RestAPI、HTTPAPI,作为HTTP的事件源。不管是哪种格式,LambdaAdapter都可以做相应的解析并转换。同时因为LambdaFunctionURLs的事件格式和APIGatewayHTTPAPIV2事件格式完全一致,所以LambdaAdapter不用做任何的修改,就可以接入LambdaFunctionURLs。用户结合LambdaFunctionURLs和LambdaAdapter就可以把Web应用或者HTTPAPI运行在Lambda上面。同时,因为Web应用有可能返回图片等Binary数据,因为json里面是不能直接存Binary数据的,所以Binary数据要做base64encoding,LambdaAdapter会检测返回的数据是不是Binary数据,并且自动完成base64转码工作。
同时,Adapter支持用容器镜像的方式打包函数,也支持用zip的方式来打包函数。当用户使用容器镜像的方式打包函数,得到的容器镜像既可以在AmazonLambda上运行,也可以在容器环境里面运行,甚至在本地的电脑上运行。所以Web应用可以非常方便地运行在不同的计算平台上,不需要做修改,就可以在不同的平台之间平滑地迁移。
构造无服务器Web应用实践通过LambdaFunctionURLs和LambdaAdapter可以很方便的通过熟悉的API的方式,构建了Web应用。但是如果用LambdaAdapter,是否可以把现有的Web应用运行在AmazonLambda上呢?
亚马逊云科技用WooCommerce进行了尝试。WooCommerce是一个电商的场景,为什么要尝试将WooCommerce运行在AmazonLambda上呢?首先,在Buildwith网站上,访问量最大的一百个网站中,WooCommerce所占份额第一;其次,Wordpress是基于PHP开发的,PHP在Web应用网站建设上,大概有70-80%的网站是基于PHP开发的,使用量非常广;第三,PHP语言,每个请求进入,都需要重新进行初始化,同AmazonLambda无状态的计算环境非常契合。
亚马逊云科技团队采用了如下无服务器WooCommerce架构,在AmazonLambda上运行WordPress。
该架构前面部分采用Route53、CloudFront做CDN,用AmazonLambda运行应用,前端用LambdaFunctionURLs代替APIGateway作为入口,并将静态资源通过AmazonS3存储。然后,在Lambda函数里面通过Docker镜像的方式,把PHPRuntime、NGINXServer和PHPFPM运行的进程管理服务加载进来,把Wordpress与WooCommerce代码打包进去。后端用相应的数据库,比如Redis、最新的V2数据库做数据的缓存,用EFS共享的系统来保存用户上传的文件。通过该架构,亚马逊云科技实现了在Serverless基础上运行WordPress。
在Serverless上运行网站实际性能如何呢?如果在WordPress的网站想要做到比较好的性能,可以把WordPress静态化,变成静态内容放在前端的CDN网站上。如果运行的是WooCommerce电商网站,用户浏览商品、将商品加入购物车、提交订单、支付,是动态请求,需要回到后端的PHP应用上。对于静态应用,性能方面可以做到3分钟内从无请求到最高峰值,每分可处理2万多笔订单,持续1小时。成本方面,每处理一笔订单需要调用10次API,也就是处理万笔订单需要调用0万次Lambda函数。据统计,0万次Lambda函数调用的费用也仅为美元。不仅如此,在测试过程中网站的API响应时间也非常平稳,P99延迟仅为在1-2s,P50延迟只有ms左右。
分享的最后,孙华针对Serverless上运行网站实际性能进行了演示,并提供了Serverless相关的资料,感兴趣的开发可扫描下方