mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-25 20:56:42 +08:00
347 lines
28 KiB
HTML
347 lines
28 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>03 常见 Serverless 架构模式.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/01 架构的演进.md.html">01 架构的演进</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/02 Serverless 的价值.md.html">02 Serverless 的价值</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/Serverless 技术公开课(完)/03 常见 Serverless 架构模式.md.html">03 常见 Serverless 架构模式</a>
|
||
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/04 Serverless 技术选型.md.html">04 Serverless 技术选型</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/05 函数计算简介.md.html">05 函数计算简介</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/06 函数计算是如何工作的?.md.html">06 函数计算是如何工作的?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/07 函数粘合云服务提供端到端解决方案.md.html">07 函数粘合云服务提供端到端解决方案</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/08 函数计算的开发与配置.md.html">08 函数计算的开发与配置</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/09 函数的调试与部署.md.html">09 函数的调试与部署</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/10 自动化 CI&CD 与灰度发布.md.html">10 自动化 CI&CD 与灰度发布</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/11 函数计算的可观测性.md.html">11 函数计算的可观测性</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/12 典型案例 1:函数计算在音视频场景实践.md.html">12 典型案例 1:函数计算在音视频场景实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/13 典型案例 3:十分钟搭建弹性可扩展的 Web API.md.html">13 典型案例 3:十分钟搭建弹性可扩展的 Web API</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/14 Serverless Kubernetes 容器服务介绍.md.html">14 Serverless Kubernetes 容器服务介绍</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/15 Serverless Kubernetes 应用部署及扩缩容.md.html">15 Serverless Kubernetes 应用部署及扩缩容</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/16 使用 Spot 低成本运行 Job 任务.md.html">16 使用 Spot 低成本运行 Job 任务</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/17 低成本运行 Spark 数据计算.md.html">17 低成本运行 Spark 数据计算</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/18 GPU 机器学习开箱即用.md.html">18 GPU 机器学习开箱即用</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/19 基于 Knative 低成本部署在线应用,灵活自动伸缩.md.html">19 基于 Knative 低成本部署在线应用,灵活自动伸缩</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/20 快速构建 JenkinsGitlab 持续集成环境.md.html">20 快速构建 JenkinsGitlab 持续集成环境</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/21 在线应用的 Serverless 实践.md.html">21 在线应用的 Serverless 实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/22 通过 IDEMaven 部署 Serverless 应用实践.md.html">22 通过 IDEMaven 部署 Serverless 应用实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/23 企业级 CICD 工具部署 Serverless 应用的落地实践.md.html">23 企业级 CICD 工具部署 Serverless 应用的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/24 Serverless 应用如何管理日志&持久化数据.md.html">24 Serverless 应用如何管理日志&持久化数据</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践.md.html">25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构.md.html">26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/27 SAE 应用分批发布与无损下线的最佳实践.md.html">27 SAE 应用分批发布与无损下线的最佳实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/28 如何通过压测工具+ SAE 弹性能力轻松应对大促.md.html">28 如何通过压测工具+ SAE 弹性能力轻松应对大促</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Serverless 技术公开课(完)/29 SAE 极致应用部署效率.md.html">29 SAE 极致应用部署效率</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>03 常见 Serverless 架构模式</h1>
|
||
<h3>究竟什么是 Serverless 架构?</h3>
|
||
<p>什么是 Serverless 架构?按照 CNCF 对 Serverless 计算的定义,Serverless 架构应该是采用 FaaS(函数即服务)和 BaaS(后端服务)服务来解决问题的一种设计。这个定义让我们对 Serverless 的理解稍显清晰,同时可能也造成了一些困扰和争论。</p>
|
||
<ul>
|
||
<li>随着需求和技术的发展,业界出现了一些 FaaS 以外的其它形态的 Serverless 计算服务,比如 Google Cloud Run,阿里云推出的面向应用的 Serverless 应用引擎服务以及 Serverless K8s,这些服务也提供了弹性伸缩能力和按使用计费的收费模式,具备 Serverless 服务的形态,可以说进一步扩大了 Serverless 计算的阵营;</li>
|
||
<li>为了消除冷启动影响,FaaS 类服务如阿里云的函数计算和 AWS 的 Lambda 相继推出了预留功能,变得不那么“按使用付费”了;</li>
|
||
<li>一些基于服务器(Serverful)的后端服务也推出了 Serverless 形态产品,比如 AWS Serverless Aurora,阿里云 Serverless HBase 服务。</li>
|
||
</ul>
|
||
<p>这样看来,Serverless 的界线是有些模糊的,诸多云服务都向着 Serverless 方向演进。一个模糊的东西如何指导我们解决业务问题呢?Serverless 有一个根本的理念是一直没有改变的,即让用户最大化地专注业务逻辑,其它的特征如不关心服务器、自动弹性、按使用计费等,都是为了实现这个理念而服务。</p>
|
||
<p>著名的 Serverless 实践者 Ben Kehoe 这样描述 Serverless 原生心智,当我们在业务中考虑做什么时可以体会一下这种心智:</p>
|
||
<ul>
|
||
<li>我的业务是什么?</li>
|
||
<li>做这件事情能不能让我的业务出类拔萃?</li>
|
||
<li>如果不能,我为什么要做这件事情而不是让别人来解决这个问题?</li>
|
||
<li>在解决业务问题之前没有必要解决技术问题。</li>
|
||
</ul>
|
||
<p>在实践 Serverless 架构时,最重要的心智不是选择哪些流行服务和技术,攻克哪些技术难题,而是时刻将专注业务逻辑铭记在心,这样更容易让我们选择合适的技术和服务,明确如何设计应用架构。人的精力是有限的,组织的资源是有限的,Serverless 的理念可以让我们更好地用有限的资源解决真正需要解决的问题,正是因为我们少做了一些事情,转而让别人做这些事情,我们才可以在业务上做的更多。</p>
|
||
<p>接下来我们介绍一些常见的场景,并探讨如何使用 Serverless 架构支持这些场景。我们主要会采用计算、存储和消息通信等技术来设计架构,从可运维性、安全性、可靠性、可扩展性、成本几个角度来衡量架构的优劣。为了让这种讨论不过于抽象,我们会用一些具体的服务作为参考,但是这些架构的思想是通用的,可以用其它类似产品实现。</p>
|
||
<h3>场景 1: 静态 Web 站点</h3>
|
||
<p><img src="assets/2020-07-27-1.JPG" alt="img" /></p>
|
||
<p>假如我们要做一个信息展示的网站,需求很简单,就像早年的中国黄页那样,信息更新很少,大概有以下几种主要选择:</p>
|
||
<ul>
|
||
<li>买台服务器放在 IDC 机房里托管,运行站点;</li>
|
||
<li>去云厂商上买台云服务器运行站点,为了解决高可用的问题又买了负载均衡服务和多个服务器;</li>
|
||
<li>采用静态站点方式,直接由对象存储服务(如 OSS)支持,并使用 CDN 回源 OSS。</li>
|
||
</ul>
|
||
<p><img src="assets/2020-07-27-022836.jpg" alt="2.JPG" /></p>
|
||
<p>这三种方式由云下到云上,由管理服务器到无需管理服务器,即 Serverless。这一系列的转变给使用者带来了什么变化呢?前两种方案需要预算,需要扩展,需要实现高可用,需要自行监控等,这些都不是马老师当年想要的,他只想去展示信息,让世界了解中国,这是他的业务逻辑。Serverless 正是这样一种理念,最大化地让人去专注业务逻辑。第三种方式就是采用了 Serverless 架构去构建一个静态站点,它有其它方案无法比拟的优势,比如:</p>
|
||
<ul>
|
||
<li>可运维性:无需管理服务器,比如操作系统的安全补丁升级、故障升级、高可用性,这些云服务(OSS,CDN)都帮着做了;</li>
|
||
<li>可扩展性:无需对资源做预估和考虑未来的扩展,因为 OSS 本身是弹性的,使用 CDN 使得系统延迟更小、费用更低、可用性更高;</li>
|
||
<li>成本:按实际使用的资源付费,包括存储费用和请求费用,没有请求时不收取请求费用;</li>
|
||
<li>安全性:这样一个系统甚至看不到服务器,不需要通过 SSH 登录,DDoS 攻击也交给云服务来解决。</li>
|
||
</ul>
|
||
<h3>场景 2: 单体和微服务应用</h3>
|
||
<p><img src="assets/2020-07-27-3.JPG" alt="img" /></p>
|
||
<p>静态页面和站点适合用于内容少、更新频率低的场景,反之,就需要动态站点了。比如淘宝的商品页面,采用静态页面方式管理商品信息是不现实的。如何根据用户请求动态地返回结果呢?我们来看两种常见的解决方案:</p>
|
||
<ul>
|
||
<li>Web 单体应用:所有的应用逻辑都在一个应用中完成,结合数据库,这种分层架构可以快速实现一些复杂度较低的应用;</li>
|
||
<li>微服务应用:随着业务发展,功能多了,访问量高了,团队大了,这时候一般就需要将单体应用中的逻辑拆分成多个执行单元,比如商品页面上的评论信息、售卖信息、配送信息等,都可以对应一个单独的微服务。这种架构的好处是每个单元是高度自治的,易于开发(比如使用不同技术)、部署和扩展。但是这种架构也引入了分布式系统的一些问题,如服务间通信的负载均衡、失败处理等。</li>
|
||
</ul>
|
||
<p>处在不同阶段不同规模的组织可以选择适合自身的方式,来解决它面临的首要业务问题,淘宝最初被人们接受一定不是因为它使用了哪种技术架构。但是无论选择哪种架构,上面提到的 Serverless 原生心智都有助于我们专注业务。比如:</p>
|
||
<ul>
|
||
<li>是否需要自己购置服务器安装数据库,实现高可用、管理备份、升级版本等,还是可以把这些事情交给托管的服务如 RDS;是否可以使用表格存储、Serverless HBase 等 Serverless 数据库服务,实现按使用的弹性扩容缩容和付费;</li>
|
||
<li>单体应用是需要自己购置服务器运行,还是可以交给托管服务,如函数计算和 Serverless 应用引擎;</li>
|
||
<li>是否可以通过函数来实现轻量级微服务,依赖函数计算提供的负载均衡、自动伸缩、按需付费、日志采集、系统监控等能力;</li>
|
||
<li>基于 Spring Cloud、Dubbo、HSF 等实现的微服务应用是否需要自己购置服务器部署应用,管理服务发现,负载均衡,弹性伸缩,熔断,系统监控等,还是可以将这些工作交给诸如 Serverless 应用引擎服务。</li>
|
||
</ul>
|
||
<p><img src="assets/2020-07-27-022839.jpg" alt="4.JPG" /></p>
|
||
<p>上图右侧的架构引入了 API 网关、函数计算或者 Serverless 应用引擎来实现计算层,将大量的工作交给了云服务完成,让用户最大程度上专注实现业务逻辑。其中系统内部多个微服务的交互如下图所示,通过提供一个商品聚合服务,将内部的多个微服务统一呈现给外部。这里的微服务可以通过 SAE 或者函数实现。</p>
|
||
<p><img src="assets/2020-07-27-5.JPG" alt="img" /></p>
|
||
<p>这样的架构还可以继续扩展,比如如何支持不同客户端的访问,如上图右侧所示。现实中这种需求是常见的,不同的客户端需要的信息可能是不同的,手机可以根据位置信息做相关推荐。如何让手机客户端和不同浏览器都能受益于 Serverless 架构呢?这又牵扯出了另一个词——Backend for fronted(BFF),即为前端定做的后端,这受到了前端开发工程师的推崇,Serverless 技术让这个架构广泛流行,因为前端工程师可以从业务角度出发直接编写 BFF,而无需管理服务器相关的令前端工程师更加头疼的事情。更多实践可以参见:<a href="https://yq.aliyun.com/articles/752780">基于函数计算的 BFF 架构</a>。</p>
|
||
<h3>场景 3: 事件触发</h3>
|
||
<p>前面提到的动态页面生成是同步请求完成的,还有一类常见场景,其中请求处理通常需要较长时间或者较多资源,比如用户评论中的图片和视频内容管理,涉及到如何上传图片和处理图片(缩略图、水印、审核等)及视频,以适应不同客户端的播放需求。</p>
|
||
<p><img src="assets/2020-07-27-6.JPG" alt="img" /></p>
|
||
<p>如何对上传多媒体文件实时处理呢?这个场景的技术架构大体经历了以下演变:</p>
|
||
<p><img src="assets/2020-07-27-022842.jpg" alt="7.JPG" /></p>
|
||
<ul>
|
||
<li>基于服务器的单体架构:多媒体文件被上传到服务器,由服务器处理,对多媒体的显示请求也由服务器完成;</li>
|
||
<li>基于服务器的微服务架构:多媒体文件被上传到服务器,服务器处理转存到 OSS,然后将文件地址加入消息队列,由另一组服务器处理文件,将处理结果保存到 OSS,对多媒体的显示请求由 OSS 和 CDN 完成;</li>
|
||
<li>Serverless 架构:多媒体直接上传到 OSS,由 OSS 的事件触发能力直接触发函数,函数处理结果保存到 OSS,对多媒体的显示请求由 OSS 和 CDN 完成。</li>
|
||
</ul>
|
||
<p>基于服务器的单体架构面临以下问题:</p>
|
||
<ul>
|
||
<li>如何处理海量文件?单台服务器空间有限,购买更多的服务器;</li>
|
||
<li>如何扩展 Web 应用服务器?Web 应用服务器是否适合 CPU 密集型任务?</li>
|
||
<li>如何解决上传请求的高可用?</li>
|
||
<li>如果解决显示请求的高可用?</li>
|
||
<li>如何应对请求负载的波峰波谷?</li>
|
||
</ul>
|
||
<p>基于服务器的微服务架构很好地解决了上述的大部分问题,但是仍然面临一些问题:</p>
|
||
<ul>
|
||
<li>管理应用服务器的高可用性和弹性;</li>
|
||
<li>管理文件处理服务器的弹性;</li>
|
||
<li>管理消息队列的弹性。</li>
|
||
</ul>
|
||
<p>而第三种 Serverless 架构很好地解决了上述所有问题。开发人员原来需要做的负载均衡、服务器的高可用和弹性伸缩、消息队列都转移到了服务内部。我们可以看到随着架构的演进,开发人员做的事情越来越少,系统更加成熟,业务上更加聚焦,大大提升了交付速度。</p>
|
||
<p>这里的 Serverless 架构主要体现的价值是:</p>
|
||
<ul>
|
||
<li>事件触发能力:函数计算服务与事件源(OSS)的原生集成让使用者无需管理队列资源,队列自动扩展,实时处理上传的多媒体文件;</li>
|
||
<li>高弹性和按需付费:图片和视频(不同大小的视频)需要的计算资源规格是不同的,流量的波峰波谷对资源的需求是不同的,现在这种弹性由服务提供,按照用户的真实使用去扩容缩容,让用户 100% 地利用资源,无需为闲置资源付费。</li>
|
||
</ul>
|
||
<p>事件触发能力是 FaaS 服务的一个重要特性,这种 Pub-Sub 事件驱动模式不是一个新的概念,但是在 Serverless 流行之前,事件的生产者、消费者以及中间的连接枢纽都是用户负责的,就像前面架构演进中的第二个架构。</p>
|
||
<p>Serverless 让生产者发送事件,维护连接枢纽都从用户职责中省略了,而只需关注消费者的逻辑,这就是 Serverless 的价值所在。</p>
|
||
<p>函数计算服务还集成其它云服务事件源,让你更方便地在业务中使用一些常见的模式,如 Pub/Sub、事件流模式、Event Sourcing 模式。关于更多的函数组合模式可以参见:<a href="https://yq.aliyun.com/articles/722461">函数组合的 N 种方式</a>。</p>
|
||
<p><img src="assets/2020-07-27-8.JPG" alt="8.JPG" /></p>
|
||
<h3>场景 4: 服务编排</h3>
|
||
<p>前面的商品页面虽然复杂,但是所有的操作都是读操作,聚合服务 API 是无状态、同步的。我们来看一下电商中的一个核心场景——订单流程。</p>
|
||
<p><img src="assets/2020-07-27-9.JPG" alt="img" /></p>
|
||
<p>这个场景涉及到多个分布式写的问题,这是引入微服务架构导致的最麻烦的一个问题。单体应用在一定程度上可以比较容易地处理这个流程,因为使用了一个数据库,可以通过数据库事务保持数据一致性。但是现实中可能不得不去跟一些外部服务打交道,需要一定的机制保证流程的前进和回退顺利完成,解决这个问题的一个经典模式是 Saga 模式,而实现这种模式有两种不同架构:</p>
|
||
<p>一种做法是采用事件驱动模式,驱动流程完成。在这个架构里,有一个消息总线,感兴趣的服务如库存服务监听事件,监听者可以使用服务器或者函数。借助于函数计算和消息主题的集成,这个架构也可以完全不使用服务器。</p>
|
||
<p>这个架构模块是松耦合的,职责清晰。不足之处是随着流程变得更长更加复杂,这个系统变得难以维护。比如很难直观地了解业务逻辑,执行时的状态也不宜跟踪,可运维性比较差。</p>
|
||
<p><img src="assets/2020-07-27-10.gif" alt="img" /></p>
|
||
<p>另外一种架构是基于工作流的 Saga 模式。在这个架构里,各个服务之间是独立的,也不通过事件传递信息,而是有一个集中的协调者服务来调度单个业务服务,业务逻辑和状态由集中协调者维护。而实现这个集中的协调者通常面临以下问题:</p>
|
||
<ul>
|
||
<li>编写大量代码来实现编排逻辑、状态维护和错误重试等功能,而这些实现又很难被其它应用重用;</li>
|
||
<li>维护运行编排应用的基础设施,以确保编排应用的高可用性和可伸缩性;</li>
|
||
<li>考虑状态持久性,以支持多步骤长时间运行流程并确保流程的事务性。</li>
|
||
</ul>
|
||
<p>依赖于云服务,比如阿里云的 Serverless 工作流服务,这些事情都可以交给平台来做,用户又回到了只需关注业务逻辑的状态。></p>
|
||
<p>下图右侧是流程定义,我们可以看到这实现了前面基于事件的 Saga 模式的效果,并且流程大大简化,提升了可观测性。</p>
|
||
<p><img src="assets/2020-07-27-11.JPG" alt="img" /></p>
|
||
<h3>场景 5: 数据流水线</h3>
|
||
<p>随着业务的进一步发展,数据变得越来越多,这时候就可以挖掘数据的价值。比如,分析用户对网站的使用行为并做相应的推荐。一个数据流水线包括数据采集、处理、分析等多个环节。这样的服务如果从头搭建虽然是可行的,但是也是复杂的,我们这里讨论的业务是电商,而不是去提供一个数据流水线服务。有了这样一个目标,我们做选择时就会变得简单明确。</p>
|
||
<ul>
|
||
<li>日志服务(SLS)提供了数据采集、分析和投递功能;</li>
|
||
<li>函数计算(FC)可以对日志服务的数据进行实时处理,将结果写入其它服务,如日志服务、OSS;</li>
|
||
<li>Serverless 工作流服务可以定时批量处理数据,通过函数定义灵活的数据处理逻辑,构建 ETL 作业;</li>
|
||
<li>数据湖分析(DLA)提供了 Serverless 化的交互式查询服务,它使用标准 SQL 分析对象存储(OSS)、数据库(PostgreSQL / MySQL 等)、NoSQL(TableStore 等)等多个数据源的数据。</li>
|
||
</ul>
|
||
<h3>总结</h3>
|
||
<p>限于篇幅,我们只讨论了 Serverless 架构在几个场景中的应用,但是在实践中我们可以看出一种共性,即如何将业务逻辑中与业务不相关的工作剥离出去,交给平台和服务完成。这种各司其职、分工协作的做法在其它场合并不陌生,但是 Serverless 的思想让这种形态更为明确。Less is more,少的不只是 Server 和围绕 Server 相关的负担,还可以是业务以外的方方面面,多的是专注的业务和产品的核心竞争力。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/Serverless 技术公开课(完)/02 Serverless 的价值.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/Serverless 技术公开课(完)/04 Serverless 技术选型.md.html">下一页</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"7099745d48133d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
</script>
|
||
</html>
|