来源|Serverless
责编|晋兆雨
头图|付费下载于视觉中国
“Serverless能取代微服务吗?”这是知乎上Serverless分类的高热话题。
有人说微服务与Serverless是相背离的,虽然我们可以基于Serverless后端来构建微服务,但在微服务和Serverless之间并不存在直接的路径。
也有人说,因为Serverless内含的Function可以视为更小的、原子化的服务,天然地契合微服务的一些理念,所以Serverless与微服务是天作之合。
马上就要2021年了,Serverless是否终将取代微服务?从微服务到Serverless需要经过怎样的路径?在我们深入探讨细节之前,先别急着“站队”,不妨先基于你团队的实际情况,真实的去思考是否适合使用微服务,千万不要因为"这是趋势"而去做选择。
微服务在Serverless中的优势
1.可选择的可扩展性和并发性
Serverless让管理并发性和可扩展性变得容易。在微服务架构中,我们最大限度地利用了这一点。每一个微服务都可以根据自己的需求对并发性/可扩展性进行设置。从不同的角度来看这非常有价值:比如减轻DDoS攻击可能性,降低云账单失控的财务风险,更好地分配资源......等等。
2.细粒度的资源分配
因为可扩展性和并发性可以自主选择,用户可以细粒度控制资源分配的优先级。在Lambda functions中,每个微服务都可以根据其需求,拥有不同级别的内存分配。比如,面向客户的服务可以拥有更高的内存分配,因为这将有助于加快执行时间;而对于延迟不敏感的内部服务,就可以用优化的内存设置来进行部署。
这一特性同样适用于存储机制。比如DynamoDB或Aurora Serverless数据库就可以根据所服务的特定(微)服务的需求,拥有不同级别的容量分配。
3.松耦合
这是微服务的一般属性,并不是Serverless的独有属性,这个特性让系统中不同功能的组件更容易解耦。
4.支持多运行环境
Serverless功能的配置、部署和执行的简易性,为基于多个运行时的系统提供了可能性。
虽然Node.js(JavaScript运行时)是后端Web应用最流行的技术之一,但它不可能成为每一项任务的最佳工具。对于数据密集型任务、预测分析和任何类型的机器学习,你可能选择Python作为编程语言;像SageMaker这样的专用平台更适合大项目。
有了Serverless基础架构,你无需在操作方面花费额外的精力就可以直接为常规后端API选择Node.js,为数据密集型工作选择Python。显然,这可能会给你的团队带来代码维护和团队管理的额外工作。
5.开发团队的独立性
不同的开发者或团队可以在各自的微服务上工作、修复bug、扩展功能等,做到互不干扰。比如AWS SAM、Serverless框架等工具让开发者在操作层面更加独立。而AWS CDK构架的出现,可以在不损害高质量和运维标准的前提下,让开发团队拥有更高的独立性。
微服务在Serverless中的劣势
1.难以监控和调试
在Serverless带来的众多挑战中,监控和调试可能是最有难度的。因为计算和存储系统分散在许多不同的功能和数据库中,更不用说队列、缓存等其他服务了,这些问题都是由微服务本身引起的。不过,目前已经有专业的平台可以解决所有这些问题。那么,专业的开发团队是否要引入这些专业平台也应该基于成本进行考量。
2.可能经历更多冷启动
当FaaS平台(如Lambda)需要启动一个新的虚拟机来运行函数代码时,就会发生冷启动。如果你的函数Workload对延迟敏感,就很可能会遇到问题。因为冷启动会在总启动时间中增加几百毫秒到几秒的时间,当一个请求完成后,FaaS平台通常会让microVM空闲一段时间,等待下一个请求,然后在10-60分钟后关闭(是的,变化很大)。结果是:你的功能执行的越频繁,microVM就越有可能为传入的请求而启动并运行(避免冷启动)。
当我们将应用分散在数百个或数千个微服务中时,我们可能在每个服务中分散调用时间,导致每个函数的调用频率降低。注意“可能会分散调用”。根据业务逻辑和你的系统行为方式,这种负面影响可能很小,或者可以忽略不计。
3.其他缺点
微服务概念本身还存在其他固有的缺点。这些并不是与Serverless有内在联系的。尽管如此,每一个采用这种类型架构的团队都应该谨慎,以降低其潜在的风险和成本。
确定服务边界并非易事,可能会招致架构问题。
更广泛的攻击面
服务编排费用问题
同步计算和存储(在需要的时候)是不容易做到高性能和可扩展
微服务在Serverless中的挑战和实践
1.Serverless中微服务应该多大?
人们在理解Serverless时,"Function as a Services(FaaS)"的概念很容易与编程语言中的函数语句相混淆。目前,我们正在处在一个没有办法划出完美界限的时期,但经验表明,使用非常小的Serverless函数并不是一个好主意。
当你决定将一个(微)服务分拆成独立的功能时,你就将不得不面对Serverless难题。因此,在此提醒,只要有可能,将相关的逻辑保持在一个函数中会好很多。
当然,决策过程也应该考虑拥有一个独立的微服务的优势
你可以这样设想:“如果我把这个微服务分拆出来......”
它能让不同的团队独立工作吗?
能否从细粒度的资源分配或选择性的扩展能力中获益?
如果不能,你应该考虑将这个服务与另一个需要类似资源、上下文关联并执行相关Workload的服务捆绑在一起。
2.松耦合的架构
通过组成Serverless函数来协调微服务的方法有很多。
当需要同步通信时,可以直接调用(即AWS Lambda RequestResponse调用方法),但这会导致高度耦合的架构。更好的选择是使用Lambda Layers或HTTP API,这样可以让以后的修改或迁移服务对客户端不构成影响。
对于接受异步通信模型,我们有几种选择,如队列(SQS)、主题通知(SNS)、Event Bridge或者DynamoDB Streams。
3.跨组件隔离
理想情况下,微服务不应向使用者暴露细节。像Lambda这样的Serverless平台会提供一个API来隔离函数。但这本身就是一种实现细节的泄露,理想情况下,我们会在函数之上添加一个不可知的HTTP API层,使其真正隔离。
4.使用并发限制和节流策略的重要性
为了减轻DDoS攻击,在使用AWS API Gateway等服务时,一定要为每个面向公众的终端设置单独的并发限制和节流策略。这类服务一般在云平台中会为整个区域设置全局并发配额。如果你没有基于端点的限制,攻击者只需要将一个单一的端点作为攻击目标,就可以耗尽你的配额,并让你在该区域的整个系统瘫痪。