環(huán)境搭建
rust安裝
編輯器 rust插件安裝
環(huán)境變量配置
國(guó)內(nèi)源配置
demo
需求
1 搭建服務(wù),完成一個(gè)可以接受任何參數(shù)的post的方法
2 接入opensearch,將post收到的參數(shù)上傳的opensearch
3 將該demo做成docker運(yùn)行
步驟
1.使用cargo new xx --bin 創(chuàng)建新項(xiàng)目
2.編輯器打開(kāi)新項(xiàng)目 在Cargo.toml引入需要的包
[dependencies]
# rocket 接口相關(guān)
rocket = { version = "0.5.0", features = ["json"] }
# serde json序列化反序列化
serde = { version = "1.0", features = ["derive"] }
# opensearch 操作包
opensearch = { version = "2.0.0" }
# tokio 異步線程包
tokio = { version = "1.24.2", features = ["full"] }
# chrono 時(shí)間包
chrono = {version="0.4.23"}
3.編寫(xiě)代碼
#[launch]
fn rocket() -> Rocket<Build> {
let rt = Runtime::new().unwrap();
let client = rt.block_on(init_open_search()).expect("Failed to initialize OpenSearch");
rocket::build()
.manage(client)
.mount("/", routes![index])
.mount("/data", routes![create])
}
async fn init_open_search() -> Result<OpenSearch, Box<dyn std::error::Error>> {
let url = Url::parse("url")?;
let conn_pool = SingleNodeConnectionPool::new(url);
let transport = TransportBuilder::new(conn_pool)
.auth(Credentials::Basic("username".parse().unwrap(), "passwrod.".parse().unwrap()))
.build()?;
let client = OpenSearch::new(transport);
Ok(client)
}
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[post("/", format = "application/json", data = "<data>")]
async fn create(data: rocket::serde::json::Json<HashMap<String, Value>>, client: &State<OpenSearch>) -> String {
let params = data.0;
let _ = send_data(client, params.clone()).await;
format!("Received data: {:?}", params)
}
async fn send_data(client: &State<OpenSearch>, data: HashMap<String, Value>) -> Result<(), Box<dyn std::error::Error>> {
let log_data = LogData {
timestamp: chrono::offset::Utc::now().timestamp(),
data: data,
};
let response = client
.index(IndexParts::Index("test_stream_rust"))
.body(json!(log_data))
.send().await.expect("Failed to add OpenSearch");
println!("Successfully indexed a document {}", response.status_code());
Ok(())
}
#[derive(Serialize, Deserialize)]
struct LogData {
timestamp: i64,
data: HashMap<String, Value>,
}
4.docker build
ARG RUST_VERSION=1.76
ARG APP_NAME=opensearch-service
################################################################################
# Create a stage for building the application.
FROM rust:${RUST_VERSION} AS build
ARG APP_NAME
RUN USER=root cargo new --bin ${APP_NAME}
WORKDIR /app
COPY ./src ./src
COPY ./Cargo.toml ./Cargo.toml
RUN cargo build --release
RUN cp /app/target/release/${APP_NAME} /app/target/release/server
FROM debian:stable-slim
RUN apt-get update && apt-get install -y libssl3 && rm -rf /var/lib/apt/lists/*
# Copy the executable from the "build" stage.
COPY --from=build /app/target/release/server /usr/local/bin/server
# Configure rocket to listen on all interfaces.
ENV ROCKET_ADDRESS=0.0.0.0
# Expose the port that the application listens on.
EXPOSE 8000
# What the container should run when it is started.
CMD ["/usr/local/bin/server"]
5.測(cè)試
5.1 啟動(dòng)服務(wù)
docker build -t opensearch-service .
winpty docker run -p 8000:8000 -it --rm opensearch-service
5.2 調(diào)用接口
postman測(cè)試

5.3 驗(yàn)證數(shù)據(jù)
opensearch查看對(duì)應(yīng)indexs,看到內(nèi)容成功插入
6.總結(jié)
6.1 關(guān)于cargo中的features
你引用的包里還引用了別人的包,但是默認(rèn)是不自動(dòng)引入這些配置了features的包(即可選引用包), 通過(guò)features可以把對(duì)應(yīng)的包及功能引入
6.2 rocket中#[launch]可以在代碼中不加入main方法
6.3 tikio異步轉(zhuǎn)同步
opensearch的demo全是異步的,但是rocket使用同步,為了引入客戶端,將異步轉(zhuǎn)為同步
let rt = Runtime::new().unwrap();
let client = rt.block_on(init_open_search()).expect("Failed to initialize OpenSearch");
6.4 如何在rocket引入一個(gè)全局變量
rocket::build() .manage(client)
此處manage引入后,所有的api方法中都可以通過(guò)參數(shù)拿到這個(gè)client
6.5 關(guān)于json序列化
#[derive(Serialize, Deserialize)]
struct LogData {
timestamp: i64,
data: HashMap<String, Value>,
}
此處的log data 中不要直接引入別人的包中的對(duì)象,可能無(wú)法直接序列化,盡量用基礎(chǔ)類(lèi)。
6.6 docker打包問(wèn)題
一開(kāi)始用用docker init 構(gòu)建項(xiàng)目后 docker run直接報(bào)錯(cuò)找不到包。
排查方法
6.6.1 先注釋掉 dockerfile中最后一句 "CMD ["/usr/local/bin/server"]",再次運(yùn)行,找到對(duì)應(yīng)文件位置后發(fā)現(xiàn)打好的原生包是存在的,但是命令行運(yùn)行還是報(bào)錯(cuò)找不到包
6.6.2 內(nèi)核缺少依賴包
ldd filename 通過(guò)該命令發(fā)現(xiàn)內(nèi)核缺少依賴包
為了解決這個(gè)問(wèn)題,將運(yùn)行環(huán)境從alpine切換為debian:stable-slim,發(fā)現(xiàn)還是缺少rocket依賴的openssl3的包
加入命令RUN apt-get update && apt-get install -y libssl3 && rm -rf /var/lib/apt/lists/*
成功打包運(yùn)行