learn.lianglianglee.com/专栏/Serverless 技术公开课(完)/07 函数粘合云服务提供端到端解决方案.md.html
2022-05-11 18:57:05 +08:00

737 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>07 函数粘合云服务提供端到端解决方案.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 架构的演进.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/02 Serverless 的价值.md.html">02 Serverless 的价值.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/03 常见 Serverless 架构模式.md.html">03 常见 Serverless 架构模式.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/04 Serverless 技术选型.md.html">04 Serverless 技术选型.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/05 函数计算简介.md.html">05 函数计算简介.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/06 函数计算是如何工作的?.md.html">06 函数计算是如何工作的?.md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/Serverless 技术公开课(完)/07 函数粘合云服务提供端到端解决方案.md.html">07 函数粘合云服务提供端到端解决方案.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/08 函数计算的开发与配置.md.html">08 函数计算的开发与配置.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/09 函数的调试与部署.md.html">09 函数的调试与部署.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/10 自动化 CI&amp;CD 与灰度发布.md.html">10 自动化 CI&amp;CD 与灰度发布.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/11 函数计算的可观测性.md.html">11 函数计算的可观测性.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/12 典型案例 1函数计算在音视频场景实践.md.html">12 典型案例 1函数计算在音视频场景实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/13 典型案例 3十分钟搭建弹性可扩展的 Web API.md.html">13 典型案例 3十分钟搭建弹性可扩展的 Web API.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/14 Serverless Kubernetes 容器服务介绍.md.html">14 Serverless Kubernetes 容器服务介绍.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/15 Serverless Kubernetes 应用部署及扩缩容.md.html">15 Serverless Kubernetes 应用部署及扩缩容.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/16 使用 Spot 低成本运行 Job 任务.md.html">16 使用 Spot 低成本运行 Job 任务.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/17 低成本运行 Spark 数据计算.md.html">17 低成本运行 Spark 数据计算.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/18 GPU 机器学习开箱即用.md.html">18 GPU 机器学习开箱即用.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/19 基于 Knative 低成本部署在线应用,灵活自动伸缩.md.html">19 基于 Knative 低成本部署在线应用,灵活自动伸缩.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/20 快速构建 JenkinsGitlab 持续集成环境.md.html">20 快速构建 JenkinsGitlab 持续集成环境.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/21 在线应用的 Serverless 实践.md.html">21 在线应用的 Serverless 实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/22 通过 IDEMaven 部署 Serverless 应用实践.md.html">22 通过 IDEMaven 部署 Serverless 应用实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/23 企业级 CICD 工具部署 Serverless 应用的落地实践.md.html">23 企业级 CICD 工具部署 Serverless 应用的落地实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/24 Serverless 应用如何管理日志&amp;持久化数据.md.html">24 Serverless 应用如何管理日志&amp;持久化数据.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践.md.html">25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构.md.html">26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/27 SAE 应用分批发布与无损下线的最佳实践.md.html">27 SAE 应用分批发布与无损下线的最佳实践.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/28 如何通过压测工具+ SAE 弹性能力轻松应对大促.md.html">28 如何通过压测工具+ SAE 弹性能力轻松应对大促.md.html</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/29 SAE 极致应用部署效率.md.html">29 SAE 极致应用部署效率.md.html</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>07 函数粘合云服务提供端到端解决方案</h1>
<p>**导读:**阿里云Serverless 产品函数计算可以作为粘合剂, 串联其他云服务提供端到端解决方案, 从而简化编程模型, 快速实现最上层的业务目标。</p>
<h3>传统单体应用的拆解</h3>
<p><img src="assets/2020-08-10-092427.png" alt="img" /></p>
<p>首先我们来看下单体应用里面常见的两个编程模型,如上图所示,一种是 UI-driven另外一种是 Message-driven。单体应用这种体系结构客户端可能相对不那么智能系统中的许多逻辑比如身份验证、页面导航、搜索、交易等由服务器应用程序实现随着业务逻辑复杂度的增长服务端的应用程序会越发膨胀和难以维护。</p>
<p>而在 Message-driven 异步消息处理这种模式中,需要用户实现一个常驻的、弹性高可用的消费者服务。为了更专注具体业务逻辑的开发,对一个庞大的单体应用进行拆解,充分利用云服务体系结构是一个非常好的解决方案。在这里,最大的关键是如何为应用程序的各个组件选择和使用正确的云服务,而通过函数作为粘合剂来串联云上的托管服务,就是一个非常好的实践。</p>
<p><img src="assets/2020-08-10-093807.png" alt="img" /></p>
<p>如上图所示UI-driven 切换到 Serverless 架构以后:</p>
<ul>
<li>第三方 BaaS 服务取代认证逻辑;</li>
<li>允许客户端通过临时 token 直接访问架构与第三方上的数据子库BaaS</li>
<li>宠物商店服务端的逻辑可以转移到客户端中,例如跟踪用户访问,读取数据库转化为可视视图等,客户端则慢慢转化为单页面应用;</li>
<li>CPU 密集型或者需要访问大量数据,比如搜索,使用 FaaS 实现,无需一直运行的 server</li>
<li>购买功能使用另外一个 FaaS 实现,因为安全原因放在服务端。</li>
</ul>
<p>Message-driven 切换到 Serverless 架构以后:</p>
<p>与单体应用示例相比,这里改动很小,同时使用 FaaS 功能替换了长期存在的消息消费者应用程序,消息消费的高可用性交给了云平台去负责。</p>
<h3>事件驱动与编排助力完整 Serverless 应用</h3>
<p><img src="assets/2020-08-10-093825.png" alt="img" /></p>
<p>目前,在很多的人的第一印象中,一般将 FaaS也就是 Fucntion as a Service函数即服务等同于 Serverless 比如阿里云的函数计算、AWS 的 Lambda但是实际上有许多其他的云服务也是 Serverless他们和 FC 一起构建成完整的 Serverless 应用,让用户完全聚焦他最上层和核心的原始业务。比如,用户直接使用 API 网关, 就可以从 API 限流、鉴权等许多 API 层面上需要考虑的繁杂工作中解放出来;直接使用 Serverless 的 NoSQL 数据库 TableStore 或者对象存储 OSS 来持久化数据,替代自己管理数据库实例;使用 SLS 或者 Datahub 从外部系统收集数据流;使用消息服务 MNS/MQ 来管理消息等。</p>
<p>用户可以使用一个个函数将这些 Serverless 服务串联起来,从而达到构建具体复杂的业务逻辑和应用的目标。在这里,用户也可以选择 Serverless 工作流来编排函数和其他云服务,简化了开发和运行业务流程(比如自己去编写代码进行任务协调、状态管理、错误处理以及重试等繁琐工作),让用户聚焦业务逻辑开发。当然,用户也可以使用阿里云提供的开发工具链来简化自动化部署和持续集成。使用这些开箱即可使用的工具可以帮助用户快速达到想要的目标和效果。</p>
<p>如果是一个庞大复杂的单体应用或者是一个面向服务体系的架构,开发者需要负责所有的事情,包括代码的编写、管理和部署数据库以及其他相关的后端服务等,切换到 Servrless 架构, 可以看到:特定的的模块交由特定的托管云服务去处理, 之后再使用实现了具体业务代码的函数将它们串联起来, 也实现了解耦。 为了使这种架构运转的更有效率, 事件驱动是一个必不可少的特性, 比如用户尝试往 OSS 上传一个文件或者更新表格存储会自动做一些逻辑处理,对于开发者来说, 最关心的是什么样的事件可以触发我的编写逻辑。</p>
<h3>Serverless 粘合云服务示例</h3>
<p>这里有一个有趣的例子:</p>
<p><img src="assets/2020-08-10-093837.png" alt="img" /></p>
<p>如上图所示,用户上传图片文件,产生消息事件触发了 FC 函数执行,处理生成了图片缩略图,并将缩略图存储至对象存储 OSS之后触发了另一个 FC 函数将图片产生的更新信息写入表格存储数据库,最后再触发一个 FC 函数完成搜索模块的更新。整个过程中文件处理存储、搜索服务、表格存储数据库服务被几个 FC 函数粘合为一个业务处理逻辑。</p>
<p>参考文章:<a href="https://martinfowler.com/articles/serverless.html">https://martinfowler.com/articles/serverless.html</a></p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/Serverless 技术公开课(完)/06 函数计算是如何工作的?.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/Serverless 技术公开课(完)/08 函数计算的开发与配置.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":"709974665b023d60","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>