はじめに
Rust で Web アプリケーションを作成し render.com で公開してみたので、記事にまとめてみたいと思います。
Web フレームワークは Axum 、DBには MongoDB を採用しました。
Axum は公式の examples が充実していますが、検索してもなかなか実装例などをの情報がヒットしません。
また、 Rust と MongoDB の参考記事も少なく、苦労しました。
この記事や拙いソースコードが、少しでも誰かのお役に立てられれば幸いですー🥂
Web アプリケーション
mountix API
山岳一覧・百名山の情報を取得できる REST API を開発、公開してみました。
APIのドキュメント も公開しているので、Postman や Insomnia 等の HTTP クライアントツールで遊んでいただけると嬉しいです!
GitHub
GitHub でソースコードも公開しました。
小出しに実装例を見るよりも伝わりやすい部分もあるかと思いますので、のっけておきます。
エラーハンドリングまわりの実装が非常に雑です… もっと上手く実装できるはず。
今後、validator を使うようにリファクタ予定です。
技術スタック
Axum
tokio チーム製の Web サーバーを実装するためのクレートです。
Axum の特徴を簡単に挙げておきます。
- 非同期ランタイムに tokio が使われているため、tokio のバージョン管理から解放されること
- マクロレスで実装されていること
actix-web を採用するか迷いましたが、今回は Axum を採用しました。
MongoDB
データベースには MongoDB を採用し、ドライバーは MongoDB 公式の mongodb クレートを使用しました。
また、MongoDB を採用した理由は以下です。
- Geospatial queries があり、地理空間検索が容易に実装できること
- GET のエンドポイントのみを提供する REST API であり、特にデータの整合性に注意する必要もなくため、RDSであるメリットがないこと
tokio-runtime
を選択できること- MongoDB Atlas を利用すれば、低コストで運用できること
地理空間検索が容易に実装できること が個人的に大きかったです。
もちろん、低コストも嬉しいポイントですが🥳🥳
アーキテクチャ
レイヤードアーキテクチャ
レイヤードアーキテクチャでの実装については、以下の記事をとても参考にさせていただきました。
Axum での実装ポイント
Router と nest
Router を定義して、.nest()
でネストさせることができます。
パスパラメータとクエリパラメータ
ハンドラの引数に Path や Query を渡すことで値を受け取ることができます。
serde の Deserialize が実装された構造体であれば、axum が裏で良しなに変換してくれます。
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
render.com にデプロイする
Heroku の無料プランが廃止されてしまったので、今回は 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
は未定義にしてあります。
HOST=127.0.0.1
PORT=8080
HOST=0.0.0.0
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番台の成功応答が返ればよいと思われます。(試してはないです)
render.com を使った感想
.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です。
デプロイ時間が長い
無料プランで稼働させているので、デプロイに10分弱かかります。
初回のデプロイはキャッシュが効かないので、もう少し時間がかかった記憶があります。
短くしたい場合は、有料プランを検討した方が良いかもしれません。
まとめ
やはり、何かをつくって公開するのが一番勉強になる…
Rust を業務で使える機会を虎視眈々狙っているので、今後も Rust を触り倒したいと思います🫰🌟
P.S. お察しの通り、山を題材にしたのは 登山が趣味だからです⛰️🏔️
コメント