試しに actix サーバを IIS にデプロイしてみた話。
もとが perl cgi をリプレイスした方がいいんじゃないかという話だったのでちょっとだけ速度比較もしてみた。
細かい手順については様々な記事が存在しているのであまり深くは触れません。
概要
- HttpPlatformHandler でIISにデプロイする
- perl CGI よりもちょっと速い
HttpPlatformHandler
IIS でのバックエンドプログラムの実行方法は CGI とか FastCGI、
HttpPlatformHandler などがある。
.NET のプログラムだと .NET 用のモジュールを使うのが良さそうだが、その他の exe 形式のものを使う場合はこれが良さそう。
fastapi について調べた時はこれが推奨されていた。(参考)
rust についてもこれと同じ感じでデプロイできる。
デプロイの流れ
とりあえず流れと要点だけ。
- rust ソースをビルド
-
--release
オプションを適宜使う。
-
-
web.config
を作成-
web.config
は IIS にデプロイする際の設定ファイル - 詳細は後述
-
- IIS サーバにビルドしたファイルと
web.config
を配置- どこでも良いが、
C:\inetpub\wwwroot
がよくある置き場所
- どこでも良いが、
- IIS にアプリケーションを追加
- 物理パスは 3 で配置した場所
- URL 構成とかは適宜設定する
- 実行権限の付与
- 3 のフォルダについて、
IIS_IUSRS
に実行権限を付与する - perl や python で exe が別フォルダにあるときはそちらにも権限をつける
- 3 のフォルダについて、
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="PythonHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="C:\inetpub\wwwroot\<実行ファイルのパス>"
arguments=""
stdoutLogEnabled="true"
stdoutLogFile="<ログファイルのパス>"
startupTimeLimit="60"
processesPerApplication="1">
<environmentVariables>
<environmentVariable name="SERVER_PORT" value="%HTTP_PLATFORM_PORT%" />
<environmentVariable name="BASE_PATH" value="/actix" />
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>
BASE_PATH
はアプリケーションの URL のベースパス。環境変数で渡す形にしてみた。
SERVER_PORT
の末尾に謎のスペースが入ったので、trim
してからパースした。
let port: u16 = std::env::var("SERVER_PORT")
.unwrap_or("8080".to_string())
.trim()
.parse()
.unwrap();
速度比較
perl cgi、rust で作った exe を cgi として実行したものと actix の exe を HttpPlatformHandler で実行したものを比較。
python のrequests でGETリクエストした時のレスポンスタイムを比較。
純粋な実行速度の比較というよりは、ネットワークを経由するときの諸々を比べる感じ。
コールドスタートを考慮して、10回リクエストした後に50回リクエストした平均をとっている。
が、今回はコールドスタートにならなかった。
テキストを返すだけ
単位は秒。小数点以下第五位で切り捨て。
perl | rust (cgi) | rust (actix) | |
---|---|---|---|
初回 | 0.0998 | 0.0944 | 0.0657 |
50回平均 | 0.1020 | 0.0915 | 0.0652 |
DB からデータを取得して返す
一つのテーブルの全データ (250Byte 程度) を返すだけのシンプルなクエリ。
単位は秒。小数点以下第五位で切り捨て。
perl | rust (cgi) | rust (actix) | |
---|---|---|---|
初回 | 0.3852 | 0.1809 | 0.1267 |
50回平均 | 0.3880 | 0.1964 | 0.1395 |
詰まったところのメモ
actix で postgres クレートを使ってDB接続する時に、非同期関数を呼び出せない場面があった。
rust cannot start a runtime from within a runtime
のエラー。
tokio の main がスレッドのロックか何かをしていることが原因の模様。tokio のイシューにもある。
actix の main が tokio::main
として動いている時に postgres クレートも tokio::main
として動こうとするので動けないっぽい。
こちらの記事を参考にweb::block
を使って解決。
感想
actix を HttpPlatformHandler で使うのが速いという結果になった。
cgi の方が exe を直接実行してそうで速いかもと思っていたので、ちょっと意外。
actix にはデバッグ用のプリント文が入っているがそれでも速い。
cgi だと標準出力を拾って整形してるっぽいので、その辺のオーバーヘッドかもしれない。
perl での DB 接続は、モジュールの都合かもしれないが遅い。
データ量が増えてくれば別の問題も出てきて速度に影響してくるかもしれない。
おわりに
mac から windows 向けのクロスコンパイルも実施できた。
windows + wsl のときにはうまくいかなかいことがあったのでちょっとうれしい。
perl と cgi にもちょっと詳しくなった()。
ついでに FastCGI とか python との比較も試そうと思ったのだが、実行時エラーになったので断念。