云计算机经过这么多年的发展,逐渐进化到用户仅需关注业务和所需的资源。通过Swarm、K8S这些编排工具,容器服务让开发者的体验达到很完美的境界。我曾经觉得Docker可以替代虚机,用户只要关注自己的计算和需要的资源就行,不需要操心到机器这一层。但是因为Docker对资源的隔离不够好,各大云厂商的做法还是一个Docker对应一台虚机,不仅成本高,给用户暴露虚机也多余了。
用户为什么需要关注业务运行所需要的CPU、内存、网络情况?还有没有更好的解决方案?Serverless架构应运而生,让人们不再操心运行所需的资源,只需关注自己的业务逻辑,并且为实际消耗的资源付费。可以说,随着Serverless架构的兴起,真正的云计算时代才算到来了。
容器在开发模式方面并没有提出新的想法,大家还是在用传统的那一套开发模式,需要写一个大而全的后端服务。与之对比,Serverless架构是事件驱动的,这样让后端的开发体验变得跟前端和移动端很类似了。针对不同客户的需求,先让其购买好相关的资源,然后一个个填坑,给不同的产品添加各种事件处理逻辑就行。这就跟iOS开发一样,界面写出来,然后处理一个个事件就好了,大家都很容易理解这种开发模式。
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成功的前提条件。Lambda不适合处理复杂的业务逻辑,比较适合作为胶水代码,粘合关键的产品。另外就是Lambda不管怎么完善,可能只能解决80%的问题,剩下20%的逻辑需要用户自己写服务,通过docker发布,然后给Lambda或者用户使用。这种混合的编码方式可能是未来的主流开发模式。
还是成本。IT行业一些领先的公司基础设施非常完善,开发工程师写好代码,然后通过发布平台发布,感觉也是挺方便的。比起Serverless的架构,成本还是要高不少。
机器成本。日常、预发、线上,1+1+2=4台服务器少不了。时刻要关注业务数据,盘点资源,看看是否需要扩容和缩减资源。扩容容易,缩减难,造成大量资源闲置。全链路压测是不是很烦?阿里云在今年四月份南京云栖大会上推出了自己的Serverless产品:函数计算,目前只支持API Gateway和OSS,并且只能在华东2区域使用。还没有形成体系,很难满足用户多样的需求。
推广Serverless不是一件容易的事情,一是现有产品上云要接入的东西有点多,比如售卖、权限、风控、服务等级等,未来还需要接入Serverless。开发团队很累。第二个是,现有大量的产品要一个个去推动做改造,不是一件容易的事情。
不过阿里云也在很努力完善对Serverless的支持,未来可期。函数计算携手API网关轻松实践Serverless架构
云栖社区有一些相关的文章:阿里云 Serverless Computing,讲得非常好,可以了解一下。
移动开发领域最早有一些厂商提供移动推送、Crash收集分析、移动数据分析等基础服务,也就是MPaaS。然后逐渐有一些厂商开始提供数据库、存储、配置等相关的服务,在Web控制台上操作,移动端直接使用这些服务,不需要经过服务器端中转,这就是MBaaS。
目前移动开发领域的服务提供商,比如Facebook的Parse(已关闭)、Firebase(已被Google收购,现在很强大)、国内的LeanCloud都发展得不好。我觉得主要还是因为产品线不够丰富,只能满足一些小App或者App发展初期的需要。MBaaS/MPaaS依托主流云厂商丰富的产品线,通过类似Lambda机制将这些产品串联起来,应该会有不错的发展。