对Serverless架构的一点体验和思考

    xiaoxiao2021-04-18  277

    发端

    云计算机经过这么多年的发展,逐渐进化到用户仅需关注业务和所需的资源。通过Swarm、K8S这些编排工具,容器服务让开发者的体验达到很完美的境界。我曾经觉得Docker可以替代虚机,用户只要关注自己的计算和需要的资源就行,不需要操心到机器这一层。但是因为Docker对资源的隔离不够好,各大云厂商的做法还是一个Docker对应一台虚机,不仅成本高,给用户暴露虚机也多余了。

    用户为什么需要关注业务运行所需要的CPU、内存、网络情况?还有没有更好的解决方案?Serverless架构应运而生,让人们不再操心运行所需的资源,只需关注自己的业务逻辑,并且为实际消耗的资源付费。可以说,随着Serverless架构的兴起,真正的云计算时代才算到来了。

    容器在开发模式方面并没有提出新的想法,大家还是在用传统的那一套开发模式,需要写一个大而全的后端服务。与之对比,Serverless架构是事件驱动的,这样让后端的开发体验变得跟前端和移动端很类似了。针对不同客户的需求,先让其购买好相关的资源,然后一个个填坑,给不同的产品添加各种事件处理逻辑就行。这就跟iOS开发一样,界面写出来,然后处理一个个事件就好了,大家都很容易理解这种开发模式。

    AWS Lambda体验

    AWS在2014年11月的re:Invent大会上推出Lambda,经过将近三年的发展,已经达到了非常完善的程度。Lambda主要有三个作用。

    跟API Gateway结合起来,方便快捷地提供API服务。串联关键产品,比如在DDB插入一条新数据之后,触发Lambda执行,读取新记录送给搜索引擎建索引。扩展功能,比如Cognito User Pool提供非常多的点,方便用户在登录的时候增加自己的处理逻辑。

    AWS Lambda支持多种语言开发,比如C#、Java、Node.js和Python,拥有广泛的群众基础。

    AWS Lambda在除北京之外的所有region均可用。AWS中国支持的产品可以参考:地区表。

    Serverless Reference Architecture: Mobile Backend是一个非常好的实例,讲述了如果通过Serverless架构实现一个App。

    这个App的主要功能类似Evernote,支持上传图片,编写和上传文章。功能非常简单,但是涉及到的产品非常多,玩法也非常老练。

    123

    整个demo用到的云产品和它们相互之间的关系如下图所示。除了Lambda本身,IAM、API Gateway等产品也发挥了巨大的作用。

    $ tree cloudformation lambda-functions cloudformation ├── config-helper.template ├── mobile-backend-no-cloudfront.template //去除CloudFront相关配置的template文件。在CloudFormation控制台上传该文件。 └── mobile-backend.template //如果CloudFront可用的话,上传这个template文件也OK。 lambda-functions //Lambda代码已经压缩好并放到一个公共的S3 bucket里面,所以不用管这些代码。 ├── search │   └── index.js //CloudSearch搜索接口的代码 ├── stream-handler │   └── index.js //DDB触发建索引的代码 └── upload-note └── index.js //新增文章接口的代码,主要是写DDB。

    配置

    CloudFormation真的很方便,template上传之后,相关的资源就创建和设置好了。cloudformation目录下有两个template文件,只需上传mobile-backend.template,它会把config-helper.template加载好。阿里云对应的产品是:资源编排ROS。

    看起来API Gateway、Cognito、CloudSearch这几款个产品对CloudFormation支持的并不好,所以还需要通过文章中那么多命令行和Web控制台上的设置。

    为了能运行这些命令,要把AWS CLI配置好,region设置为us-east-1(弗吉尼亚北部),因为文章中存放Lambda代码压缩包的S3也是在us-east-1区域的。

    $ aws configure AWS Access Key ID [****************X3CA]: AWS Secret Access Key [****************Qo3J]: Default region name [us-east-1]: $ cat ~/.aws/config [default] region = us-east-1
    配置里面的一些坑

    一个坑是CloudFront可能没有初始化好,导致CloudFormation创建失败。懒得去配置了,所以我干脆删除了CloudFormation里面CloudFront相关的配置。这样并不会影响体验。

    CloudFormation有一个资源创建失败后,会rollback。它把资源的创建当做一个事务来处理,全部成功才行。

    客户端使用Swift 2.3写的。因为代码也比较简单,所以Convert到3.0就行。后面接着会报Ambiguous use of 'continue'错误,类似下面这样的代码使用一对小括号括住block就行。

    let noteApiClient = APINotesApiClient(forKey: "USEast1NoteAPIManagerClient") noteApiClient?.notesPost(noteRequest).continue ({ (task) -> AnyObject! in if let error = task?.error { print("Failed creating note: [\(error)]") } if let exception = task?.exception { print("Failed creating note: [\(exception)]") } if let noteResponse = task?.result as? APICreateNoteResponse { if((noteResponse.success) != nil) { print("Saved note successfully") }else { print("Unable to save note due to unknown error") } } return task })

    程序运行起来之后,Upload Image到S3没有问题。但是上传文章的时候会报forbidden的错误。Xcode里面会打印下面这个错误。通过Charles抓包,发现服务器端给了错误提示。

    需要在Usage Plans里面Add API Stage里面操作一下,API和Stage对上就好了。文章中没有提到这个配置。

    一些技术细节

    App直接面对API Gateway和S3,要先从Cognito Identity Pool获取到一个id(Unauthenticated),这个Pool对应MobileClientRole角色,可以看一下这个角色的具体配置,主要是针对S3和API Gateway相关action的allow 。这里直接使用了API Gateway生成的SDK,结合Cognito Identity Pool用着也挺方便。API Gateway也支持使用Cognito UserPool做验证器,不需要SDK,用起来更加方便一些,详细信息可以参看:[对AWS Cognito的一些理解](http://www.jianshu.com/p/112438fb86aa)。

    /notes的post接口交给NotesApiFunction Lambda来处理,在控制台可以看得很清楚。

    DDB变动会触发执行DynamoStreamHandlerFunction这个Lambda,从配置里面也可以很清楚看到这个trigger。

    效果

    S3里面可以看到图片。

    Dynamo DB里面可以看到Post数据。

    但是CloudSearch里面Searchable Documents却一直都是0。

    可以看看DynamoStreamHandlerFunction这个Lambda的数据,发现调用都失败了。

    去CloudWatch里面看看。提示TypeError: Cannot read property 'S' of undefined。

    对着stream-handler/index.js看了一下,发现拿到Dynamo DB的数据之后,要通过.S将其转型为字符串类型。再对着文档看看,其实是没有毛病的,所以这个问题还不知道怎么解决。

    function createSearchDocuments(records) { var searchDocuments = []; for(var i = 0; i<records.length; i++) { var record = records[i]; if (record.eventName === "INSERT") { var searchDocument = { type : 'add', id : record.dynamodb.Keys.noteId.S, fields : { headline : record.dynamodb.NewImage.headline.S, note_text : record.dynamodb.NewImage.text.S } }; searchDocuments.push(searchDocument); } } return searchDocuments; }

    这个问题突然就消失了,建索引和检索功能都正常了,amazing~

    费用

    Lambda根据使用内存和调用次数收费。内存最低是128MB。具体信息请参看:Lambda 定价详情。

    这个App使劲玩,花不了几块钱的。Lambda累计运行了240秒,没有花钱,主要是S3和数据传输花了点钱。

    Serverless成功的关键

    拥有丰富的产品,并且打通所有的云产品,是Serverless成功的前提条件。Lambda不适合处理复杂的业务逻辑,比较适合作为胶水代码,粘合关键的产品。另外就是Lambda不管怎么完善,可能只能解决80%的问题,剩下20%的逻辑需要用户自己写服务,通过docker发布,然后给Lambda或者用户使用。这种混合的编码方式可能是未来的主流开发模式。

    Serverless的主要优点

    开发者更加专注于业务逻辑,开发效率更高。开发一个典型的服务器端项目,需要花很多时间处理依赖、线程、日志、发布和使用服务、部署及维护等相关的工作,基于Serverless架构则不需要操心这些工作。用户为实际使用的资源付费。用户购买的ECS使用时间一般不到5成,但是为另外5成闲置时间付费了。Lambda按照运行的时间收费,成本会低很多。NO Architecture,NO Ops。架构师的责任是设计一个高可用、高扩展的架构。运维负责整个系统稳定可靠地运行,适当缩减和增加资源。大型云厂商能保证产品的高可用,Serverless架构本身就是高扩展的。Serverless不再需要服务器端的工作人员,给客户节省了大量的资源。架构师和运维的同学应该好好思考一下未来的出路了。架构师可以转型去做销售,整理用户的需求,然后写写CloudFormation的template就好了。

    还是成本。IT行业一些领先的公司基础设施非常完善,开发工程师写好代码,然后通过发布平台发布,感觉也是挺方便的。比起Serverless的架构,成本还是要高不少。

    机器成本。日常、预发、线上,1+1+2=4台服务器少不了。时刻要关注业务数据,盘点资源,看看是否需要扩容和缩减资源。扩容容易,缩减难,造成大量资源闲置。全链路压测是不是很烦?

    Serverless的主要缺点

    排查问题困难,因为逻辑散落在各处,一个操作可能触发成百上千个Lambda执行。AWS的X-Ray和CloudWatch等产品可以帮助用户排查问题。准备runtime需要时间,流量瞬间爆发容易导致超时。带状态的Lambda写起来很困难。Lambda运行有诸多资源限制,比如运行时长、内存、磁盘、打开的文件数量等。厂商锁定。云计算是赢者通吃的行业,大而全的云厂商优势巨大,Serverless加剧了这种趋势。以前用户还需要自己写很多服务器端的逻辑,迁移的时候,把服务器端代码重新部署一下。采用Serverless架构之后,代码都是各个平台的Lambda代码片段,没法迁移。从客户的角度来看,是不希望自己被某家云厂商所绑架的。所以云计算需要有一个标准,产品需要标准化,方便用户无缝在各种云之间迁移。

    阿里云对Serverless的支持情况

    阿里云在今年四月份南京云栖大会上推出了自己的Serverless产品:函数计算,目前只支持API Gateway和OSS,并且只能在华东2区域使用。还没有形成体系,很难满足用户多样的需求。

    推广Serverless不是一件容易的事情,一是现有产品上云要接入的东西有点多,比如售卖、权限、风控、服务等级等,未来还需要接入Serverless。开发团队很累。第二个是,现有大量的产品要一个个去推动做改造,不是一件容易的事情。

    不过阿里云也在很努力完善对Serverless的支持,未来可期。函数计算携手API网关轻松实践Serverless架构

    云栖社区有一些相关的文章:阿里云 Serverless Computing,讲得非常好,可以了解一下。

    MBaaS/MPaaS为什么不赚钱?

    移动开发领域最早有一些厂商提供移动推送、Crash收集分析、移动数据分析等基础服务,也就是MPaaS。然后逐渐有一些厂商开始提供数据库、存储、配置等相关的服务,在Web控制台上操作,移动端直接使用这些服务,不需要经过服务器端中转,这就是MBaaS。

    目前移动开发领域的服务提供商,比如Facebook的Parse(已关闭)、Firebase(已被Google收购,现在很强大)、国内的LeanCloud都发展得不好。我觉得主要还是因为产品线不够丰富,只能满足一些小App或者App发展初期的需要。MBaaS/MPaaS依托主流云厂商丰富的产品线,通过类似Lambda机制将这些产品串联起来,应该会有不错的发展。

    参考资料

    十年生聚,十年教训——我眼中的云计算Liming的动态夏日清风 - 基于Docker Swarm的极简Serverless实践InfoQ虚拟研讨会:无服务器计算的实践方法诱人却非万能,理性看待Serverless的落地对AWS Cognito的一些理解 相关资源:七夕情人节表白HTML源码(两款)

    最新回复(0)