最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在Rust?web服務(wù)中使用Redis的方法

 更新時間:2022年08月31日 14:27:09   作者:coding到燈火闌珊  
這篇文章主要介紹了在Rust?web服務(wù)中使用Redis,在這篇文章中,我們將演示如何在一個Rust?web應(yīng)用程序中使用Redis,需要的朋友可以參考下

Redis一直是網(wǎng)絡(luò)生態(tài)系統(tǒng)的重要組成部分,它經(jīng)常用作緩存、消息代理或簡單地用作數(shù)據(jù)存儲。

在這篇文章中,我們將演示如何在一個Rust web應(yīng)用程序中使用Redis。

我們將探索兩種種使用Redis的方法:

  • 使用同步連接池

  • 使用異步連接池

對于同步池,我們使用基于r2d2庫的r2d2-redis。我們在異步解決方案中使用mobc,還有許多其他異步連接池,如deadpool和bb8,它們都以類似的方式工作。

話不多說,讓我們開始吧!

新建一個項目:

cargo new rust-redis-web-example

在Cargo.toml中加入依賴:

[dependencies]</code>
<code>tokio = { version = "1.19", features = ["full"] }</code>
<code>warp = "0.3.2"</code>
<code>redis = "0.21"</code>
<code>r2d2_redis = "0.14"</code>
<code>mobc-redis = "0.7"</code>
<code>mobc = "0.7"</code>
<code>thiserror = "1.0"

首先,讓我們設(shè)置一些共享類型,在main.rs中:

type WebResult= std::result::Result;</code>
<code>type Result= std::result::Result;</code>
<code>const REDIS_CON_STRING: &str = "redis://127.0.0.1/";

定義這兩個Result類型是為了節(jié)省一些輸入,并表示內(nèi)部Errors (Result)和外部Errors (WebResult)。

接下來,定義這個內(nèi)部error類型并為其實現(xiàn)Reject,以便它可以處理從程序返回的HTTP錯誤。

#[derive(Error, Debug)]</code>
<code>pub enum Error {</code>
<code>    #[error("mobc error: {0}")]</code>
<code>    MobcError(#[from] MobcError),</code>
<code>    #[error("r2d2 error: {0}")]</code>
<code>    R2D2Error(#[from] R2D2Error),</code>
<code>}</code>
<code>#[derive(Error, Debug)]</code>
<code>pub enum MobcError {</code>
<code>    #[error("could not get redis connection from pool : {0}")]</code>
<code>    RedisPoolError(mobc::Error),</code>
<code>    #[error("error parsing string from redis result: {0}")]</code>
<code>    RedisTypeError(mobc_redis::redis::RedisError),</code>
<code>    #[error("error executing redis command: {0}")]</code>
<code>    RedisCMDError(mobc_redis::redis::RedisError),</code>
<code>    #[error("error creating Redis client: {0}")]</code>
<code>    RedisClientError(mobc_redis::redis::RedisError),</code>
<code>}</code>
<code>#[derive(Error, Debug)]</code>
<code>pub enum R2D2Error {</code>
<code>    #[error("could not get redis connection from pool : {0}")]</code>
<code>    RedisPoolError(r2d2_redis::r2d2::Error),</code>
<code>    #[error("error parsing string from redis result: {0}")]</code>
<code>    RedisTypeError(r2d2_redis::redis::RedisError),</code>
<code>    #[error("error executing redis command: {0}")]</code>
<code>    RedisCMDError(r2d2_redis::redis::RedisError),</code>
<code>    #[error("error creating Redis client: {0}")]</code>
<code>    RedisClientError(r2d2_redis::redis::RedisError),</code>
<code>}</code>
<code>impl warp::reject::Reject for Error {}

上面定義了通用的錯誤類型和我們將實現(xiàn)的每一種使用Redis方法的錯誤類型。錯誤本身只是處理連接、池的創(chuàng)建和命令執(zhí)行等 錯誤。

使用r2d2(同步)

r2d2 crate是第一個被廣泛使用的連接池,它現(xiàn)在仍然被廣泛使用。Redis的連接池是r2d2-redis crate。

在src目錄下創(chuàng)建r2d2_pool.rs文件,因為我們現(xiàn)在使用的是連接池,所以這個池的創(chuàng)建也需要在r2d2模塊中處理。

use crate::{R2D2Error::*, Result, REDIS_CON_STRING};</code>
<code>use r2d2_redis::redis::{Commands, FromRedisValue};</code>
<code>use r2d2_redis::{r2d2, RedisConnectionManager};</code>
<code>use std::time::Duration;</code>
<code>pub type R2D2Pool = r2d2::Pool;</code>
<code>pub type R2D2Con = r2d2::PooledConnection;</code>
<code>const CACHE_POOL_MAX_OPEN: u32 = 16;</code>
<code>const CACHE_POOL_MIN_IDLE: u32 = 8;</code>
<code>const CACHE_POOL_TIMEOUT_SECONDS: u64 = 1;</code>
<code>const CACHE_POOL_EXPIRE_SECONDS: u64 = 60;</code>
<code>pub fn connect() -> Result> {</code>
<code>    let manager = RedisConnectionManager::new(REDIS_CON_STRING).map_err(RedisClientError)?;</code>
<code>    r2d2::Pool::builder()</code>
<code>        .max_size(CACHE_POOL_MAX_OPEN)</code>
<code>        .max_lifetime(Some(Duration::from_secs(CACHE_POOL_EXPIRE_SECONDS)))</code>
<code>        .min_idle(Some(CACHE_POOL_MIN_IDLE))</code>
<code>        .build(manager)</code>
<code>        .map_err(|e| RedisPoolError(e).into())</code>
<code>}

定義一些常量來配置池,如打開和空閑連接,連接超時和連接的生命周期,池本身是使用RedisConnectionManager創(chuàng)建的,傳遞給它的參數(shù)是redis連接字符串。

不要太擔心配置值,大多數(shù)連接池都有一些缺省值,這些缺省值將適用于基本應(yīng)用程序。

我們需要一種方法來獲得連接池,然后向Redis設(shè)置和獲取值。

pub fn get_con(pool: &R2D2Pool) -> Result{</code>
<code>    pool.get_timeout(Duration::from_secs(CACHE_POOL_TIMEOUT_SECONDS))</code>
<code>        .map_err(|e| {</code>
<code>            eprintln!("error connecting to redis: {}", e);</code>
<code>            RedisPoolError(e).into()</code>
<code>        })</code>
<code>}</code>
<code>pub fn set_str(pool: &R2D2Pool, key: &str, value: &str, ttl_seconds: usize) -> Result<()> {</code>
<code>    let mut con = get_con(&pool)?;</code>
<code>    con.set(key, value).map_err(RedisCMDError)?;</code>
<code>    if ttl_seconds > 0 {</code>
<code>        con.expire(key, ttl_seconds).map_err(RedisCMDError)?;</code>
<code>    }</code>
<code>    Ok(())</code>
<code>}</code>
<code>pub fn get_str(pool: &R2D2Pool, key: &str) -> Result{</code>
<code>    let mut con = get_con(&pool)?;</code>
<code>    let value = con.get(key).map_err(RedisCMDError)?;</code>
<code>    FromRedisValue::from_redis_value(&value).map_err(|e| RedisTypeError(e).into())</code>
<code>}

我們嘗試從池中獲取連接,并配置超時時間。在set_str和get_str中,每次調(diào)用這些函數(shù)時都會調(diào)用get_con。

使用mobc(異步)

在src目錄下創(chuàng)建r2d2_pool.rs文件,讓我們定義配置并創(chuàng)建連接池。

use crate::{MobcError::*, Result, REDIS_CON_STRING};</code>
<code>use mobc::{Connection, Pool};</code>
<code>use mobc_redis::redis::{AsyncCommands, FromRedisValue};</code>
<code>use mobc_redis::{redis, RedisConnectionManager};</code>
<code>use std::time::Duration;</code>
<code>pub type MobcPool = Pool;</code>
<code>pub type MobcCon = Connection;</code>
<code>const CACHE_POOL_MAX_OPEN: u64 = 16;</code>
<code>const CACHE_POOL_MAX_IDLE: u64 = 8;</code>
<code>const CACHE_POOL_TIMEOUT_SECONDS: u64 = 1;</code>
<code>const CACHE_POOL_EXPIRE_SECONDS: u64 = 60;</code>
<code>pub async fn connect() -> Result{</code>
<code>    let client = redis::Client::open(REDIS_CON_STRING).map_err(RedisClientError)?;</code>
<code>    let manager = RedisConnectionManager::new(client);</code>
<code>    Ok(Pool::builder()</code>
<code>        .get_timeout(Some(Duration::from_secs(CACHE_POOL_TIMEOUT_SECONDS)))</code>
<code>        .max_open(CACHE_POOL_MAX_OPEN)</code>
<code>        .max_idle(CACHE_POOL_MAX_IDLE)</code>
<code>        .max_lifetime(Some(Duration::from_secs(CACHE_POOL_EXPIRE_SECONDS)))</code>
<code>        .build(manager))</code>
<code>}

這和r2d2非常相似,這不是巧合;許多連接池庫都從r2d2出色的API中獲得了靈感。

async fn get_con(pool: &MobcPool) -> Result{</code>
<code>    pool.get().await.map_err(|e| {</code>
<code>        eprintln!("error connecting to redis: {}", e);</code>
<code>        RedisPoolError(e).into()</code>
<code>    })</code>
<code>}</code>
<code>pub async fn set_str(pool: &MobcPool, key: &str, value: &str, ttl_seconds: usize) -> Result<()> {</code>
<code>    let mut con = get_con(&pool).await?;</code>
<code>    con.set(key, value).await.map_err(RedisCMDError)?;</code>
<code>    if ttl_seconds > 0 {</code>
<code>        con.expire(key, ttl_seconds).await.map_err(RedisCMDError)?;</code>
<code>    }</code>
<code>    Ok(())</code>
<code>}</code>
<code>pub async fn get_str(pool: &MobcPool, key: &str) -> Result{</code>
<code>    let mut con = get_con(&pool).await?;</code>
<code>    let value = con.get(key).await.map_err(RedisCMDError)?;</code>
<code>    FromRedisValue::from_redis_value(&value).map_err(|e| RedisTypeError(e).into())</code>
<code>}

現(xiàn)在看起來應(yīng)該很熟悉了,傳入池并在開始時獲取連接,但這一次采用異步方式,使用async和await。

下一步就是把它們結(jié)合到一個warp web應(yīng)用中,修改main.rs:

use std::convert::Infallible;</code>
<code>use mobc_pool::MobcPool;</code>
<code>use r2d2_pool::R2D2Pool;</code>
<code>use thiserror::Error;</code>
<code>use warp::{Rejection, Filter, Reply};</code>
<code>mod r2d2_pool;</code>
<code>mod mobc_pool;</code>
<code>type WebResult= std::result::Result;</code>
<code>type Result= std::result::Result;</code>
<code>const REDIS_CON_STRING: &str = "redis://127.0.0.1/";</code>
<code>#[tokio::main]</code>
<code>async fn main() {</code>
<code>    let mobc_pool = mobc_pool::connect().await.expect("can create mobc pool");</code>
<code>    let r2d2_pool = r2d2_pool::connect().expect("can create r2d2 pool");</code>
<code>    let mobc_route = warp::path!("mobc")</code>
<code>        .and(with_mobc_pool(mobc_pool.clone()))</code>
<code>        .and_then(mobc_handler);</code>
<code>    let r2d2_route = warp::path!("r2d2")</code>
<code>        .and(with_r2d2_pool(r2d2_pool.clone()))</code>
<code>        .and_then(r2d2_handler);</code>
<code>    let routes = mobc_route.or(r2d2_route);</code>
<code>    warp::serve(routes).run(([0, 0, 0, 0], 8080)).await;</code>
<code>}</code>
<code>fn with_mobc_pool(</code>
<code>    pool: MobcPool,</code>
<code>) -> impl Filter+ Clone {</code>
<code>    warp::any().map(move || pool.clone())</code>
<code>}</code>
<code>fn with_r2d2_pool(</code>
<code>    pool: R2D2Pool,</code>
<code>) -> impl Filter+ Clone {</code>
<code>    warp::any().map(move || pool.clone())</code>
<code>}</code>
<code>async fn mobc_handler(pool: MobcPool) -> WebResult{</code>
<code>    mobc_pool::set_str(&pool, "mobc_hello", "mobc_world", 60)</code>
<code>        .await</code>
<code>        .map_err(|e| warp::reject::custom(e))?;</code>
<code>    let value = mobc_pool::get_str(&pool, "mobc_hello")</code>
<code>        .await</code>
<code>        .map_err(|e| warp::reject::custom(e))?;</code>
<code>    Ok(value)</code>
<code>}</code>
<code>async fn r2d2_handler(pool: R2D2Pool) -> WebResult{</code>
<code>    r2d2_pool::set_str(&pool, "r2d2_hello", "r2d2_world", 60)</code>
<code>        .map_err(|e| warp::reject::custom(e))?;</code>
<code>    let value = r2d2_pool::get_str(&pool, "r2d2_hello").map_err(|e| warp::reject::custom(e))?;</code>
<code>    Ok(value)</code>
<code>}

用Docker啟動一個本地Redis實例:

docker run -p 6379:6379 redis

接下來,運行 cargo run。

使用curl測試:

curl http://localhost:8080/r2d2</code>
<code>curl http://localhost:8080/mobc

到此這篇關(guān)于在Rust web服務(wù)中使用Redis的文章就介紹到這了,更多相關(guān)Rust 使用Redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Rust版本號的使用方法詳解

    Rust版本號的使用方法詳解

    在 Rust 項目中,版本號的使用遵循語義版本控制(Semantic Versioning)原則,確保版本號的變化能準確反映代碼的變更情況,本文給大家詳細解釋了Rust版本號用法,需要的朋友可以參考下
    2024-01-01
  • Rust中的Enum與Struct示例詳解

    Rust中的Enum與Struct示例詳解

    在 Rust 中,struct(結(jié)構(gòu)體)和enum(枚舉)是兩種核心的自定義類型,分別用于組合相關(guān)數(shù)據(jù)和表示互斥的可能性,這篇文章主要介紹了Rust中的Enum與Struct示例,需要的朋友可以參考下
    2025-10-10
  • Go調(diào)用Rust方法及外部函數(shù)接口前置

    Go調(diào)用Rust方法及外部函數(shù)接口前置

    這篇文章主要為大家介紹了Go調(diào)用Rust方法及外部函數(shù)接口前置示例實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • rust 中的 EBNF簡介舉例

    rust 中的 EBNF簡介舉例

    這篇文章主要介紹了rust 中的 EBNF簡介舉例,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • 如何使用Rust直接編譯單個的Solidity合約

    如何使用Rust直接編譯單個的Solidity合約

    本文介紹了如何使用Rust語言直接編譯Solidity智能合約,特別適用于沒有外部依賴或flatten后的合約,一般情況下,Solidity開發(fā)者使用Hardhat或Foundry框架,本文給大家介紹如何使用Rust直接編譯單個的Solidity合約,感興趣的朋友一起看看吧
    2024-09-09
  • 使用環(huán)境變量實現(xiàn)Rust程序中的不區(qū)分大小寫搜索方式

    使用環(huán)境變量實現(xiàn)Rust程序中的不區(qū)分大小寫搜索方式

    本文介紹了如何在Rust中實現(xiàn)不區(qū)分大小寫的搜索功能,并通過測試驅(qū)動開發(fā)(TDD)方法逐步實現(xiàn)該功能,通過修改運行函數(shù)和獲取環(huán)境變量,程序可以根據(jù)環(huán)境變量控制搜索模式
    2025-02-02
  • Rust使用lettre實現(xiàn)郵件發(fā)送功能

    Rust使用lettre實現(xiàn)郵件發(fā)送功能

    這篇文章主要為大家詳細介紹了Rust如何使用lettre實現(xiàn)郵件發(fā)送功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-11-11
  • Rust中字符串類型&str和String的使用

    Rust中字符串類型&str和String的使用

    在Rust中,字符串是一種非常重要的數(shù)據(jù)類型,&str和String是Rust中兩種主要的字符串類型,本文主要介紹了Rust中字符串類型&str和String的使用,感興趣的可以了解一下
    2024-03-03
  • Rust如何進行模塊化開發(fā)技巧分享

    Rust如何進行模塊化開發(fā)技巧分享

    Rust模塊化,模塊化有助于代碼的管理和層次邏輯的清晰,本文主要介紹了Rust如何進行模塊化開發(fā),結(jié)合實例代碼給大家講解的非常詳細,需要的朋友可以參考下
    2023-01-01
  • Rust CLI 項目構(gòu)建的實現(xiàn)步驟

    Rust CLI 項目構(gòu)建的實現(xiàn)步驟

    本文提供了一個完整的Rust CLI項目構(gòu)建流程,以 anthropic-config 配置管理工具為例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-12-12

最新評論

凌云县| 济宁市| 团风县| 陆河县| 大同县| 台南市| 长垣县| 南皮县| 哈密市| 乐清市| 昭平县| 广水市| 张掖市| 吉木萨尔县| 广元市| 留坝县| 沙雅县| 科技| 聊城市| 叙永县| 洛南县| 海淀区| 莱州市| 区。| 正镶白旗| 方正县| 武定县| 内江市| 盐城市| 石嘴山市| 两当县| 芒康县| 海阳市| 伊宁县| 上杭县| 武清区| 大足县| 四子王旗| 开鲁县| 潍坊市| 休宁县|