电子说
前言
本后端项目用到的技术栈主要包括:
Actix Web框架;
Log 日志库;
Serde 序列化;
SnowFlake Id生成;
dotenv 获取环境配置;
MongoDB 存取;
lazy_static 全局静态初始化;
ELO 算法;
使用 Pre-Commit 在 Git Commit 前进行校验;
使用 Github Action 进行 CI;
使用中间镜像对代码进行编译并创建部署镜像;
……
阅读了本文,你应该也能够学会上面这些库的用法;
那么废话不多说,直接开始!
代码实现
代码目录结构
整个项目的目录结构如下(已去掉无关文件):
下面来说明:
.github 目录:Github Actions 相关配置;
src 目录:项目源代码目录;
.pre-commit-config.yaml:Pre-Commit 配置;
.env:项目环境变量配置;
Cargo.toml:Cargo 项目配置;
Makefile:项目编译脚本;
Dockerfile:项目Docker镜像配置;
build-image.sh:打包镜像脚本;
对于 src 目录下的各个子目录,见名知意,基本上很好理解了!
服务入口
Cargo 项目约定程序的入口都是:src/main.rs 下;
我们从 main 函数来看做了些什么:
src/main.rs
在入口文件中,首先启用了一些库的宏(Macro),并声明了 Actix-Web 框架的 main 函数;
在 main 函数中,做了一般后端服务都会做的事情:
获取环境配置;
初始化项目日志;
初始化资源:数据库、Id生成器等;
注册并启动服务;
下面我们分别来看
配置与日志
获取环境配置
我们可以通过 dotenv 库解析位于项目下、以及系统环境变量中的配置;
只需要下面一句话即可:
dotenv().ok();
配置文件如下:
.env
MONGODB_URI=mongodb://admin:123456@localhost:27017/?retryWrites=true&w=majority
LOG_LEVEL=INFO
SNOWFLAKE_MACHINE_ID=1
SNOWFLAKE_NODE_ID=1
主要是配置了 MongoDB 的连接地址、日志级别、SnowFlake 的配置;
上面的语句会将这些配置解析;
初始化Logger
main 函数中的这条语句初始化了 Logger:
logger::init();
这个是 logger 模块封装的一个函数:
logger/mod.rs
上面的代码首先定义了一个全局日志类型 Logger;
并在 init 函数中初始化了全局静态变量:LOGGER,并使用 log::set_logger 进行了设置;
同时,我们我们从环境变量中获取 LOG_LEVEL 日志级别配置(如果未设置,则默认为 INFO 级别),随后进行了设置;
我们为我们的 Logger 实现了log::Log Trait,这也是为什么我们能将该类型的变量设置为Logger的原因!
在 log::Log Trait 的实现中,我们简单定义了日志的输出格式以及输出颜色;
可以看到有了很多第三方库的支持,rust 还是非常好用的!
初始化资源
接下来我们调用:
resource::check_resources().await;
service::init_file_service().await;
来等待资源初始化完成;
下面初始化文件服务的逻辑非常简单,只是创建了一个临时文件:
我们重点来看 check_resources() 函数,在其中初始化并校验了 MongoDB 连接以及 SnowFlake Id生成器;
资源相关的初始化都是在 resource 模块中完成的;
resource 模块的入口 mod.rs 中定义了资源的校验函数:
resource/mod.rs
MongoDB 通过 Ping 校验了数据库连接,而 SnowFlake 通过创建了一个 Id 校验了正确性;
那么这些资源是在哪里初始化的呢?
主要是通过 lazy_static 在首次使用的时候初始化的!
lazy_static 的一个特性是:在首次使用这个变量的时候,才会进行静态初始化;
下面分别来看:
src/resource/mongo.rs
上面的代码在 lazy_static! 宏中,异步初始化了 MongoDB 的连接:
首先,从环境变量中获取配置 MONGODB_URI,随后进行了初始化,并保存至变量:MONGO_CLIENT 中;
src/resource/id_generator.rs
与上面的初始化类似,这里从环境变量中获取:SNOWFLAKE_MACHINE_ID 和 SNOWFLAKE_NODE_ID,随后使用 SnowflakeIdBucket::new 进行了初始化;
同时,和 MongoDB 不同的是,这里需要使用 Mutex 进行封装,因为极有可能多个出现多个线程并发获取Id;
而 MongoDB 的 Client 已经是:Arc
我们也封装了 get_id 函数,直接供外部调用,而无需暴露 ID_GENERATOR_BUCKET 变量!
最下面是一个单测,用于测试我们的 Id 生成器;
至此,我们的资源初始化完成。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !