2024-03-04 快速入門(mén)rust

環(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è)試


image.png

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)行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是 Docker 概述 和虛擬機(jī)一樣,容器技術(shù)也是一種資源隔離的虛擬化技術(shù)。 2000 年的時(shí)候 FreeBS...
    索倫x閱讀 1,855評(píng)論 0 8
  • 環(huán)境管理 管理 Python 版本和環(huán)境的工具 p:非常簡(jiǎn)單的交互式 python 版本管理工具。 pyenv:簡(jiǎn)...
    璃沫仙人閱讀 528評(píng)論 0 0
  • 基本概念及操作 常用快捷鍵 常用通配符 所有的手冊(cè)頁(yè)遵循一個(gè)常見(jiàn)的布局,為了通過(guò)簡(jiǎn)單的 ASCII 文本展示而被優(yōu)...
    Jachin111閱讀 279評(píng)論 0 1
  • 新手入門(mén) 讓我們來(lái)創(chuàng)建第一個(gè)Rocket應(yīng)用并運(yùn)行它。首先確認(rèn)我們安裝了適當(dāng)?shù)腞ust版本,然后創(chuàng)建一個(gè)依賴 Ro...
    江河弦音閱讀 10,226評(píng)論 2 5
  • 在Java世界工作了10年之后,我最近更認(rèn)真地看待Rust。我?guī)缀鯖](méi)有開(kāi)始Rust編程(即,我是一個(gè)完整的新手),...
    FrederickLei閱讀 8,326評(píng)論 0 9

友情鏈接更多精彩內(nèi)容