この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Introduction
Momentoは、クラウドネイティブな
高速のサーバーレスキャッシュサービスです。
キャッシュサーバの設定や準備は短時間(数分)で完了し、
キャッシュ最適化・スケール・管理も自動。
セキュリティもデフォルトでしっかりしています。(E2E暗号化や監査ログサポートなど)
公式サイトでは「世界最速」を謳っていますが、実際はどんな感じでしょうか。
今回はRustを使ってMomentoにアクセスしてみます。
Environment
- OS : MacOS 12.4
- rust : 1.61.0
M1 Macで動かしました。
AWSアカウントはセットアップ済みとします。
Setup
Momentoのセットアップは公式Githubや以前の記事などを参考におこなってください。
ここにあるように、
momento account signupで指定したメールアドレス宛にトークンが送付されているはずです。
このトークンはMomento CLIセットアップや
このあとプログラムからアクセスするために必要なので、確認しておきましょう。
momentoコマンドを実行してversionが表示できればOKです。
% momento --version
momento 0.20.1
そしてRustのインストール。
% curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
RustとCargoのコマンドが使えることを確認。
% rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.61.0 (fe5b13d68 2022-05-18)`
% cargo --version
cargo 1.61.0 (a028ae42f 2022-04-29)
Lambdaのビルド&デプロイを簡単にするため、Cargo Lambdaをインストールします。
% cargo install cargo-lambda
Introduce Momento Library
各種Momentoライブラリの使い方はシンプルです。
ここを参考に、
RustでMomentoライブラリを使う方法をみてみましょう。
Momentoライブラリは、
Cargo.tomlに下記依存ライブラリを追記するだけでOKです。
[dependencies]
momento = "0.6.0"
ちなみにここにあるサンプルの場合、
tokioも追加する必要があります。
RustでMomentoにアクセス
クライアントを作成するためにSimpleCacheClientBuilderを使います。
tokenとttlを指定してクライアントを作り、
create_cacheでキャッシュを作成します。
let auth_token = "your token";
let item_default_ttl_seconds = 300;
let mut cache_client = SimpleCacheClientBuilder::new(
auth_token,
NonZeroU64::new(item_default_ttl_seconds).unwrap(),
)
.unwrap()
.build();
let cache_name = String::from("your-cache-name");
match cache_client.create_cache(&cache_name).await {
Ok(_) => {
println!("create_cache OK!");
}
Err(err) => {
eprintln!("{}", err);
}
}
Rust用Momentoライブラリでは、キャッシュ関連操作はすべて非同期なので、
create_cache時にawaitを使います。
ちなみに、キャッシュを削除したいときは
cache_client.delete_cacheとすればOK。
作成したキャッシュに対してデータの保存/取得/削除をするのも簡単です。
クライアントの各種関数に、さきほど作ったキャッシュの参照と
データのkeyやvalueを渡します。
//キャッシュデータの保存
let key = String::from("my_key");
let value = String::from("my_value");
cache_client
.set(&cache_name, key.clone(), value.clone(), None)
.await
.unwrap();
//キャッシュデータの取得
cache_client
.get(&cache_name, key.clone())
.await
.unwrap();
//キャッシュデータの削除
cache_client
.delete(&cache_name, key.clone())
.await
.unwrap();
getは正常に処理が行われた場合、MomentoGetResponseを返します。
MomentoGetResponseはresult(キャッシュヒットしたか判定するenum)と
value(実際の値の&[u8])をもっています。
なので、例えば文字列をsetして、キャッシュからgetして使いたい場合は↓のようにします。
let result:MomentoGetResponse = cache_client.get(&cache_name, key.clone()).await.unwrap();
println!("{:?}",String::from_utf8(result.value).unwrap());
Create AWS Lambda on Rust
次は、AWS Lambda on RustでMomentoをつかってみましょう。
Lambdaでも、ローカルで動かすのと特に違いはありません。
まずはCargo Lambdaでプロジェクトの作成。
簡単に実行できるように、HTTP functionで作る。
% cargo lambda new momento-lambda
Is this function an HTTP function? <yes>
momento-lambda/Cargo.tomlに依存ライブラリを追加。
[dependencies]
・・・
quanta = "0.10.0"
momento = "0.6.0"
momento-lambda/src/main.rsにMomento関連の処理を追記します。
キャッシュをset/get/deleteして処理時間を計測し、それらをログに出力します。
use lambda_http::{run, service_fn, Error, IntoResponse, Request, RequestExt, Response};
use quanta::Clock;
use momento::response::cache_get_response::MomentoGetStatus;
use momento::simple_cache_client::SimpleCacheClientBuilder;
use std::num::NonZeroU64;
use std::process;
async fn function_handler(event: Request) -> Result<impl IntoResponse, Error> {
let clock = Clock::new();
const N:u32 = 1_000_000;
let start = clock.now();
let mut stop = start;
let auth_token = "<your Momento Token>".to_string();
let item_default_ttl_seconds = 60;
let mut cache_client = match SimpleCacheClientBuilder::new(
auth_token,
NonZeroU64::new(item_default_ttl_seconds).unwrap(),
) {
Ok(client) => client,
Err(err) => {
eprintln!("{}", err);
panic!("create cache_client error")
}
}
.build();
// Creating a cache named "cache"
let cache_name = String::from("cache");
match cache_client.create_cache(&cache_name).await {
Ok(_) => {
println!("create_cache OK!")
}
Err(err) => {
eprintln!("{}", err);
panic!("create_cache error")
}
}
// cache key
let key = String::from("my_key");
// cache value
let value = String::from("my_value");
println!("Setting key: {}, value: {}", key, value);
match cache_client
.set(&cache_name, key.clone(), value.clone(), None)
.await
{
Ok(_) => {}
Err(err) => {
eprintln!("{}", err);
}
};
//get cache value
match cache_client.get(&cache_name, key.clone()).await {
Ok(r) => match r.result {
MomentoGetStatus::HIT => println!("cache hit!"),
MomentoGetStatus::MISS => println!("cache miss"),
_ => println!("error occurred"),
},
Err(err) => {
eprintln!("{}", err);
}
};
// delete cache
match cache_client.delete_cache(&cache_name).await {
Ok(_) => {
println!("Permanently deleted cache named, {}", cache_name);
}
Err(err) => {
eprintln!("{}", err);
}
};
//Execution Time Measurement
stop = clock.now();
println!("quanta::clock::now() overhead = {:?}",stop.duration_since(start));
let resp = Response::builder()
.status(200)
.header("content-type", "text/html")
.body("Hello AWS Lambda HTTP request")
.map_err(Box::new)?;
Ok(resp)
}
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.without_time()
.init();
run(service_fn(function_handler)).await
}
ファイルが修正できたらビルド&デプロイ。
% cd momento-lambda
% cargo lambda build
% cargo lambda deploy --enable-function-url momento-lambda --iam-role <iamロールのArn>
? function arn: arn:aws:lambda:XXXXXXXXXXXXXXXXXXX
function url: https://somethingurl.lambda-url.us-east-1.on.aws/
Lambda実行後にログをみてみると、Momentoにアクセスできているのがわかります。
Summary
今回はサーバレスキャッシュサービスMomentoをRustから使ってみました。
セットアップも使い方も簡単ですし、Rust以外にも
JavaScript、Python、Java、Go、C#にライブラリが用意されています。
基本的な使い方は同じなので、お好みの環境で試してみてください。