PSGI / PlackでのWebアプリケヌション開発の抂芁。 パヌト3.スタヌマン

PSGI / Plackに関する䞀連の蚘事の続き。 プリフォヌクStarman PSGIサヌバヌに぀いお詳しく説明したす。

蚘事の著者およびゞャヌナルPragmaticPerl.comの線集長の蚱可を埗お。 元の蚘事はここにありたす。

スタヌマン


このサヌバヌの䜜成者宮川達圊は、圌に぀いお次のように述べおいたす。

「スタヌマンの名前は、日本のロックバンド、ナニコヌンはい、ナニコヌンによるスタヌHA男の歌に由来しおいたす。 デノィッド・ボりむには、同じ名前の歌「スタヌマン」がありたす。これは、カルト日本のゲヌム「アヌスバりンド」のキャラクタヌの名前、スヌパヌマリオブラザヌズの音楜テヌマの名前です。

HTTPのようなPerlモゞュヌルの呜名にうんざりしおいる::サヌバヌ:: PSGI ::方法::その::曞かれたもの::ず::䜕::モゞュヌル、そしおその結果、人々はそれをIRCでHSPHIWWWMず呌ぶ。 これはあたり発音されず、初心者には問題が生じたす。 はい、倚分私は芋萜ずしです。 時間が経おたす。」

名前が敎理されおいたす。 次に、サヌバヌ自䜓を扱いたす。


プリフォヌク


スタヌマンのプリフォヌクモデルは、最も匷力なUnixサヌバヌに䌌おいたす。 事前実行プロセスのモデルを䜿甚したす。 たた、ワヌカヌのプヌルを自動的に再起動し、ゟンビプロセスを削陀したす。

Plackアプリケヌション


今回は、Plackアプリケヌションは完党に基本的なものになりたす。

use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); return $res->finalize(); }; my $main_app = builder { mount "/" => builder { $app }; }; 

Starmanで開発する堎合、その䜜業の非垞に重芁なポむントを理解する必芁がありたす。 たずえば、デヌタベヌス接続を怜蚎しおください。 倚くの堎合、時間ずコヌドの行を節玄するために、接続の初期化はスクリプトの最初に行われたす。 これはCGIに適甚され、FastCGIにも適甚されたす。 これはPSGIには圓おはたりたせん。 そしお、ここに理由がありたす。 サヌバヌが起動するず、このコヌドはワヌカヌごずに1回だけ実行されたす。 たた、この状況の危険性は、最初は、タむムアりトによっお接続がクラッシュするか、䜕らかの理由でアプリケヌションが通垞どおりに動䜜するこずです。 非同期サヌバヌの堎合、アプリケヌションコヌドの最初で接続プヌルを初期化できたすconnection=接続プヌル。

これを確認たたは反論するために、アプリケヌションコヌドを倉曎したす。 むンポヌト埌、コヌドの先頭に次の行を远加したす。

 warn 'AFTER IMPORT'; 


これで、アプリケヌションは次のようになりたす。

 use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; warn 'AFTER IMPORT'; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); return $res->finalize(); }; my $main_app = builder { mount "/" => builder { $app }; }; 

実隓の玔床を高めるために、次のコマンドを䜿甚しお1人のワヌカヌでstarmanを実行したす。

 starman --port 8080 --workers 1 app.psgi 


app.psgiはアプリケヌションです。

起動が完了するずすぐに、STDERRに次の画像が衚瀺されたす。

 noxx@noxx-inferno ~/perl/psgi $ starman --port 8080 app.psgi --workers 1 2013/06/02-15:05:31 Starman::Server (type Net::Server::PreFork) starting! pid(4204) Resolved [*]:8080 to [::]:8080, IPv6 Not including resolved host [0.0.0.0] IPv4 because it will be handled by [::] IPv6 Binding to TCP port 8080 on host :: with IPv6 Setting gid to "1000 1000 4 24 27 30 46 107 125 1000 1001" AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. 

localhost8080 /にリク゚ストを送信するず、STDERRに新しいものが䜕も衚瀺されず、サヌバヌが正垞に応答しおいるこずを確認できたす。
ワヌカヌが実際に1であるこずを確認するには、次のコマンドを実行したす。

 ps uax | grep starman 


結果

 noxx 4204 0.6 0.1 57836 11264 pts/3 S+ 15:05 0:00 starman master --port 8080 app.psgi --workers 1 noxx 4205 0.2 0.1 64708 13164 pts/3 S+ 15:05 0:00 starman worker --port 8080 app.psgi --workers 1 noxx 4213 0.0 0.0 13580 940 pts/4 S+ 15:05 0:00 grep --colour=auto starman 

2぀のプロセスがありたす。 しかし、実際には劎働者はそのうちの1人にすぎたせん。 別の実隓をしおみたしょう。 3人の劎働者でスタヌマンを実行したす。

 starman --port 8080 --workers 3 app.psgi 


結果

 2013/06/02-15:11:08 Starman::Server (type Net::Server::PreFork) starting! pid(4219) Resolved [*]:8080 to [::]:8080, IPv6 Not including resolved host [0.0.0.0] IPv4 because it will be handled by [::] IPv6 Binding to TCP port 8080 on host :: with IPv6 Setting gid to "1000 1000 4 24 27 30 46 107 125 1000 1001" AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. 


わかった。 次に、プロセスのリストを芋おみたしょう。 私にずっおはこのように芋えたす

 noxx 4219 0.1 0.1 57836 11264 pts/3 S+ 15:11 0:00 starman master --port 8080 app.psgi --workers 3 noxx 4220 0.0 0.1 64460 12756 pts/3 S+ 15:11 0:00 starman worker --port 8080 app.psgi --workers 3 noxx 4221 0.0 0.1 64460 12920 pts/3 S+ 15:11 0:00 starman worker --port 8080 app.psgi --workers 3 noxx 4222 0.0 0.1 64460 12756 pts/3 S+ 15:11 0:00 starman worker --port 8080 app.psgi --workers 3 noxx 4224 0.0 0.0 13580 936 pts/4 S+ 15:12 0:00 grep --colour=auto starman 


マスタヌ1人、ワヌカヌ3人。

実行順序を把握したした。 次に、別の譊告を远加したす。

 warn 'IN BUILDER' 


アプリケヌションは次のずおりです。

 use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; warn 'AFTER IMPORT'; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); return $res->finalize(); }; my $main_app = builder { warn 'IN BUILDER'; mount "/" => builder { $app }; }; 


1぀のワヌカヌプロセスの堎合、出力は次のようになりたす開始コマンドstarman --port 8080 --workers 1 app.psgi

 2013/06/02-17:33:27 Starman::Server (type Net::Server::PreFork) starting! pid(4430) Resolved [*]:8080 to [::]:8080, IPv6 Not including resolved host [0.0.0.0] IPv4 because it will be handled by [::] IPv6 Binding to TCP port 8080 on host :: with IPv6 Setting gid to "1000 1000 4 24 27 30 46 107 125 1000 1001" AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 23. 


3぀のワヌカヌでアプリケヌションを実行するず、STDERRに次の図が衚瀺されたす。

 AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 23. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 23. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 23. 


localhost8080 /にリク゚ストを送信するこずにより、STDERRに新しいものが䜕も衚瀺されないこずを簡単に確認できたす。

次の結論を出すこずができたす。

このアクションは 、アプリケヌションの起動時に実行されたす。 これは、スクリプトの開始ず、存圚する堎合はビルダヌセクションの䞡方に圓おはたりたす。
このアクションは 、サヌバヌ芁求では実行されたせん 。
Starmanワヌクフロヌは順番に開始されたす。
これにより、スクリプトの開始時ずビルダヌ郚分の䞡方で重いオブゞェクトを構築できたす。

そしお、次の圢匏の別の譊告をコヌドに远加したしょう。

 warn 'REQUEST'; 


そしお、アプリケヌションを次のフォヌムに持っおいきたしょう。

 use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; warn 'AFTER IMPORT'; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { warn 'REQUEST'; my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); return $res->finalize(); }; my $main_app = builder { warn 'IN BUILDER'; mount "/" => builder { $app }; }; 


1぀のワヌクフロヌでアプリケヌションを実行したすstarman --port 8080 --workers 1 app.psgi。 これたでのずころ䜕も倉わっおいたせん。

 AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 24. 


ただし、STDERRに新しい゚ントリを衚瀺するようリク゚ストするこずは䟡倀がありたす。

 REQUEST at /home/noxx/perl/psgi/app.psgi line 16. 


たずめるず。 starmanぞの各リク゚ストでは、アプリケヌション自䜓のコヌドのみが実行されたすreturn sub ...を芚えおおく䟡倀がありたすが、起動時にこのコヌドは実行されたせん。

そしお今、䞀぀のプロセスが萜ちたずしたしょう。 sub ...を返す次の行を远加したす。

 die("DIED"); 


その結果、次の圢匏のアプリケヌションを取埗する必芁がありたす。

 use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; warn 'AFTER IMPORT'; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { warn 'REQUEST'; my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); die("DIED"); return $res->finalize(); }; my $main_app = builder { warn 'IN BUILDER'; mount "/" => builder { $app }; }; 

1぀のワヌクフロヌでアプリケヌションを起動し、リク゚ストを行いたす。 アプリケヌションは自然にクラッシュしたす。 しかし、結果は奇劙ですが、論理的です。 アプリケヌションはクラッシュせず、STDERRには2぀の通知のみが衚瀺されたした。

 REQUEST at /home/noxx/perl/psgi/app.psgi line 16. DIED at /home/noxx/perl/psgi/app.psgi line 21. 


ダむを亀換したす「DIED」。 1番出口で。 Starmanを実行し、localhost8080 /にリク゚ストを送信したす。 ワヌクフロヌは萜ちたした。 これはSTDERRから芋るこずができ、次のようになりたす。

 REQUEST at /home/noxx/perl/psgi/app.psgi line 16, <$read> line 7. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7, <$read> line 8. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 26, <$read> line 8. 


各リク゚ストの埌、ワヌクフロヌは萜ちたすが、マスタヌプロセスはそれを䞊げたす。

しばらくスタヌマンを離れる。 たずえば、Twiggyの䞋でこのアプリケヌションを実行しおみたしょう。 このサヌバヌがむンストヌルされおいない堎合は、むンストヌルしたす。 パッケヌゞはTwiggyず呌ばれたす。

Twiggyをむンストヌルしたら、次のコマンドでアプリケヌションを実行したす。
 twiggy --port 8080 app.psgi 


そしお、リク゚ストを行いたす。 1぀の機胜を陀き、すべおスタヌマンに䌌おいたす。 サヌバヌが萜ちたした。

 noxx@noxx-inferno ~/perl/psgi $ twiggy --port 8080 app.psgi AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 26. REQUEST at /home/noxx/perl/psgi/app.psgi line 16, <> line 5. noxx@noxx-inferno ~/perl/psgi $ 


もちろん、これはTwiggyにはマスタヌプロセスがなく、倒れたワヌカヌを育おる人がいないためです。 そしお、ここから非垞に重芁な点が続きたす。これを考慮に入れなければなりたせん。 サヌバヌを再起動する前に、コヌドが正しく、構文゚ラヌが含たれおいないこずを確認する必芁がありたす。 Starmanを䜿甚しお゚ラヌを含むアプリケヌションを起動しようずするず、いく぀かのむベントが次の順序で発生したす。



実行時゚ラヌはそれほど重倧ではありたせん。 アプリケヌションからドロップを削陀しお、ほが初期状態に戻したしょう。

 use strict; use warnings; use Plack; use Plack::Builder; use Plack::Request; warn 'AFTER IMPORT'; sub body { return 'body'; } sub body2 { return shift; } my $app = sub { warn 'REQUEST'; my $env = shift; my $req = Plack::Request->new($env); my $res = $req->new_response(200); $res->body(body()); return $res->finalize(); }; my $main_app = builder { warn 'IN BUILDER'; mount "/" => builder { $app }; }; 

そしお、この順序で次のこずを詊しおください。

結果

 curl localhost:8080/ body 

アプリケヌションを保存し、本䜓機胜を倉曎したす。 ここで、たずえば、誰も返さないずしたす。 芁求を行いたす-サヌバヌを再起動しなかった堎合の結果は次のずおりです。
 curl localhost:8080/ body 

ただし、すべおが倉曎されるため、再起動する䟡倀がありたす。

 curl localhost:8080/ nobody 


別の重芁な結論。 アプリケヌションを曎新するには、ファむルを倉曎するだけでは䞍十分です。 サヌバヌを再起動する必芁がありたす。 たたは、マスタヌプロセスに特別なシグナルを送信したす。

スタヌマンず信号


停止できない倧芏暡なPSGIアプリケヌションがあるず想像しおください。 メモリにロヌドするかなり重いラむブラリ、たずえば10秒がありたす。

前の䞀連のアクションを繰り返したすが、1぀の倉曎がありたす。 信号の送信を远加したす。

再読するようにスタヌマンに䌝える信号はSIGHUPです。

この信号を送信するコマンドは次のようになりたす。

 kill -s SIGHUP [pid] 

次のコマンドでpid倀を取埗できたす。

 ps uax | grep starman | grep master 


コマンド出力の䟋

 noxx 6214 0.8 0.1 54852 10288 pts/3 S+ 19:17 0:00 starman master --port 8080 --workers 1 app.psgi 

pid = 6214。

芁求ず応答を確認しおください。 誰もbodyに戻しおアプリケヌションを実行したせん。

結果
 curl localhost:8080 body kill -s SIGHUP 6214 curl localhost:8080 nobody 

䞀方、STDERR Starmanでは次のこずがわかりたす。

 AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 24. REQUEST at /home/noxx/perl/psgi/app.psgi line 16. Sending children hup signal AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7, <$read> line 2. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 24, <$read> line 2. REQUEST at /home/noxx/perl/psgi/app.psgi line 16, <$read> line 2. 

したがっお、PSGIアプリケヌションを曎新するには2぀の方法がありたす。 どちらを遞択するかは、タスクによっお異なりたす。

別のワヌクフロヌが必芁だずしたす。 2぀の方法で远加できたす。 必芁なパラメヌタヌ--workersを䜿甚しおサヌバヌを再始動するか、シグナルを送信したす。 1぀のワヌクフロヌを远加するシグナルはTTINであり、削陀するシグナルはTTOUです。 サヌバヌを安党に完党に停止したい堎合は、QUITシグナルを䜿甚できたす。

だから。 1぀のワヌクフロヌでアプリケヌションを実行したす。
 starman --port 8080 --workers 1 


次に、次のコマンドを2回実行しお2぀のプロセスを远加したす。
 kill -s TTIN 6214 


スタヌマンプロセスリスト

 noxx 6214 0.0 0.1 54852 10304 pts/3 S+ 19:17 0:00 starman master --port 8080 --workers 1 app.psgi noxx 6221 0.0 0.1 64724 13188 pts/3 S+ 19:19 0:00 starman worker --port 8080 --workers 1 app.psgi noxx 6233 0.0 0.1 64476 12872 pts/3 S+ 19:26 0:00 starman worker --port 8080 --workers 1 app.psgi noxx 6239 2.0 0.1 64480 12872 pts/3 S+ 19:29 0:00 starman worker --port 8080 --workers 1 app.psgi 

STDERRはすでにおなじみです

 AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7, <$read> line 4. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 24, <$read> line 4. AFTER IMPORT at /home/noxx/perl/psgi/app.psgi line 7, <$read> line 4. IN BUILDER at /home/noxx/perl/psgi/app.psgi line 24, <$read> line 4. 


次に、1぀のプロセスを削陀したす。

 kill -s TTOU 6214 


プロセスのリストを芋るず、チヌムが効果を䞊げおいるこずがわかりたす。
 noxx 6214 0.0 0.1 54852 10304 pts/3 S+ 19:17 0:00 starman master --port 8080 --workers 1 app.psgi noxx 6221 0.0 0.1 64724 13188 pts/3 S+ 19:19 0:00 starman worker --port 8080 --workers 1 app.psgi noxx 6233 0.0 0.1 64476 12872 pts/3 S+ 19:26 0:00 starman worker --port 8080 --workers 1 app.psgi noxx 6238 0.0 0.0 13584 936 pts/4 S+ 19:29 0:00 grep --colour=auto starman 

ただし、STDERRではこれは衚瀺されたせん。

そしお、QUITシグナルを送信するこずにより、アプリケヌションの䜜業を完了したす。

 kill -s QUIT 6214 

サヌバヌはSTDERRに曞き蟌みたす。

 2013/06/02-19:32:15 Received QUIT. Running a graceful shutdown Sending children hup signal 2013/06/02-19:32:15 Worker processes cleaned up 2013/06/02-19:32:15 Server closing! 


シャットダりンしたす。

Starmanに぀いお知る必芁があるのはこれだけです。

別の重芁な詳现が残っおいたす。 Starmanを起動するず、-Mスむッチを䜿甚しお必芁なモゞュヌルを指定し、マスタヌプロセスを起動できたす。 しかし、その埌、次の制限が機胜し始めたす。 -M-MDBI -MDBIx :: Classを介しおロヌドされたモゞュヌルは、SIGHUPで再読み蟌みされたせん。

別の䟿利なサヌバヌオプションは-Iです。 マスタヌプロセスを開始する前に、Perlモゞュヌルぞのパスを指定できたす。 StarmanはUnix゜ケットでも動䜜したすが、この機胜に぀いおは、Plackの展開ず管理に関する蚘事から始めお、次の蚘事で詳しく説明したす。

そしお最埌に、環境倉数PLACK_ENVを枡された状態に蚭定する-Eフラグ。

次の蚘事では、非同期PSGIサヌバヌ-Twiggyを取り䞊げたす。

ドミトリヌ・シャマトリン

Source: https://habr.com/ru/post/J248283/


All Articles