RustでPHPビルトインサーバ用のリバースプロキシを書いてみました

kamasu

名前は kamasu です。 RustをPHPのビルトインサーバの前段にカマして並列に処理したい、という目的で書きました。 HTTPSで接続を受けて、通信することも可能です。

       +--------------------+     +----------------------------------------+
       | kamasu(main proc)  | - - |                                        |-+
       |                    | +-->|           php built-in server          | |-+
 HTTP  |    +--------+ HTTP | |+->| (child proc via std::process::Command) | | |
----------->| thread |--------+|  +----------------------------------------+ | |
       |    | (http) |      |  |    +----------------------------------------+ |
       |    +--------+      |  |      +----------------------------------------+
       |                    |  |                     :
 HTTPS |    +--------+ HTTP |  |                     : N procs
----------->| thread |---------+                     :
       |    | (https)|      |
       |    +--------+      |
       +--------------------+

使い方

 $ cargo install --force --git https://github.com/hhatto/kamasu.git
 $ kamasu -S 127.0.0.1:8080

-S -t -c あたりは php コマンドと同じ引数を指定すれば、バインドアドレス、 ドキュメントルート、php.iniファイル(またはディレクトリ)を指定して起動することができます。

-s オプションにアドレスを渡すことでHTTPSのプロキシとして動作させることができます。

軽くベンチマーク

 $ php -S 127.0.0.1:8000 -t ./docroot
 $ ab -n 1000 -c 10 http://127.0.0.1:8000/
         :
 Concurrency Level:      10
 Time taken for tests:   14.320 seconds
 Complete requests:      1000
 Failed requests:        0
 Total transferred:      229000 bytes
 HTML transferred:       96000 bytes
 Requests per second:    69.83 [#/sec] (mean)
 Time per request:       143.200 [ms] (mean)
 Time per request:       14.320 [ms] (mean, across all concurrent requests)
 Transfer rate:          15.62 [Kbytes/sec] received
         :

 $ kamasu -S 127.0.0.1:8000 -t ./docroot
 $ ab -n 1000 -c 10 http://127.0.0.1:8000/
         :
 Concurrency Level:      10
 Time taken for tests:   7.825 seconds
 Complete requests:      1000
 Failed requests:        0
 Total transferred:      305000 bytes
 HTML transferred:       107000 bytes
 Requests per second:    127.79 [#/sec] (mean)
 Time per request:       78.255 [ms] (mean)
 Time per request:       7.825 [ms] (mean, across all concurrent requests)
 Transfer rate:          38.06 [Kbytes/sec] received
         :
 $

モチベーション

手元の開発環境だとPHPのビルトインサーバを使っていて、 ちょっと並列で動かしたいなという場面がでてきたので、 Tokio のサンプルにちょうどいいと思い実装してみました。

アイディア自体は以下のQiita記事を読んで、思い立った次第です。ありがたい。

その他

バイナリのリリースについては、以下を参考にさせていただきました。ありがたい。

GitHubのreleasesページ からバージョンごとのバイナリをダウンロードして使い始めることができます。 今の所x86_64なLinux/macOS環境向けのみ提供しています。

よければ使ってみてください。ではまた

peg-rstを書きました

公開してから日が空いてしまったのですが、 少し前にCのreStructuredTextパーサであるところの peg-rst をリリースしました。

「今までなかった情報は英語で記事を書く」みたいなことを言っておきながら、 英語書くの億劫だしなぁとか思ってたら日が経ってしまいました。 書かないぐらいならせめて日本語で書こうってことで、今キーボードを叩いてます。

以前、GoのreStructuredTextパーサ gorst を書いて、今もメンテナンスしていますが、 もともとCのMarkdownパーサからGoのMarkdownパーサに移植したものをベースにつくったので、 reStructuredTextでGoからCにまた移植できるかなぁと妄想しつつやっと手をつけた感じです。

まだまだバグは多いですが、細々とメンテナンスしていきたいなと思います。

バグ報告でもよいので、気軽に使ってフィードバックいただけるとありがたいです。

goremanを拡張してみた

foreman クローンであるところの goreman 便利ですよね。 よく使っています。

若干バッドノウハウな気もしますが、 コマンドの起動順序を制御したり、少し遅らせてコマンドを実行したい時があります。 以前は起動コマンドに sleep を挟んだりして対応していたのですが、 最近の変更(#41)で exec 経由でコマンドを実行するようになったため、 このワザが使えなくなってしまいました。

 web1: sleep 2.5; go run web.go
 web2: sleep 3.5; go run web.go

拡張する

起動順と起動までの時間を制御するためにforkして独自拡張を追加してみました。

https://github.com/hhatto/goreman

Procfileの記法は プロセス名: 実行コマンド のような形で作成するのですが、 プロセス名: の間に () 内に設定を記載できるようにしました。

具体的には以下の様な感じです。

オリジナルのProcfile

 web1: plackup --port $PORT
 web2: plackup --port $PORT
 web3: bundle exec ruby web.rb
 web4: go run web.go -a :$PORT

拡張後のProcfile

 web1: plackup --port $PORT
 web2(delay=1000): plackup --port $PORT
 web3(priority=2): bundle exec ruby web.rb
 web4(delay=2500,priority=-2): go run web.go -a :$PORT

インストールして使う。

 $ go get -u github.com/hhatto/goreman
 $ goreman start

今の所便利に使えています。 もちろんオリジナルのProcfile記法でもそのまま動きます。

[2017.07.14追記]

プロセスを終了する際のシグナルをしていできるようにしました。 goremanはデフォルトで SIGHUP でプロセス終了させるのですが、 redis-serverSIGHUP を無視しているので、他のシグナルで終了させたいなと。 sig=XXX のように指定できます。

Magick++ (GraphicsMagick) problems when using drawing text with DrawableFont() on macOS

Lifelog 2017.03

Backpack

Older Blog Posts