前后端分离进击之路

起源

Web刀耕火种的时代,创业型小项目非常之多,不分前后端,页面由 JSP、PHP 等工程师在服务端生成,浏览器负责展现。基本上是服务端给什么浏览器就展现什么,展现的控制在 Web Server 层。

这种模式的好处是:简单明快,前后端人员过着与世无争的生活 原始

直到有一天,出现了一个新物种:产品经理 进击的巨人

我们的需求越来越多了,功能实现越来越复杂了,项目越做越大了。前后端人员进入了混乱阶段。

为了打败强大的产品经理,我们必须提高项目的扩展性、合作的流畅度,充分发挥个人的技术栈,以适应日渐增长的业务需求。

所以我们进行了:前后端分离

前后端分离结构

前后端分离

数据的展现是后端通过异步接口的方式提供的,前端只管展现。 前后端分离

Web 前后端分离的意义

  • 网站前端展示页面变化远比后端变化频繁
  • 原始的网站开发模式,数据逻辑与表现逻辑混杂不清,难以维护、扩展
  • 网站前端效果绚丽,专业化也越来越高,VUE、Three.js、小程序等,技能差异也很大
  • 前后端开发相对独立,互相影响小,分工、职责明确
  • 前后端都可以专注于自己熟悉的技术栈

问题

  • WEB端如何做SEO优化?(NodeJs服务器渲染)
  • 前后端如何独立地进行开发?(MOCK数据)
  • 如何制定接口的契约以及修改后的及时通知消费者?(定制化接口文档)

演化

前端架构VUE

Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动

API文档

预期不了它的正常行为是什么。输入了一个 A,预期返回的是一个 B,结果它什么也没有。有的时候,还抛出了一堆异常,导致你的应用崩溃。

在前后端分离的项目里,API 也是这样一个烦人的存在。我们就经常遇到各种各样的问题:

  • API 的字段更新了
  • API 的路由更新了
  • API 返回了未预期的值
  • API 返回由于某种原因被删除了
  • 。。。

API 在其的生命周期里要不断地演进、变化的,问题是这种变化是双向的、单向的、联动的?还是静默的?

如何制定接口的契约以及修改后的及时通知消费者?

从代码入手

mock server

  • 编写契约(即 API)。即规定好 API 请求的 URL、请求内容、返回结果、鉴权方式等等。
  • 根据契约编写 Mock Server。可以采用 Moco
  • 编写集成测试将请求发给这个 Mock Server,并验证

而对于前端来说,则是依赖于 UI 自动化测试。在测试的时候,启动这个 Mock Server,并借助于 Selenium 来访问浏览器相应的地址,模拟用户的行为进行操作,并验证相应的数据是否正确。

当契约发生变动的时候,持续集成便失败了。因此相应的后台测试数据也需要做相应的修改,相应的前端集成测试也需要做相应的修改。因此,这一改动就可以即时地通知各方了。

从文档入手

API文档需求

  • 方便的API编辑功能
  • 美观的API展示页面
  • API调试功能
  • API Mock功能
  • 最重要的变动通知功能

考虑的方案

  • 协同文档编辑工具,可进行编辑备注、通知,但编辑困难且没有API辅助功能,专业版收费
  • 文档工具,例如Swagger,方便编辑、调试以及美观的界面,但是变动后不能通知
  • API管理平台,功能齐全,但就是没有变更通知功能,专业版收费
  • 最终决定自行开发,基于swagger作为主要工具,根据git的hook进行扩展通知

SOA架构

SOA是一种设计方法,其中包含多个服务,而服务之间通过配合最终会提供一系列功能。一个服务通常以独立的形式存在于操作系统进程中。服务之间通过网络调用,而非采用进程内调用的方式进行通信。

SOA

基础服务

基础服务组件不要面向功能,就是说它不关心是那个具体的业务功能在调用它,它面向业务领域的核心基础逻辑,负责与业务对象和数据层交互,因此也封装了该领域的数据。(专注于数据层的扩展)它的特征是稳定的,与数据层是紧密关联的,它与数据层一起构成应用系统稳定的核心和关键,其他部分包括服务组件和UI都是非关键和随时可以替换的。

组合服务

服务组件实现的功能类似于面向功能的服务,但细节上完全不同,它不同于传统的服务直接操纵数据和处理业务逻辑,它不直接与数据层打交道,它通过组合调用基础服务组件实现一个具体的业务功能。

黑格组合服务

问题

  • 这跟一个接口直接完成业务以及数据操作的模式有什么不同?(数据操作重复,数据层难以扩展,安全性更高,维护复杂 )

服务调用

按需调用

组合服务只做必要的业务逻辑处理,前端自行按需调用组合服务以及原子服务

组合服务封装

组合服务将原子服务封装起来,前端根据组合服务提供的接口进行数据处理

问题

  • 这两种方式有什么优缺点?
    • 按需调用实现简单,灵活调用,但不能对调用进行控制(原子接口不做逻辑处理),安全性低
    • 组合服务封装可对API进行控制(权限、缓存等),安全性较高,对接口调用进行了统一的接入

API网关

既然在线商店使用了微服务模式,商品详情数据通过服务来展开。如:

  • 商品信息服务(Product Info Service) - 商品基本信息如标题,作者
  • 价格服务(Pricing Service) - 商品价格
  • 订单服务(Order service) - 商品购买历史
  • 库存服务(Inventory service) - 商品是否有货
  • 评论服务(Review service) - 用户评论 …

API Gateway(API GW / API 网关),顾名思义,是出现在系统边界上的一个面向 API 的、串行集中式的强管控服务,这里的边界是企业 IT 系统的边界,主要起到隔离外部访问与内部系统的作用。

API网关

网关的作用和价值

网关层作为客户端与服务端的一层挡板,主要起到了三大类作用:

  • 第一类作用是隔离作用,作为企业系统边界,隔离外网系统与内网系统。
  • 第二类作用是解耦作用,通过解耦,使得微服务系统的各方能够独立、自由、高效、灵活地调整,而不用担心给其他方面带来影响。
  • 第三类作用是脚手架作用,提供了一个地点,方便通过扩展机制对请求进行一系列加工和处理。