2024年前端微服务在字节跳动的打磨与应用,分析前端未来几年的发展前景

结尾

学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。

html5

还有其它问题比如 debug 的时候到底能不能找到。也不是单体应用不行,单纯是说解决这个问题的时候投入了多少精力、多少设计,以及维持这个设计规范问题不崩坏,需要多少精力。

这一类都是单体应用本身的代码问题。“拆了就没这些事了。”

框架无法调整

真的从架构角度来说,到底如今的前端项目需要怎么开发、一般是怎么干的呢。从上一段内容读过来,我们知道大部分出色的架构师工程师都已经解决了好多那些困难了,方式是通过杰出的架构设计。

然后都知道前端的各种框架各种实践实际上非常多。前端工程师有个别名不知道你们听过吗,叫“npm install 工程师”哈哈,还有“github search 工程师”。

到底发生了极端困难的情况是来自框架还是来自生产框架的方法呢,这个不好说。但是是个值得琢磨的问题。所以你看接手拿到项目什么的别说了你就学吧。反正现有架构肯定是挺好的。就是你得学一阵、用对了才好。

微前端在字节跳动

========

这里开始讲我们的细节,分别是服务发现、运行隔离、环境一致以及其他架构优势,其实这几件事都讲完就能发现在讲的主要意思是,具体是什么把一个非常特殊、对习惯改变比较大的方案变成可能的。实现这样一个与众不同的方案不是大家聊一聊觉得同意并且开心就能做成。涉及到过程、成本、风险等方方面面。

“工程师”的任务不是说证明一个结构在理论上是可以存在的就完了,要有建造这个结构的过程。比如你拿化学键可以算出来任何可能存在的分子,画个小人都可以。但是到底怎么合成,按照什么路径能让这种分子被制造,哪种路径最快最便宜,这个是过程的可能性。通常这才是工程师的任务。

服务发现


服务发现的方面我们会首先讲一下在整个微服务模式里他作用是什么、有哪些方式。然后第二部分讲到底在解决什么问题,以及多说一些他能提供的新能力。我们很重视新能力因为我们的定位不是消防队,灭了火就完成任务,还有很多新目标、很多新好处可以探索实现。

最后是讲一下在字节跳动具体是怎么实现的。

1. 原理

“服务发现”就是原来的单体服务拆分之后,本来一个项目里的方法分开部署了,谁也找不到谁。需要有个统一的注册机构,把提供服务的各个部署都查到。

“发现”就是当你想访问一个微服务,你要怎么找到他。

这样就有两种构型,一个是以 Netflix OSS 为典型的,它在客户端的机器里先拿到一个服务目录,处理逻辑在客户端的代码里。另一种是服务端的服务发现,AWS 就是如此。

传统微服务的服务发现更像是函数调用的替代,拆了之后怎么调到不同容器里部署的函数。这里微前端思路非常类似,作用略有区别。微服务的情况是会区分像什么订阅、通知、请求、发布这些,前端很可能都不用或者表现上不在前端运行时使用。还有一些例如“对单”、“对多”这些基本就是前端不太用考虑的东西。

两者一致的地方是都谁也不认识谁了,如何知道哪些服务存在、谁在提供?下面就要讲一下各种构型的服务发现和背后的服务注册分别具体是什么情况。

客户端服务发现 是说客户端——也就是服务的调用者,去请求一个注册的目录,里面包含所有服务和负载均衡的基本信息这些,然后自己决定如何处理,使用哪种具体的 load balance 策略。比如 Netflix 的 OSS,服务在 Netflix Eureka 注册一下,它心跳给各个客户端。客户端自己搞,简单直观。

服务端服务发现 是类似 AWS Elastic LoadBalancer 这种。客户端请求就完了,服务端决定怎么给你反向代理、负载均衡。

服务注册 分自注册和第三方注册。自注册不言而喻。第三方注册就是一个保活机制,定期检查服务状态,帮你去管控该上了还是下了。

我们主要用的是第一种:客户端服务发现,就是你要多请求一个模块列表。这个列表给出的资源是根据用户 session 决定的,有丰富的动态的能力。然后客户端再根据这个列表里的各种信息,去加载模块资源。

2. 给前端带来了什么?

用服务发现的方式去组织微前端,除了使复杂的上线流程变得解耦、快捷,还可以使拆散之后的工程版本方便对齐,实现更高的稳定性和可调试性。还对前端工程带来好多其他好处。下面主要讲一下各种收益中的最重要的两个。

快速上线 是什么概念呢,前面说了几十个业务和在一个项目里,一起发布,这样发布的频率能有多高?实际考察一下放开限制后的情景,就会发现有超乎意料的高。我们的一个微前端应用的业务是头条号,它在 2019 年上半年发了 2000 个版本。前面说了传统上线需要 30 分钟才能完成打包升级和容器的重启,并且 10 分钟才能完一个回滚,这就意味着 1000 小时的上下线等待时间。相比之下我们新的方式点一下 HTTP 请求发出去就生效了,是一个毫秒级的反应速度。

这个搁以前就不是慢、需要干等着的问题了,直接大家就不这样去发了。都学 Native 发版那样火车式发布。结果是响应效率降低了很多,很多需求渐渐变得不再由开发形成瓶颈,反而是总要等版本排发布。

独立切换 我们现在就分别发,可以一个单页应用分几十个模块,各自上各自的、下各自的。而且后面会说到还可以各自配置自己的 AB 测试版:有 10 个模块就可以产生 1024 个 AB 版的组合,20 个模块 100 万个。跟以前完全不敢想象——也就是说一起发版的时代根本做不了这个事。现在不敢想象的反而是,你说字节跳动某个业务里面不能做 AB 测。

我们的头条号平台就是刚才一个典型的微前端项目,包含列出的这么多模块,各模块有独立的版本,和对服务版本的 session 控制。每个模块进去都是版本列表,有一个模块所有的历史版本。通过这个平台配置小流量、AB、上线规则。

运行隔离


1. 耦合开发的严峻形势

17 年我们推进项目的时候有一个很不错的帖子很流行,红遍朋友圈那种,讲 react-loadable 的。ta 从解耦的维度介绍了这个方向。我们当时也有一个很明确的业务需求,要把公司不同部门的人组织到一个项目里。并且这个项目经过经年累月的增肥,已经非常臃肿并且积攒了很多值得推敲的、非直接技术的工程细节。这就意味着要用不同组织,不同的技术,不同的工程规范和打包工具,去合写同一个平台、同一个工程。如果当时用了 iframe 可能就是非常凑合的勉强满足业务,完全不符合我们追求极致的习惯。

然后当时我们很在意一点就是这种跨团队合作,想融合不同的技术团队,实现少费力沟通或者不重沟通,运行隔离是个非常绝对的基本前提,我们其他分享里面也用了不小的篇幅介绍,有对内的也有对外的。当时的效果是什么呢。这个是我们 18 年 4 月内部培训录制到的当时情况:

我们把线上的页面(左图)通过调试工具插入脚本,临时移除掉沙盒功能,得到的右图效果。

2. 运行隔离的目标

运行隔离是啥意思,回想一下刚才说的 AB 测的问题,20 个项目是多少个组合。如果把这个对应到 bug 的维度,大家都在一个应用里乱跑会有多恐怖。那么这样的组合对我们的程序和程序员提出了什么样的要求?

不跑挂 说是“对一切工程师最基本要求”,我觉得不算夸张。所有软件工程师的第一个能力层级都应该是不把系统拖垮。微服务之后这个问题不明显了,因为有架构层面的方式解决了绝大多数挑战。我很信服的一个理论是所有程序员都是四个阶段:写完需求,不拖垮别人,能扩容,性能好。

不干扰 也是另一个大问题,我们当时西瓜团队和头条是两个独立的 App,他们和我们的合作完全跨部门,连 polyfill 的规则都不一样。事先也是做了很多公共组件、 CSS 约定之类的。但是规范和约定远远不够。协作的境界从最差到最好应该是:

  • 定规范:谁来了都好好学、好好听,自己对自己的行为负全责。

  • 能 enforce 规范:不凭自觉,而是用工具和流程等手段去发现和强制,实现可靠性。

  • 不需要规范:系统的确定性由系统解决。靠人去发现和执行规范是消耗大量认知资源的,带来的都是额外的工作量和系统的不确定性。

3. 沙盒

我们还有另外一篇文章专门介绍沙盒的设计和采坑经验。这篇就快速用几张图示意一下。

① 变量保护: 全局变量、 DOM 和 CSS 基本都是走的这条路。前后两次快照,我们来比较,之后根据需要帮你恢复现场。这块内容不细说了,看一眼图就不言而喻:一次比较对照所有 key、两次遍历、黑名单 location、白名单 readonly。估计我这样一说大家都懂。

② 沙盒时序: 稍微多说一些。右图是我们做的 ABCDE 五个模块的加载和混行的时序图。虚线左边是加载,右边是独占线程所占用的时间。也就是说有 ABCDE 五个模块五个沙盒,分别在这个模块编译(下载、创建 js 变量和函数、运行这些语句、最终生成一个 React Component)和运行时(这个模块被打开、渲染对应的所有功能)。

这里面两个基础:js 单线程、事件循环

我们用了非常单纯的单进程操作系统的思路,比喻一下就是 js 的单线程就像单核 CPU 一样。你激活一个模块,相当于激活一个线程,其他都退到背景里。

实际上单核单进程不是必然,大家都知道这个原理。在事件循环的基础上,我们可以封装所有的异步操作,把回调套在沙盒激活后面。比如 setTimeoutaddEventListener,这样每个模块看起来就像是在并行。这块可以说的很多,但是就想一下操作系统的比喻就好了。

4. 加载方式

React 的项目用 react-loadable 本身不多说了,VUEraw (也就是不包含展示层框架的原始版)的各种项目,我们都提供 masterpage 的样例,每个版本对应的都实现了一套和 react-loadable 相似的效果。

子模块(Modules) 就是一个个的 CMD 包,我用 new Function 来包起来。其他就是具体主工程(MasterPage)项目框架的约定,load 过程分为 5 个钩子:

  • preload 是否预加载,是个 promisefullfill 的时候就会触发 Ajax。各种空闲政策阻塞政策都可以由 master 制定;

  • loadCondition 编译前置条件,fullfill 了才会开始运行这部分,执行结果就是得到那个 CMD 的 exports

  • provider 是一个模块的入口的函数,由模块开发者提供,返回模块的一切输出。这个函数的传入参数由 masterpage 主工程来提供。

  • loaded 完成加载,得到编译结果了。

  • 等等后面不说太细了。

环境一致


因为我们之前都是在讲微服务是什么和落地效果如何,从来没有讲过 推行一个微服务你得做什么。现在这部分内容是我们第一次公开分享的,也是一个很独立的维度。

其实就是在讲为什么对微前端来说这个环境一致工具是必须的,是绕不过的必经之路。如果不搞也很容易就栽进坑里,项目失败。然后很可能还不知道是为何失败的,把问题归结为框架不好啊、人不好啊甚至微前端就不好啊之类的问题上。

1. Serverless vs container

container 就是一个寄生环境,尽管这个环境还是挺特殊的,不像 linux 这种完整操作系统。相比之下 Serverless 就特殊多了。特殊到连谷歌云都曾经在商业上被击败。

这里举两个 Serverless 的例子,比如 lambda。它的本地工具是一个 CLI 系统:SAM,是一个非常典型的必要基础设施。如果说发展容器化 AWS 全是靠 docker,发展 lambda 就是靠的 SAM。

另一个典型的例子 firebase。想必前端的同学们都非常清楚,也都用过他们的开发套件。这些工具都非常重视一点就是本地开发,我做个项目到底能不能先测试再上。或者说先调试在上。

要做的话就是尽可能模拟真实环境了,SAM 的话就模拟了 API Gateway,memory limit 这些。有 live debugging、 local debugging。不然的话发什么疯有人敢把线上业务放到一个非常不同的环境下运行。

2. 你是不是环境有问题(在我这是好的)

标题程序员最常说的一句话对不对,另一种表达是“我这是好的”。大家都知道绝大多数情况这么说话不对,但常常会忍不住说。甚至更像是其实是对自己说。一种扪心自问,自我拷问,“我这是好的啊”。

我们用沙盒把微前端做成了像 container,像浏览器里的 docker。但是不够,我们还是把寄生在 masterpage 内这种应用框架的特征,也就是业务具体逻辑,看成是一种 Serverless。

然后我们还把隔离的思路做到极致,我们的 dev 命令是通过启动参数启动一个完全独立的 Chrome 会话,有自己的 cookie 啊缓存啊这些,效果像是装了 2 个 Chrome 乃至多个 Chrome。然后代理工具默认也配到了启动参数,是个 pac 文件。所以也可以单独用或者装 switchy 用。

代理工具 就是调试环境的整个配置,那些走测试环境、哪些走线上请求全部代理管理。生成一个动态的 pac 地址和代理服务。就是刚才说的。

总结

三套“算法宝典”

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

28天读完349页,这份阿里面试通关手册,助我闯进字节跳动

算法刷题LeetCode中文版(为例)

人与人存在很大的不同,我们都拥有各自的目标,在一线城市漂泊的我偶尔也会羡慕在老家踏踏实实开开心心养老的人,但是我深刻知道自己想要的是一年比一年有进步。

最后,我想说的是,无论你现在什么年龄,位于什么城市,拥有什么背景或学历,跟你比较的人永远都是你自己,所以明年的你看看与今年的你是否有差距,不想做咸鱼的人,只能用尽全力去跳跃。祝愿,明年的你会更好!

由于篇幅有限,下篇的面试技术攻克篇只能够展示出部分的面试题,详细完整版以及答案解析,有需要的可以关注

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值