目录

    最近在优化一下项目,梳理整个链路之后,开始逐步优化,发现了很多可以改进的点。下面是对开发模式、部署方式的一些思考,希望对你有所启发。

    1. 开发背景

    1.1 部署方式

    如上图,简单描述一下应用的架构。

    采用的是经典三层架构,接入层,逻辑层,存储层。其中,接入层和存储层,是全部应用共用的服务。逻辑层由 K8S 部署,每个应用会有多个实例。

    接入层能支持的并发量很大,由一个 LVS 将流量分给 多个 Nginx 实例。

    逻辑层主要是将代码以 Slug 的形式打包到基础镜像,然后进行多实例部署。为了保证数据一致性,逻辑层不会保存任何状态,状态全部需要通过外部服务的形式管理。

    存储层提供各种状态服务,比如 MySQL、对象存储等。

    1. 2 开发模式

    如上图,简单讲一下目前的开发模式。

    我们采用的是前后端分离的开发模式。后端采用的 Django,前端 Webpack + Vuejs。前后端的交互通过 index.html 和接口进行。

    开发者服务分为两部分:CI,CD

    CI,也就是开发者持续集成。开发者分别向同一个仓库,提交代码。为了确保开发质量,会做一些 Merge Request 流程。当代码合并到 master 分支之后,CI Runner 会被触发执行,编译前端 Webpack 工程,然后将编译生成的前端文件和后端代码推送到 SVN 发布仓库。

    CD,持续部署部分主要是由 PaaS Engine 提供。这是一套由 K8S 提供的部署引擎。

    2. 开发问题

    虽然采取的是前后端分离的开发模式,但是实际上代码仓库使用的是同一个。这是由于 PaaS Engine 只支持 SVN 方式部署。同时,PaaS Engine 是一套通用的部署引擎,并不会针对前后端开发模式进行特殊适配。

    使用同一个代码仓库进行开发,由于使用不同的目录,代码层面不会产生冲突,但是在部署上进行了强绑定 — 必须前后端一起部署。这导致了一系列问题。

    • 代码仓库大,GitLab CI 推送 SVN 慢
    • PaaS Engine 转发前端静态文件效率低
    • 在开发迭代过程中,线上问题不能即时有效修复
    • 正式环境不能进行灰度测试,只有一个版本
    • 前后端仓库权限混乱,职责不清
    • 不同地区、网络访问应用的速度差别大

    3. 前后端更多的分离

    个人认为前后端分离最大的意义在于,权责的分离。权,意味着可以自由选择技术,发掘一些有趣有用的东西,取悦自己,也为了更好的发展项目。责,不仅仅是按期完成任务,还意味着需要去思考项目的持续性,优化项目中的问题,预防可能的风险。

    第一步,拆分 Git 仓库。

    如上图,我们将整个应用拆分为两个 Git 仓库。前端同学负责前端的 Git 仓库,后端同学负责后端的 Git 仓库。

    第二步,分开部署。

    PaaS Engine 部署时,拉取的是指定 SVN 仓库代码。这是一个禁锢,应用开发者以为代码需要打包,整合在一起才能部署。

    在对应用进行优化的过程时,我逐步将前端第三方插件移动到 CDN。突然想到,为什么不将整个前端文件都放到 CDN 呢?

    当然可以!静态资源直接使用 CDN,不仅能实现高并发,还能低延时,降低网络和地域的差异。绝对是前端部署的首选。

    如上图,CD 过程被拆分为两个并行独立的步骤。后端依然走之前的发布流程,在 GitLab 合并代码,推送到 SVN 之后,借助 PaaS Engine 进行发布。前端除了 GitLab 上的 Merge Request 和 Code Review 流程,在部署时,不需要走 PaaS ,而是直接发布到 CDN。

    完成这两步,就实现了对前后端权责的再次分离。

    4. 版本管理

    前后端统一仓库时,一起部署,版本绑定,不会存在版本错配问题。但是,前后端分开部署之后,版本管理的问题随之而来。

    4.1 前后端对版本文件的管理

    前端的文件存储在 CDN,通过约定的目录结构可以实现对版本的管理。

    假设域名为 cdn.domain.com 。

    存储相对路径路径为:

    /:version_id/js/xxx.js
    /:version_id/css/xxx.css
    

    对应的完整访问路径为:

    https://cdn.domain.com/:version_id/js/xxx.js
    https://cdn.domain.com/:version_id/css/xxx.css
    

    在前后端分离模式中,后端依然需要吐出首页。通过控制 index.html 中引用的静态文件版本,可以达到对前端版本控制的目的。由于只有一套后端发布环境,同时,MySQL 等状态服务不支持回滚,后端的发布,一旦数据库字段发生变更将只能向前滚动。

    index.html

    <script type="text/javascript" src="https://cdn.domain.com/{version_id}/js/vendors.js"></script>
    <script type="text/javascript" src="https://cdn.domain.com/{version_id}/js/app.js"></script>
    

    这里的 version_id 是后端数据库中的前端版本号。通过一定策略修改版本号,可以实现灰度测试、A\B 测试的效果。

    4.2 前后端联调验收策略

    前后端代码仓库分离之后,各自发布版本。

    但是前端版本与后端版本,不一定能组成一个可以发布的应用版本。例如,在新的一期迭代过程中,前端完成了功能开发【f5.3.1】,但是后端的当前版本【b3.4.4】没有就绪。

    针对正在迭代中的版本,我们约定一种发布模式,起名为红绿发布。

    如果前后端当前版本联调,验收通过,那么将前后端版本标记为绿色。

    如果前后端有一方,发生调整,会影响之前功能的正常使用,那么将修改的版本标记为红色。

    直至下一次联调版本验收通过,则将前后端版本再次标记为绿色。