本文的关键点是围绕提高个人工作效率展开,谈谈笔者如何解决重复工作的问题。
简介
自动化、配置化、UI 化、平台化与被优化 —— 曹春晖《在业务系统中寻求技术含量》
本文的关键点是围绕提高个人工作效率展开,谈谈笔者如何解决重复工作的问题。
因为笔者从事 Golang 后端开发方面的工作,解决问题时会优先考虑 Golang 方面的工具和技术框架。
在笔者平时的工作中会遇到开发环境调试的问题,例如编写脚本用于调整线上数据、通过微服务 RPC 接口查询数据提供给其他团队成员以及共享调试程序等。
诸如上述需求,笔者选用简单的技术形成工作流来达到提高工作效率的目标,工作流主要有 4 个步骤。
- 基于 Gin 提供 API 服务
- 基于 Docker 管理 API 服务
- 基于 Traefik 发布 API 服务
- 基于 Amis 高效构建可视化前端
其中第 1 步是关键,为「自动化」与「配置化」打基础,而第 2 步和第 3 步就是将「自动化」贯彻到底,第 4 步为「UI 化」。
基于 Gin 提供 API 服务
在业务开发过程中,笔者经常需要编写脚本程序来实现重复的工作,比如调用 RPC 从 A 接口读取数据并将其通过 B 接口写入,虽然程序编写过程没有难度,但过于固定、缺乏使用文档以及脱节的管理共享的方式,容易发生团队内重复造轮子的情况。
对应上述情况,笔者采用将脚本程序 API 化的方式进行解决,将传统基于 Cobra 或其它命令行框架的脚本程序统一采用 HTTP 的方式进行实现,这种方式有以下好处。
- 低门槛的调用方式。无论是测试还是产品都可使用浏览器或 Postman 调用。
- 更友好的参数传递方式。参数要求少的程序可采用 Get 请求,并且能直接发布请求链接。
- 高效的更新与发布方式。对于需求变更快的情况,可以快速修改、编译并发布程序,而无需分发至其他成员。
尽管笔者所在公司有 gRPC UI 协助调用 gRPC 接口,但这种方式不便于程序调试和执行脚本任务。
笔者在将程序 API 化的过程中采用了 Gin 作为 Web 开发框架,因为该框架具备友好的文档和出色的性能表现。编写本地调试所需的 API 服务的主要思路如下:
- 整理执行任务所需的参数,如调用登录接口获取 Token 时所需的用户名和密码。
- 必要参数少于或等于 2 个的任务采用 Path 参数的方式构建 GET 请求。
- 可选参数使用 Query 参数的方式进行解析。
- 编写业务所需的流程。
经过笔者的实践,建议避免使用 POST 作为请求的方式,因为该方式的接口无法被浏览器直接访问,对于非技术人员有使用门槛。
至此,团队其他成员可以通过笔者工位电脑的 IP 地址加上 API 路径对程序进行调用,但仍然存在一些问题,例如电脑重启后 API 服务无法自动恢复、随着 API 数量增加而带来的管理问题以及权限问题。
基于 Docker 管理 API 服务
Docker 是一款开源的容器引擎,笔者在编写完 API 服务后打包并发布到工作电脑安装的 Docker 中运行。
使用 Docker 进行应用管理的出发点是简单,相较于直接 go run
运行程序,使用 Docker 不仅可以设置容器启动策略实现自启动,还可以运行数据库容器给 API 服务提供数据存储功能。
笔者在使用 Docker 管理 API 服务的过程中经历了手动构建升级到自动构建的过程,大致流程如下所示。
- 全部 API 服务集中在一个 Golang 项目下,并以 API 服务名作为子目录名。
- 项目根目录编写 Dockerfile,该 Dockerfile 建议使用 alpine 作为基础镜像并 Expose 开放 80 端口。
- 编写 Bash 脚本,内容囊括
go build
、docker build
、docker rm
以及docker run
。
经过笔者实践,在物理机环境下编译应用耗时会比容器内编译短,常用的 go build
命令如下:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main ./子目录
在 docker build
阶段构建的镜像推荐使用 API 服务名作为镜像名,项目 git commit 的 sha 摘要值作为 Tag。而在 docker run
阶段需要注意设置容器名、restart 策略以及容器的网络。
关于容器的网络,笔者更推荐使用新的网络作为 API 服务的网络,因为默认 bridge 网络下的容器无法通过容器名访问其他容器,创建容器网络可以使用 docker network create 网络名
命令创建。
至此,借助 Docker,笔者使用 Gin 编写的调试 API 服务已经能稳定运行(不关机的情况下)。
基于 Traefik 发布 API 服务
随着 API 服务数量增加,无法避免的是服务管理问题,例如 80 端口分配、API 权限隔离以及无法记录访问日志等。
针对上述的服务管理问题,笔者初期考虑的是采用 Nginx 进行接口转发,但使用 Nginx 需要繁琐的配置,反倒让问题更加棘手,至于 Istio 这种仅适合 Kubernetes 的方案对于工位电脑来说也不合适。
笔者最终选用的是 Traefik 对 Docker 内的 API 服务进行流量转发,Traefik 是开源的边缘路由网关,它的核心优势是上手简单,同时笔者推荐使用 Redis 作为 Traefik 的路由配置 Provider(可以使用 Docker 运行 Redis 容器,请注意数据持久化)。
除此之外,笔者还准备了一个域名并使用 ddns-go 将二级通配符域名解析到工位电脑的内网 IP 地址。
笔者目前 API 服务发布的过程如下:
- Docker 上运行服务容器。
- 将对应的子目录名作为二级域名解析到对应的容器(可以进一步优化成自动化写入 Redis)。
- 如果有鉴权需求,只需要添加对应的 Middlewares 中间件即可。
除了流量转发和鉴权,Traefik 自带的 dashboard 能更直观地显示正在运行的 API 服务信息,至于 Traefik 更多的高级功能,读者可以自行查阅。
基于 Amis 高效构建可视化前端
前文使用 Gin、Docker 以及 Traefik 搭建调试用的 API 服务架构已经能应对常见的需求,但笔者偶尔会需要从线上获取数据,然后转换成 Excel 或者文档等可视化的形式将数据提供给非开发人员。
在实际的研发工作中,这类数据获取和展示类的需求往往较为迫切,哪怕在框架的加持下,无论是 CSV 还是 Excel 平均需要花费 30 分钟以上的时间(与表格的复杂度呈正比)来编写和运行程序来导出。
尽管笔者尝试过将数据导出为 JSON 并通过一系列的方式转换成 Excel,但效率依旧低下,且无法适配大部分需求。
笔者在上网查询资料的过程中无意间了解到一款前端低代码框架 Amis,该框架提供了一个 CRUD 组件能够将前端表格的内容直接转换成 Excel 的方式供使用者下载。
经过笔者学习与探索,确定了一种适合后端开发人员的高效可视化前端构建方式,主要思路如下所示:
- 编写一个静态页面作为首页,将 Amis 使用 CDN 的方式引入,并让主要区域以远程加载的形式渲染。
- 使用 Golang 1.16 自带的 embed 包内嵌静态页面并使用 template 渲染。
- 使用 MySQL 所提供的 JSON 字段存储页面配置并编写接口进行增删改查。
- 使用上述 API 服务提供展示数据的获取接口。
- 使用 Amis 在线编辑器构建前端页面并存储到 MySQL 页面配置表。
目前笔者已经在日常工作中落地实践 Amis 低代码框架,如果感兴趣可以浏览笔者编写的基于 Bbolt 内嵌式存储引擎的 goAmis - Demo。
总结
尽管笔者只是一名普通的搬砖工人(笑),但笔者坚信工欲善其事,必先利其器,一个适合自身的工作流比较重要。
目前笔者已经使用 Shell 命令完善了第 2 步与第 3 步,所以只需要将重复性的工作编写成 API 服务即可,在需要的时候使用浏览器或者 Postman 调用即可。
基于上述四步,笔者已经能够应付大部分测试、运营与产品的额外需求,根据曹大的文章,这应该就是所谓的「自动化」、「配置化」以及「 UI 化」,至于「平台化」,目前来说并不是笔者这样小小的工具人能实现的,或许曹大所说的「被优化」会来得更早一些。
参考资料
- 在业务系统中寻求技术含量 - 曹春晖
- Gin 开发框架 - https://github.com/gin-gonic/gin
- Traefik 文档 - https://doc.traefik.io/traefik/
- Amis 前端低代码框架 - https://github.com/baidu/amis
- goAmis - demo - https://github.com/avtion/goamis