您可以捐助,支持我们的公益事业。

金额: 1元 10元 50元

姓名:

邮件:

电话:

公司:

说明:

认证码: 验证码,看不清楚?请点击刷新验证码 必填



  要资料 文章 文库 视频 Code iProcess 课程 认证 咨询 工具 讲座吧   专家招募  
会员   
 
 
 
  
每天15篇文章
不仅获得谋生技能
更可以追随信仰
 
 
     
   
 订阅
  捐助
谈谈AWS Lambda和serverless architecture
 
来源:网络 发布于 2016-11-9
来自于要资料   160 次浏览     评价:      
 

谈谈AWS Lambda和serverless architecture 由于基于lambda的诸多应用场景还处在刚刚起步的阶段,所以很多orchestration的事情还需要自己做,相信等lambda的使用日趋成熟时,就像docker生态圈一样,会产生众多的orchestration的工具,解决或者缓解系统失控的问题。

最近半年来,随着AWS的各线服务都开始支持lambda,serverless architecture便渐渐成为一个火热的话题。lambda是amzon推出的一个受控的运行环境,起初仅仅支持nodejs(之后添加了java/python的支持)。你可以写一段nodejs的代码,为其创建一个lambda资源,这样,当指定的事件来临的时候,aws的运行时会创建你的运行环境,执行你的代码,执行完毕(或者timeout)后,回收一切资源。这看起来并不稀罕,整个运行环境还受到很多限制,比如目前aws为lambda提供了哪些事件支持,你就能用哪些事件,同时你的代码无法超过timeout指定的时间执行(目前最大是5min),内存使用最多也就是1.5G。那么问题来了,这样一个看起来似乎有那么点鸡肋的服务,为什么还受到如此热捧?原因就在于无比低廉的价格(每百万次请求0.2美元 + 每百万GB秒运行时间16.67美元),毋须操心infrastructure,以及近乎无限扩容的能力。

使用lambda处理事件触发

在服务器端,我们所写的大部分代码是事件触发的:

处理用户对某个URI的请求(打开某个页面,点击某个按钮)

用户注册时发邮件验证邮箱地址

用户上传图片时将图片切割成合适的尺寸

当log持续出现若干次500 internal error时将错误日志聚合发给指定的邮箱

半夜12点,分析一天来收集的数据(比如clickstream)并生成报告

当数据库的某个字段修改时做些事后处理

同时,在处理一个事件的过程中,往往会触发新的事件。基本上我们做一个系统,如果能厘清内部的数据流和事件流,以及对应的行为,那么这个系统的架构也就八九不离十了。如果要让我们自己来设计一个分布式的事件处理系统,一般会使用Message Qeueue,比如RabbitMQ或者Kafka作为事件激发和事件处理的中枢。这往往意味着在现有的infrastructure之外至少添置事件处理的broker(MQ)和worker(读取并处理事件的例程)。如果你用aws的服务,SQS(或者SNS+SQS)可以作为broker,然后配置若干台EC2做worker。如果某个事件流的产生速度大大超过这个事件流的处理速度,那么我们还得考虑使用auto scaling group在queue的长度超过一定阈值或者低于一定阈值时scale up / down。这不仅麻烦,也无法满足某些要求一定访问延迟保障的场景,因为,新的EC2的启动直至在auto scaling group里被标记为可用是数十秒级的动作。

lambda就很好地弥补了这个问题。lambda的执行是置于container之中的,所以启动速度可以低至几十到数百毫秒之间,而且它可以被已知的事件或者某段代码触发,所以基本上你可以在不同的上下文中直接调用或者触发lambda函数,当然也可以使用SNS(kenisis)+lambda取代原本用MQ+worker完成的工作。

我们看上述事件的处理:

处理用户对某个URI的请求(打开某个页面,点击某个按钮):使用API gateway + lambda

用户注册时发邮件验证邮箱地址:

可以在用户注册的流程里直接调用lambda函数发送邮件

如果使用dynamodb,可以配置lambda函数使其使用dynamodb stream在用户数据写入数据时调用lambda

用户上传图片时将图片切割成合适的尺寸

可以配置lambda函数被S3的Object Create Event触发,在lambda函数里使用libMagic的衍生库处理图片。

当log持续出现若干次500 internal error时将错误日志聚合发给指定的邮箱

如果用kenisis来收集log,那么可以配置lambda函数使其使用kenisis stream

半夜12点,分析一天来收集的数据(比如clickstream)并生成报告

使用aws最新支持lambda cronjob

当数据库的某个字段修改时做些事后处理

如果使用dynamodb,同上(配置lambda函数使其使用dynamodb)

如果使用RDBMS,可以使用database trigger + lambda cronjob

想进一步深入代码的童鞋,可以看我的这个repo: https://github.com/tyrchen/aws-lambda-thumbnail 。它接收S3的Object Create Event,并对event中所述的图片做resize,代码使用es6完成。为了简便起见,没有使用cloudformation创建/更新lambda function,而是使用了aws CLI(见makefile)。如果想要运行此代码,你需要定义自己的 $(LAMBDA_ROLE),手工创建S3 bucket并将其和lambda函数关联(目前aws cli不支持S3 event)。

使用lambda处理大数据

lambda近乎无限扩容的能力使得我们可以很轻松地进行大容量数据的map/reduce。你可以使用一个lambda函数分派数据给另一个lambda函数,使其执行成千上万个相同的实例。假设在你的S3里存放着过去一年间每小时一份的日志文件,为做security audit,你需要从中找出非正常访问的日志并聚合。如果使用lambda,你可以把访问高峰期(7am-11pm)每两小时的日志,或者访问低谷期每四小时的日志交给一个lambda函数处理,处理结果存入dynamodb。这样会同时运行近千个lambda函数(24 x 365 / 10),在不到一分钟的时间内完成整个工作。同样的事情交给EC2去做的话,单单为这些instance配置网络就让人头疼:instance的数量可能已经超出了子网中剩余IP地址的数量(比如,你的VPC使用了24位掩码)。

同时,这样一个量级的处理所需的花费几乎可以忽略不计。而EC2不足一小时按一小时计费,上千台t2.small运行一小时的花费约等于26美金,相当可观。

使用lambda带来的架构优势

如果说lambda为事件处理和某些大容量数据的快速处理带来了新的思路,并实实在在省下了在基础设施和管理上的真金白银,那么,其在架构上也带来了新的思路和优势。

web系统是天然离散的系统,里面涵盖了众多大大小小,或并联,或串联的子系统。因为基础设施的成本问题,很多时候我们做了逻辑上的分层和解耦,却在物理上将其部署在一起,这为scalability和management都带来了一些隐患。scalability上的隐患好理解,management上的隐患是指这无形把dev和ops分成不同的team:一个个dev team可以和逻辑上的子系统一一对应,但ops却要集中起来处理部署的问题,免得一个逻辑上「解耦」的功能更新,在物理上却影响了整个系统的正常运行。这种混搭的管理架构势必会影响部署的速度和效率,和「一个team负责从功能开发到上线所有的事情」的思路是相悖的。

举个例子:「用户上传图片时将图片切割成合适的尺寸」这一需求可能在不断变化和优化。对于任何失焦的照片我们还希望做一些焦距上的优化,此外,如果上传的是头像,那么我们希望切割的位置是最合适的头像的位置,如果上传的是照片,除了切割外,我们可能还要生成黑白/灰度等等不同主题的图片。这个功能在不改变已有接口的前提下,并不会影响其他团队的工作,但因为和其他功能放在一起部署,所以部署的工作并不能自己说了算。因为部署交由专门的ops团队完成(可能一天部署一次,也可能一周部署一次),这个团队无法很快地把一些有意思的点子拿出来在生产环境试验,拖累了试错和创新。

而lambda解决了基础设施上的问题,每个子系统甚至子功能(小到函数级的粒度)都可以独立部署,这就让功能开发无比轻松。只要界定好事件流的输入输出,任何事件处理的功能本身可以按照自己团队的节奏更新。

部署和管理上的改变反过来会影响架构,促成以micro-service为主体的系统架构。micro-service孰好孰坏目前尚有争论,但micros-ervice不仅拥抱软件设计上的解耦,同时拥抱软件部署上的解耦是不争的事实。一个web系统的成败和其部署方案有着密切的关系,耦合度越低的部署方案,其局部部署更新的能力也就越强,而一个系统越大越复杂,就越不容易整体部署,所以对局部部署的要求也越来越高。这如同一个有机体,其自我更新从来不靠「死亡-重生」,而是通过新陈代谢。

此外,lambda还是一个充分受限的环境,给代码的撰写带来很多约束条件。我之前在谈架构的时候曾经提到,约束条件是好事,设计软件首先要搞明白约束条件。lambda最强的几个约束是:

lambda函数必须设计成无状态的,因为其所有状态(内存,磁盘)都会在其短短的生命周期结束后消失

lambda函数有最大内存限制

lambda函数有最大运行时间限制

这些限制要求你把每个lambda函数设计得尽可能简单,一次只做一件事,但把它做到最好。很符合unix的哲学。反过来,这些限制强迫你接受极简主义之外,为你带来了无限扩容的好处。

JAWS和server-less architecture

两三个月前,我介绍了JAWS,当时它是一个利用aws刚刚推出的API gateway和lambda配合,来提供REST API的工具,如果辅以架设在S3上的静态资源,可以打造一个完全不依赖EC2的网站。这个项目从另一个角度诠释了lambda的巨大威力,所以demo一出炉,就获得了一两千的github star。如今JAWS羽翼臻至丰满,推出了尚处在beta的jaws fraemwork v1版本:https://github.com/jaws-framework/JAWS,并且在re:invent 2015上做了相当精彩的主题演讲(见github)。JAWS framework大量使用API gateway,cloudformation和lambda来提供serverless architecture,值得关注。

一个完整的serverless website可以这么考虑:

用户注册使用:API gateway,lambda,dynamodb,SES(发邮件)

用户登录使用:API gateway,lambda,或者(cognito和IAM,如果要集成第三方登录)

用户UGC各种内容:API gateway,lambda,dynamodb

其他REST API:API gateway + lambda

各种事件处理使用lambda

所有的静态资源放在S3上,使能static website hosting,然后通过javascript访问cognito或者REST API

日志存放在cloudWatch,并在需要的时候触发lambda

clickstream存在在kenisis,并触发lambda

如此这般,一个具备基本功能的serverless website就搭起来了。

如果你对JAWS感兴趣,可以尝试我生成的 https://github.com/tyrchen/jaws-test。

避免失控

lambda带来的部署上的解耦同时是把双刃剑。成千上万个功能各异的lambda函数(再加上各自不同的版本),很容易把系统推向失控的边缘。所以,最好通过以下手段来避免失控:

为lambda函数合理命名:使用一定规格的,定义良好的前缀(可类比ARN)

使用cloudformation处理资源的分配和部署(可以考虑JAWS)

可视化系统的实时数据流/事件流(类似下图)

(图片来自youtube视频截图:A Day in the Life of a Netflix Engineer,图片和本文关系不大,但思想类似)

由于基于lambda的诸多应用场景还处在刚刚起步的阶段,所以很多orchestration的事情还需要自己做,相信等lambda的使用日趋成熟时,就像docker生态圈一样,会产生众多的orchestration的工具,解决或者缓解系统失控的问题。

   
 订阅
  捐助
相关文章 相关文档 相关视频



我们该如何设计数据库
数据库设计经验谈
数据库设计过程
数据库编程总结
数据库性能调优技巧
数据库性能调整
数据库性能优化讲座
数据库系统性能调优系列
高性能数据库设计与优化
高级数据库架构师
数据仓库和数据挖掘技术
Hadoop原理、部署与性能调优
 

MySQL索引背后的数据结构
MySQL性能调优与架构设计
SQL Server数据库备份与恢复
让数据库飞起来 10大DB2优化
oracle的临时表空间写满磁盘
数据库的跨平台设计
更多...   

并发、大容量、高性能数据库
高级数据库架构设计师
Hadoop原理与实践
Oracle 数据仓库
数据仓库和数据挖掘
Oracle数据库开发与管理

中国电信 数据挖掘原理与工具
某博彩行业 数据库自动化测试
大容量、高性能数据库设计
新华文轩 数据分析与数据挖掘
上海 普华永道 Hadoop与高级实践
深圳 数据挖掘与分析(互联网行业)
海航股份 高性能数据库设计
更多...   
 
 
 
 
 
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号