-
Notifications
You must be signed in to change notification settings - Fork 22
Architecture
统一通用软件架构是整个 cn-font-split 经过 7 代代码重构升级、3 次架构升级后最终定下的开发架构。
统一通用软件架构以任意语言代码为核心组件,通过 ProtoBuf 协议定义对外接口及代码自动生成,最后通过各种适配 Wrapper 层来实现各种语言、各种平台的通用调用,极大减少了重复代码的编写,责任明确,适应力强。
统一通用软件架构不仅可以使用在 cn-font-split 框架中,也可以用于大部分二进制派发的场景中。
cn-font-split 是一个复杂的字体分包系统,整体架构分为三个主要部分:Rust Core、ProtoBuf Channel 和 Wrapper。
Rust Core 是 cn-font-split 的核心部分,负责实际的字体分包操作。它通过接收回调函数作为参数,实现异步数据返回。
font_split 函数现在为同步实现,速度足够快。架构上设计为异步函数,因异步数据返回这种形式可兼容不同的信道层实现。
Rust Core 内部主要包含以下四个核心逻辑模块:
- 预分包算法(pre_subset):在进行实际分包操作之前,预处理字体数据,进行多语言的分包优化,确定分包内字符。
- 批量分包(run_subset):处理大批量字体数据的分包操作,确保在高负载情况下依然能够高效运行。
- 链接分包(link_subset):将分包后的字体数据进行链接、整合和汇报,生成最终的分包结果。
- 报告器(reporter):收集整个程序运行过程中的数据,将其汇总为日志报告文件。
ProtoBuf Channel 是 cn-font-split 与外部系统交互的桥梁,基于 protobuf 实现。能够达成跨语言接口定义和代码自动生成,极大减少了复杂的适配层开发成本。
cn-font-split 所有的交互接口归 crates/proto 包内进行管理、分发,Wrapper 层通过引用 proto 文件自动生成各种的代码。
protobuf 在 cn-font-split 中有两种使用方式:
- 定义结构体传递: Rust 程序间进行沟通时,直接采用 protobuf 代码生成的 Strut,可以相互调用。
- 二进制数据传递:通过 protobuf 代码和任何一种可以传递二进制的信道进行数据交互,可以实现跨语言层面的直接调用。
wrapper 是 cn-font-split 对外提供的功能接口,支持多种语言调用和不同的部署方案。其核心为封装 Rust Core 和 ProtoBuf Channel 的复杂交互,直接提供简单使用方式。
wrapper 主要包括以下几种实现:
- ✅ gRPC Wrapper:基于 HTTP/2 协议,提供独立的字体构建服务。gRPC 方案简单易用,适用于所有支持 gRPC 的项目。
- ✅ FFI Wrapper:通过标准的 C API 调用 Rust 生成的二进制动态链接库,使用 protobuf 解析二进制数据,支持双边语言通信。
- ✅ JavaScript Runtime 使用
- ✅ Python Runtime 使用
- ✅ CLI Wrapper:提供一个命令行接口,用户可以通过简单的命令完成基础的字体分包操作。
- ✅ WASI Wrapper:基于 WebAssembly System Interface (WASI),支持在多种操作系统环境中运行,提供更广泛的部署可能性。
- 浏览器可以通过 WASI(@tybys/wasm-util)实现完成接入。
所有的 CI 脚本存储于 github workflow 文件夹。Github Action 提供的机器支持 Windows 和 MacOS 两个环境,对跨平台构建非常友好。
简单构建流程如下:
- Github Action 跨平台构建
- 制品上传至 Github Release
- 完成制品版本发布
- 如果 Wrapper 层有改动
- 构建 Wrapper 层包并上传到对应的库(NPM、PYPI 等)