Rust | Web フレームワーク Axum で REST API を作る
はじめに
Rust で Web アプリケーションを作成し render.com で公開してみたので、記事にまとめてみたいと思います。
Web フレームワークは Axum 、DBには MongoDB を採用しています。
Axum は公式の examples が充実していますが、検索してもなかなか実装例などをの情報がヒットしません。
また、 Rust と MongoDB の参考記事も少なく、苦労しました。
この記事や拙いソースコードが、少しでも誰かのお役に立てられれば幸いです!!!
作成したWebアプリケーション
mountix API
作成したのは、山の情報を取得できる REST API です。
運営するブログに LP を作成してあるので、気になる方はご覧ください。
使い方などを紹介していますので、
Postman、Insomnia 等のHTTPクライアントツールで遊んでいただけると嬉しいです😁
APIのドキュメント も公開しています。
Github
ソースコード一式です。
将来、Rust で実務経験を積みたいエンジニアが開発を進めています笑
小出しに実装例を見るよりも伝わりやすい部分もあるかと思いますので、のっけておきます。
技術スタック
Axum
tokio チーム製の Web サーバーを実装するためのクレートです。
actix-web を採用するか迷いましたが、今回は Axum を採用しました。
Axum の特徴を簡単に挙げておきます。
- 非同期ランタイムに tokio が使われているため、tokio のバージョン管理から解放されること
- マクロレスで実装されていること
MongoDB
データベースには MongoDB を採用しました。
ドライバーは MongoDB 公式の mongodb クレートを使用しました。
また、MongoDB を採用した理由は以下です。
- Geospatial queries があり、地理空間検索が容易に実装できること
- GET のエンドポイントのみを提供する REST API であり、特にデータの整合性に注意する必要もなくため、RDSであるメリットがないこと
-
tokio-runtime
を選択できること - MongoDB Atlas を利用すれば、低コストで運用できること
アーキテクチャ
レイヤードアーキテクチャ
レイヤードアーキテクチャでの実装については、以下の記事をとても参考にさせていただきました。
@helloyuki_さんは「実践 Rustプログラミング入門」の著者です。
ぜひチェックしてみてください!
実装おけるポイント
1. Axum
Router と nest
Router を定義して、.nest()
でネストさせることができます。
パスパラメータとクエリパラメータ
ハンドラの引数に Path や Query を渡すことで値を受け取ることができます。
serde の Deserialize が実装された構造体であれば、axum が裏で良しなに変換してくれます。
2. mongodb
ドキュメントの構造体を定義しておく
ドキュメントを表す構造体を定義し Deserialise を実装して collection
で型指定しておけば、serde が良しなに変換してくれます。
検索時の Filter Document を動的に生成する
この実装例が見当たらず、苦労しました。
doc!
マクロを使えば、Document そのものは簡単に生成できます。
クエリパラメータで受け取った name
、prefecture
、tag
があれば、条件に追加するといった処理になっています。
Geospatial queries を使用する
$nearSphere
は中心点の座標とそこからの距離(m)を引数で渡して、その範囲に存在するドキュメントを取得できます。
$near
と $nearSphere
がありますが、距離の計算が平面か球体の違いがあります。
$box
は長方形の地理空間上に存在するドキュメントを取得できます。
[[左下隅の経度, 左下隅の緯度], [右上隅の経度, 右上隅の緯度]]
の形式で指定します。
mongodbクレートの使い方はブログでも紹介しているので、良ければチェックしてください!
- MongoDBのドキュメントを検索する – find / find_one
- MongoDBのドキュメントを”_id”で検索する – find_one
- MongoDBにドキュメントを登録する – insert_one / insert_many
3. render.com
Heroku の無料プランが廃止されることとなりました。
無料枠狙いnの方々は、render.com に流れていくのではないでしょうか。
Rust で実装した Web アプリケーションを手軽に公開できる、良い選択肢だと思います。
ただ、やってみた系の記事もまだまだ少ないのが現状です。
Rust のデプロイ方法の参考記事を探すのにも苦労しました。
HOST と PORT を環境変数で管理できるように
render.comにデプロイする際、以下の制約があります。
-
HOST
は0.0.0.0
-
PORT
は環境変数で受け取れるようにする
そのため、HOST
・PORT
どちらも環境変数で管理できるようにしておくと良いかと思います。
ローカルでのデバック時には 127.0.0.1:8080
で起動していますが、
render.comの .env
では HOST=0.0.0.0を
定義し、PORT
は未定義にしてあります。
Health check 用のエンドポイントを実装しておく
今回、一番ハマったポイントかもしれません。
よく読めば、すんなり解決できたはずなのですが...笑
render.com で Rust の Web アプリケーションをデプロイする際、特に注意する点はありません。
以下のようにコマンド設定するだけで基本的にはOKなはずです。
- Build Command:
$ cargo build --release
- Start Command:
$ cargo run --release
ただし、私の場合は Health Check Pathを変更する必要がありました。(デフォルトは /
)
理由は、Health Check Path をネストさせており、ルート URL にアクセスすると404が返るためです。
Start Command 実行後にこの Health Check Path にリクエストが投げられ、200 OK
のレスポンスが返るとデプロイ成功となるようです。
デプロイ時のログを見ていると、成功応答があるまで数分間、404エラーが出続けていました笑
ちなみに、200 OK
を返せと書いてありますが、204 No Content
でも問題ありませんでした。
おそらくですが、200番台の成功応答が返ればよいと思われます。(試してはないです)
その他・所感
デプロイ時間
無料プランで稼働させているので、デプロイに10分弱かかります。
初回のデプロイはキャッシュが効かないので、もう少し時間がかかった記憶があります。
短くしたい場合は、有料プランを検討した方が良いでしょう!
.env の管理が簡単
管理画面に Secret Files という設定項目があり、.env
という名前でファイルを作成可能です。
もちろん、環境変数を個別に設定することも可能です。
.env
で管理する環境変数が多い場合は非常に便利だなと感じました。
ファイル名は自由に設定できるので、.env
以外の設定ファイルをバージョン管理下に置かずに管理する場合も、活用できる機能だと思います。
カスタムドメイン
カスタムドメインについては、設定はとても簡単でした。
render.com で Web Service を公開すると、https://{your-app-name}.onrender.com
というURLが発行されます。
お名前.com などの DNS レコード設定で、CNAME
を {your-app-name}.onrender.com
で登録すればOKです。
まとめ
エラーハンドリングやマイグレーション、テストコードなど課題がまだまだあるので、今後も開発を進めていきたいと思います。
また、render.com は便利ですが、
実務で扱うとなるとAWSにはなるかなと思うので ECS で動かせるくらいにはしたいです。
AWSでの常時稼働はお財布と相談ですね...
ひと段落したら、次は MongoDB/mongodb を PostgreSQL/sqlx あたりに置き換えて、別の Web アプリなんかも開発したいです。
Discussion