前言
本后端項目用到的技術棧主要包括:
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::LogTrait,這也是為什么我們能將該類型的變量設置為Logger的原因!
在log::LogTrait 的實現中,我們簡單定義了日志的輸出格式以及輸出顏色;
可以看到有了很多第三方庫的支持,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 生成器;
至此,我們的資源初始化完成。
審核編輯:劉清
-
生成器
+關注
關注
7文章
313瀏覽量
20977 -
rust語言
+關注
關注
0文章
57瀏覽量
3006 -
mongodb
+關注
關注
0文章
22瀏覽量
362
原文標題:用Actix寫的一個類似于Facemash的小項目總結
文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論