当前位置: 首页 > 科技观察

后端有微服务,前端呢?初识微前端的世界

时间:2023-03-14 14:25:08 科技观察

前言最近,笔者在工作中不断听到后端工程师在谈论Microservices(微服务)的架构设计。作为一名工程师,当然也希望前端也能有这样新颖的架构,所以本文就给读者介绍一下MicroFrontends(微前端)。什么是微服务?在开始进入本文的正题之前,首先要给读者介绍一下什么是微服务。微服务是一种软件架构,专注于开发每一个小的功能或服务,最后用模块化的方式组合成一个大的应用。如果读者是前端工程师,可能会觉得上面的描述和ES6模块架构很像。开发者只需要专注于每个模块的开发,最后使用Bundler将这些模块打包成一个完整的页面甚至是一个应用。就像下图一样。但是,后端与前端完全不同。后端使用一个接一个的请求实时执行相关代码。因此,在微服务架构中,一个服务又一个服务是可以相互通信的。这时候就是依赖各个API。但是这时候就会出现很大的问题。如果这三个服务都高度依赖前端的话,以上图为例:一个完整??的购物网站首先要让用户先登录,然后才能购买商品,然后去查看购物车。此时客户端必须调用3次API,并等待对方完成整个过程。即使一个服务不小心坏了需要重启,这个时候可能会先出现一个过渡期的API,防止客户端打到有问题的Service,但是客户端也不可能每次都记住新生成的API,所以这将不可避免地引起一个大问题。这时候你其实可以给这些Services添加一个APIGateway。对于客户端,我只需要找到一个网关。对于这个Gateway,我也是调用每一个Service,处理完所有的资源后发回。到前端。如果有读者是熟悉Docker或者K8s这种自动部署容器化应用的平台的SRE,应该对上图比较熟悉吧!像K8s有类似APIGateway的Ingress,而Docker有routingmesh。但是单靠APIGateway并不能突出微服务的特点。在微服务架构中,每个Service都可以拥有自己的DB。目的是防止每个服务相互关联。但是这样做其实有几个缺点,很难保证数据的一致性。上图就是一个例子。如果会员今天注销,但会员必须在注销前在**购物车**服务中结账。商品,这时候就会出现会员数据不一致的问题。DB数据丢失当服务中断需要重启时,此时DB数据可能丢失,导致后续数据错误。为了改善这些缺点,此时可以将这些ServiceDB设计成一次性的。也就是说,这些DB只是用于短期的数据访问,它们背后有一个共享的大数据库来更新这些数据。通常他们会使用Redis这种缓存DB来进行设计。为什么需要微服务?微服务的好处是你可以专注于每一个小服务的开发。例如,一个购票网站可能会在短时间内涌入大量流量。这个时候,racecondition就很重要了。这时候可以使用Go语言进行开发,或者开发一个面向性能的服务,这时候可以使用Rust进行开发。上面也提到微服务必须依赖API之间的通信,所以在企业级产品上通常会有拆分模块销售的需求。如果此时使用微服务架构进行开发,很容易拆分各个模块。服务。这些都是使用微服务可以带来的好处,所以如果读者今天需要开发一个非常复杂庞大的平台,此时不妨使用微服务架构进行开发!MonolithicArchitecture(单体架构)说完微服务,相信读者应该对这种架构有了初步的了解。与Microservices不同的架构是MonolithicArchitecture(单体架构)。一般来说,我们正常的开发都是使用MonolithicArchitecture。在MonolithicArchitecture架构中,平台内的所有内容都会被打包,如下图所示:这种架构还不错,但是如果今天要拆分或者扩展平台,互联网上的服务其实比较麻烦,而且又怕牵一发而动全身,甚至所有的服务都连接到同一个DB,极有可能导致DB连接同时过高,导致请求不断失败,所以这是微服务要解决的痛点之一。什么是微前端?微前端可以想象成微服务的前端版本。在后端世界中,强调一个接一个Service,而在前端世界中,强调一个接一个模块。如何有效的拆分网页中的各个模块是微前端要做的工作。微前端的实现接下来要给读者介绍的是微前端的实现。其实微前端的实现有不少:iframe通过iframe的特性让每个加载的块页面都可以独立运行,如果需要数据通信也可以使用window.postMessage来完成,但是这样会缺点很多,比如可能加载相同的代码,UI难以控制,甚至可能存在安全隐患,所以笔者还是建议读者不要使用这种方式来实现微前端。客户端使用JavaScript加载模块。这种方法简单粗暴。就是用JavaScript创建一个script标签,然后用script标签加载相关模块,最后将其内容插入到对应的div中,但缺点是不能使用SSR,整体写法会如下图所示。WebComponentsWebComponents可以说是讨论最广泛的微前端实现。虽然现在的网页架构中我们可以随意导入大佬们写的组件,但是不可避免的会遇到以下问题:依赖问题:需要安装一个只有这个组件才会用到的库,这样会让整个node_modules变得相当庞大。作用域问题:前端通常会使用很多className来为stylechange做stylechange,但是可能因为组件也写了同一个className很多时候需要各种重写,长此以往会是项目的负担维护。版本兼容问题:只要框架大改版,基本很容易出现组件不兼容新版本的问题。此时,只有组件作者才能在再次使用之前升级版本。相信很多开发者也面临着这种情况。困境。因此,WebComponents的出现就是为了解决以上问题,WebComponents由以下三个元素组成:自定义元素自定义一个语义标签来引用组件,使用JavaScript创建自定义元素,影子DOM,HTML模板三此自定义标签之间的关联将如下所示:。ShadowDOMShadowDOM简单来说就是生成一个完全独立于现有DOM树中其他元素的子DOM树。通过这种方式,子DOM树可以独立运行,不会干扰其他DOM树。元素。HTML模板利用