基于 NodeJS 的 serverless 架构实践

更新日期: 2019-09-07阅读: 4.5k标签: 架构

通过将 BFF 构建于 serverless 之上,将人工智能实验室(天猫精灵)数十个中后台应用整合到了一个统一入口。用云函数的方式取代了传统基于 NodeJS 的 BFF 层,提供了在一个站点下不同应用以及不同环境的快速切换能力。从而极大程度的降低了开发成本和运维成本,使机器数量从 200 余台缩减为 10 台,同时有效减少了业务方的学习和理解成本。

本文主要讲述了 BFF 局限性以及我们对应的 serverless 解决方案,其中平台核心功能包括:

  • 云函数:

    将 BFF 层的 Node 应用代码拆解成独立云函数,支持动态编写、秒级部署,平台提供隔离的沙箱容器进行执行,并自动接入日志和监控系统,使开发者可实时掌握函数的运行状况;

  • 应用:

    将各平台的前端代码打包部署,入口路由进行统一注册,我们将这些平台称为应用。

    这些应用将直接支持各环境切换及多套预发环境解决方案;

  • SDK:

    框架将集团中间件封装为 BaaS SDK 供应用直接调用,提供一套统一的 api 抹平了 Web 和 Node 的差异;

  • CLI:

    提供命令行工具便于开发者可脱离 web 管理平台,而直接快速进行开发、调试和发布。


BFF 的局限

从传统大型机到服务器集群,从虚拟技术到容器化,我们正在走向那些更加轻量、更俱灵活性的解决方案。

阿里各 BU,在“大中台,小前台”的大背景下,也逐渐从巨石应用拆分为了更为灵活的微服务,以便以更小的粒度服务于更多的需求方。

而前端也在以往前后端分离的基础上,更进一步的演变为了 BFF 架构。根据最终端上的需求,通过 BFF 层将各个微服务进行聚合和裁剪后返回。根据”谁享受谁负责“原则,该 BFF 层通常由前端使用 NodeJS 维护。


然而,作为横向支撑的前端团队,我们在实施 BFF 架构1年后,却发现它可能并没有想象的那么美好。为什么会这么说?截止目前,我们大概有 40 个左右不同的平台服务于我们的各个团队(包括运营、市场、测试、工程、算法、硬件和数据),对于大量的平台的存在,对开发人员的维护和业务方的理解,都成为了一种负担。

  • 首先,每个平台都有一个对应的 Node 层来作为 BFF,我们仍然需要针对每一个平台部署代码、安装依赖的各种软件,关心究竟需要多少台服务器,这极大的增加了我们的运维成本;

  • 其次,由于各个平台十分分散,均由独立域名进行访问,不同团队可能并不清楚已经存在一个类似平台从而导致提出相似需求,并且各个平台对于账户、权限、文件上传等中间件都需进行接入,对开发资源造成严重浪费;

  • 最后,作为业务方,需要记住大量不同平台域名和对应的功能,也成为了一项挑战。

    而每个平台还有对应还有多套环境,其也增加了他们的沟通成本和使用成本。


所以,我们核心面临的问题总结起来就是运维成本难降低、重复开发难避免、入口分散难管理。那么有没有一种更轻量的架构,使我们所有人能从上述这些繁琐的工作中解放出来?

我们想到了 serverless,它让 NoOps 成为可能,实现零配置发布业务代码,这能极大降低运维成本。但传统的 serverless 仍然只能解决一个点的问题,如果我们做的更进一步,将 serverless 与已有的 BFF、FE 整合,那是不是有可能同时解决上述问题?基于上述思考,我们提出了自己的 serverless 架构。

在此之前,先介绍一下什么是 serverless。


serverless


serverless 的定义如下

无服务器架构是基于互联网的系统,其中应用开发不使用常规的服务进程。相反,它们仅依赖于第三方服务,客户端逻辑和服务托管远程过程调用的组合。

目前我们说的 serverless,最常是指 Amazon 在 2014 年发布的 AWS Lambda 服务,为在服务端中运行的程序提供了一种全新的架构。我们不需要在服务器上持续运行进程以等待请求,而是可以通过某种事件机制来触发容器从而动态的执行代码。

不需要再关心应该配置多少机器,需要预装哪些依赖,这些统统由平台搞定,而我们只需要维护一个功能的集合,这些功能以“函数”的方式被调用。这种模式我们通常也把它称为 Faas(Function as a Services),一种比微服务粒度更小的代码组织方式。

关于 serverless 的介绍网上已有很多,具体可以从下面这篇文章开始,这里不再进行赘述。

从IaaS到FaaS—— Serverless架构的前世今生


BFF in serverless

然而独立的 FaaS 其实并不具备实用性,因为他是无状态的,无法进行存储意味着无法针对不同用户提供服务。Amazon 的解决方案是让 Lambda 打通 AWS 大量基础服务,通过简单的 API 调用,即可使用 S3、RDS 等存储服务来保存用户数据。即使这样,仍然有很多工作需要开发者完成。

我们结合的实际情况,在平台中统一了 FE、BFF,并封装了大量集团中间件,使其成为一体化解决方案,让开发者仅需在一个平台,即可完成应用的开发、调试、构建和部署。


下面将详细介绍平台几大核心功能及其背后的思考。

1. 云函数

函数运行可以说是 serverless 架构的基础,为此我们创建了一个独立的 sandbox 模块来提供该功能的基础环境。

其实现方式类似 egg 的 master/worker 模式。不同之处在于请求进来时,会根据 request 查询到具体的代码片段,然后启动 worker 进程来运行,最后将运行的结果 response 到客户端,worker 再进行自销毁。

这么做的好处是我们可以针对任何一个函数进行监控和限制,了解和控制它的运行时长、内存占用,防止恶意代码侵害公共环境,不同函数之间也不会造成相互干扰。


2. 开发者工作台(应用)

维护一个统一的入口,是平台其他功能能正常运转的基石。通过系统发布的所有平台,均通过同一域名进入,在导航处提供了在不同平台之间切换的功能,我们将这些平台称为”应用“。

这里和“阿里内外工作台”的实现方式略有不同,“工作台”是通过统一门户,再导航至不同二级域名,其每二级站点实际为独立机器进行部署。而我们在不同应用之前的切换,只是同一域名下不同路由的切换,实际背后提供服务的都是同一个服务器集群。

这样做的好处是一些业务无关的框架级功能可以在平台上进行统一实现,比如后面提到的环境切换和多套预发环境管理。对于业务来说,需求方再也不需要记住不同平台的各种域名,在任意平台也实现了各平台间的导航。

而开发者工作台,提供了应用管理的所有功能,包括 BaaS 配置、函数发布、监控日志等,以满足开发者的日常需求,并极大的改善开发者开发体验。


3. 在线环境切换

利用统一入口的优势,我们可以在线上、预发、日常之间实现无缝切换。然而由于阿里日常与线上的天然隔离,以及中间件的环境限制,我们并没有办法在线上环境的函数中,调用日常环境的 API 接口。为了实现各环境互通,我们在统一入口处增加了一层线上环境 Proxy。通过这层 Proxy,线上环境仍是正常访问,而当访问的是预发、日常的函数时,将通过 HTTP 的方式,到真正平台对应环境的机器上再执行相应函数。


4. 多套预发环境管理

由于我们特殊情况,在预发部署了多套环境用于项目联调,然而因为我们业务较为复杂,一套完整链路往往涉及100个左右的应用,因为别个项目的修改需要每个应用都进行部署显然是不合理的。

那么有没有一种方式,只部署有修改的应用,而没有修改的应用,当在该环境访问时如果缺失,自动进入默认标准环境中,并且后续链路能维持这个逻辑呢?

我们通过在请求加入标志位的方式,实现了实现这一需求。


5. BaaS SDK

如果 egg 没有通过插件化机制来支持集团的各种中间件,如果 AWS 只是单纯的 serverless 而没有与 S3、RDS 等服务打通,那么其实很难规模化应用。

为了有效降低开发门槛和成本,我们建立了一套 Web 与 Node 端 API 基本一致的 SDK,使开发者在进行开发时,不必显著的区分当前环境是在浏览器中还是在服务端中,从而有效降低学习成本。

下面举个栗子:

//  初始化 app,只需执行一次
import genie from '@ali/cloud-genie';
const app = genie.initApp();

// 1.  云函数调用
const { cf } = app.cf();
const data = await cf.invoke('functionName', params);

// 2. 根据花名查询用户信息
const buc = app.buc();
const userInfo = await buc.getUserByNickNameCn('花名');

通过上述简单的调用,即可实现调用集团包括 DB 在内的各个中间件及服务。

6. CLI

除此之外,我们还提供了一个 CLI 工具,用于开发者快速的进行开发、调试和发布。

由于我们基于 serverless 架构,实际上在本地进行调试已没有太大必要,所以我们针对函数的调试,实际上都是连接到日常或预发机器直接运行的,再将运行的结果同步会开发者的终端,开发者本地并不需要搭建 serverless 的运行环境。


More

虽然平台已可完成基本开发,为了更好的支撑更多的业务,我们后面的计划主要包括租户隔离、多协议支持、可视化编写。

租户隔离:目前平台自带 Portal,故只支持了天猫精灵相关需求在上面进行开发,租户隔离期望实现不同 Portal 在数据上的隔离,以支持更多的业务线。

多协议支持:目前平台只支持 HTTP 协议,后续将支持更多协议,以便于服务更多的业务场景。

可视化编写:目前平台主要以 CLI 的方式编写函数,但其实 BFF 层很多只是简单的聚合和裁剪,如果我们能通过可视化的方式,选择一些 API 进行聚合,再根据需求进行裁剪,那么对于客户端等其他同学将更加友好,进一步降低开发成本。


写在最后

serverless 对业务开发者具有极大的友好性,使开发者不用了解应用服务器如何配置、数据库如何链接、消息服务中间件如何搭建,不需了解到底需要多少台服务器才能支撑,尤其是针对前端开发人员,NoOps 的特性正好弥补了前端运维能力的短板,使其从前端到全栈的转变提供了一个良好的平台。

而 BFF in serverless 在 serverless 架构的基础上,提供了一套完善的 BaaS SDK、监控日志体系以及前端解决方案,从而更进一步降低了开发者门槛。

链接: https://www.fly63.com/article/detial/5747

微内核架构在大型前端系统中的应用

架构和框架是独立的,本文仅仅是提出一种架构思路,而且这个架构也在百度的某款用户量很大的复杂前端产品中得以应用。基于这一套弹性架构并结合Vue/React的现代化开发理念,可以很好的完成高复杂度的前端系统。

怎么判定web前端架构师的能力高低?

软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。传统软件架构描述的对象是直接构成系统的抽象组件,侧重于系统的抽象、拆分、组织方式等

成为一个顶尖架构师

架构师的一个重要职责是,确保团队有共同的技术愿景,以帮助我们向客户交付他们想要的系统。在某些场景下,架构师只需要和一个团队一起工作,这时他们等同于技术引领者。在其他情况下,他们要对整个项目的技术愿景负责,通常需要协调多个团队之间,甚至是整个组织内的工作。

C/S和B/S两种架构区别与优缺点分析

C/S 架构是一种典型的两层架构,其全程是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据

架构/构建高可用的网站

目的为保证服务器硬件故障时依然可用,数据依然保持并能够访问,手段:数据和服务的冗余备份以及失效转移机制,有状态 :在服务端保留之前的请求信息,用以处理当前请求(例如:session)无状态 :没有特殊状态的服务

大型web系统架构详解

动态应用,是相对于网站静态内容而言,是指以c/c++、php、Java、perl、.net等服务器端语言开发的网络应用软件,比如论坛、网络相册、交友、BLOG等常见应用。动态应用系统通常与数据库系统、缓存系统、分布式存储系统等密不可分。

讲讲亿级PV的负载均衡架构

本来没想写这个题材的,为了某某童鞋能够更好的茁壮成长,临时写一篇负载均衡的。负载均衡,大家可能听过什么3层负载均衡、4层负载均衡、7层负载均衡什么的?那这是怎么分的呢,ok,是根据osi七层网络模型来分的,例如nginx是工作在应用层

朱晔的互联网架构实践心得:品味Kubernetes的设计理念

Kubernetes(k8s)是一款开源的优秀的容器编排调度系统,其本身也是一款分布式应用程序。虽然本系列文章讨论的是互联网架构,但是k8s的一些设计理念非常值得深思和借鉴,本人并非运维专家,本文尝试从自己看到的一些k8s的架构理念结合自己的理解来分析 k8s在稳定性

大型网站核心架构要素

一般来说,除了当前的系统功能需求外,软件架构还需要关注性能、可用性、伸缩性、扩展性和安全性这5个架构要素。性能是网站的一个重要指标,任何软件架构设计档案都必须考虑可能会带来的性能问题。

大型网站技术架构 构建高可用的网站 高可用的服务

本章介绍如何去构建高可用的服务,关键词:服务分级,超时设置,异步调用,服务降级,幂等性设计,一些架构设计中的常用方案,但是需要结合实际业务场景进行设计,没有一套方案能解决所有问题

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!