美文网首页
2024-03-04 快速入门rust

2024-03-04 快速入门rust

作者: 江江江123 | 来源:发表于2024-03-03 12:32 被阅读0次

    环境搭建

    rust安装
    编辑器 rust插件安装
    环境变量配置
    国内源配置

    demo

    需求

    1 搭建服务,完成一个可以接受任何参数的post的方法
    2 接入opensearch,将post收到的参数上传的opensearch
    3 将该demo做成docker运行

    步骤

    1.使用cargo new xx --bin 创建新项目
    2.编辑器打开新项目 在Cargo.toml引入需要的包

    [dependencies]
     # rocket 接口相关
    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 时间包
    chrono = {version="0.4.23"}
    

    3.编写代码

    #[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.测试
    5.1 启动服务

    docker build -t opensearch-service .
    winpty docker run -p 8000:8000 -it --rm opensearch-service
    

    5.2 调用接口
    postman测试


    image.png

    5.3 验证数据
    opensearch查看对应indexs,看到内容成功插入

    6.总结
    6.1 关于cargo中的features
    你引用的包里还引用了别人的包,但是默认是不自动引入这些配置了features的包(即可选引用包), 通过features可以把对应的包及功能引入
    6.2 rocket中#[launch]可以在代码中不加入main方法
    6.3 tikio异步转同步
    opensearch的demo全是异步的,但是rocket使用同步,为了引入客户端,将异步转为同步

     let rt = Runtime::new().unwrap();
     let client = rt.block_on(init_open_search()).expect("Failed to initialize OpenSearch");
    

    6.4 如何在rocket引入一个全局变量

     rocket::build() .manage(client)
    

    此处manage引入后,所有的api方法中都可以通过参数拿到这个client
    6.5 关于json序列化

    #[derive(Serialize, Deserialize)]
    struct LogData {
        timestamp: i64,
        data: HashMap<String, Value>,
    }
    

    此处的log data 中不要直接引入别人的包中的对象,可能无法直接序列化,尽量用基础类。
    6.6 docker打包问题
    一开始用用docker init 构建项目后 docker run直接报错找不到包。
    排查方法
    6.6.1 先注释掉 dockerfile中最后一句 "CMD ["/usr/local/bin/server"]",再次运行,找到对应文件位置后发现打好的原生包是存在的,但是命令行运行还是报错找不到包
    6.6.2 内核缺少依赖包
    ldd filename 通过该命令发现内核缺少依赖包
    为了解决这个问题,将运行环境从alpine切换为debian:stable-slim,发现还是缺少rocket依赖的openssl3的包
    加入命令RUN apt-get update && apt-get install -y libssl3 && rm -rf /var/lib/apt/lists/*
    成功打包运行

    相关文章

      网友评论

          本文标题:2024-03-04 快速入门rust

          本文链接:https://www.haomeiwen.com/subject/ihmkzdtx.html