![](https://habrastorage.org/storage/074d55cb/60ab54be/a663de18/f66763d3.png)
背景
客観的および主観的な状況のため、PHPはMegaplanのサーバープログラミングの言語として使用されます。 時間が経つにつれて、PHPの制限のいくつかに制約され悩まされ始め、マルチスレッド、遅延開始、メッセージキューなどの「高度な」機能を見逃し始めました。 さらに、MegaplanはSaaSアプリケーションであるだけでなく、サーバーWindows、Linux、FreeBSDの3種類のOS向けのクロスプラットフォームボックス版の形で提供されるため、各問題に対するカスタムソリューションの使用に制限があります。 別のカスタムコンポーネントを追加すると(クロスプラットフォームソリューションが見つかった場合でも)、ボックスのインストールとサポートが大幅に複雑になります。 Windowsに通常の標準的なcrondがないことさえも迷惑です。一般に、PHPを「ポンプ」する必要があります。 もちろん、代替の根本的な解決策があります-Javaに移行することですが、私たちにとってこれは選択肢ではありません-数年以内に多くの悪くないコードがすでに書かれています。 さらに、JVMが大規模な彗星の問題をエレガントに解決できるかどうかはわかりません。 はい。PHPを削除するのは時期尚早です。PHPは(少なくともロシアでは)Web開発で最も人気のある言語であり、プログラマーを見つけるのは他の言語よりも簡単です。
熟したニーズと、ある瞬間に目を引き、熟した問題を解決するというアイランが本当に好きだったという事実により、Erlang仮想マシンを標準環境に統合し、この関数型言語のユニークな機能でPHPの欠陥を補います。
まず、「純粋な」PHPの助けを借りてどのタスクが困難で、どの機能が欠けているかについて説明し、次に提案されたソリューションについて説明します。 だから...
問題
この記事では、PHPで長時間実行されるプロセスは非常に信頼性の低い松葉杖であるという事実から進めます。 PHP 5.3に通常のガベージコレクターがあるように思えても、それは期待できません。 多くの人が好むがlibeventに結び付けられているPhpDaemonは納得できないため、Windowsでは動作しません。 現時点では、PHPプログラムを「悪魔化」する通常のネイティブな、そして最も重要な、信頼できる方法はありません。 また、 FastCGIに切り替えようとしても、このエコノミーを介して定期的にプロセスを再開するディスパッチャーが必要です。 要するに、私の意見では、PHPの唯一のプロダクションモードは、従来のFastCGI(またはUNIXライクなシステムではapache + prefork + mod_php)だけです。議論されるほとんどすべての制限は、この状況に関連しています。
バックグラウンドでの起動
PHPで「Hello World!」以上のことを書いた多くの開発者は、ユーザーのアクションに応じて電子メールを送信するという最も基本的なタスクなど、起動が遅れるという問題に直面しています。 PHPでは、このタスクに2つのソリューションがあります(両方ともい):
- または、同じスクリプト内でインタラクティブモードですぐに直接メールを送信し、メールサービスの速度低下とアクセス不能に陥る危険を冒してください。
- または、送信タスクをどこかに書き留めて、1分間に1回、cronでこれらのタスクをスクープするスクリプトを引き出します。
彗星
もちろん、ロングポーリングやWebソケットなどの新しい機能はすべて純粋なPHPで実行できますが、接続ごとに長時間実行されるphpプロセスが必要です。 膨大な数の顧客リソースに対して、このような贅沢を十分に得ることはできません。
後ろの行で、カップル用のApacheでマルチスレッド(ワーカー)mod_phpについて示唆している人がいます。 皆さん、本番環境でスレッドセーフなphpを使用しないでください。これは間違っています。 さらに、非常に深刻な負荷では、これでも保存されません。そして、クライアントとサーバーの間に共通のイベントスペースが必要です。 さて、この話を想像してください:サーバーがイベントをトリガーします:
<?php
Event::publish( 'common.users.onlinecountchanged', array('count' => 10) );
?>
:
Event.subscribe( 'common.users.onlinecountchanged', function(data) {
$('#onlinecount').html(data.count);
} );
, web-jabber-, .
cron
Cron- PHP-, cron' :
- .
- PHP- , , - .
,
- PHP-,
- ,
- PHP , ,
- cron, , PHP-.
(message queue)
— . , , , . , « » .
, , .
, PHP , , Erlang.
Erlang?
- Erlang , . . .
- GPL- , .
- — Comet'.
- Erlang' AMQP — RabbitMQ.
- , , .
, .
![](https://habrastorage.org/storage/392eac2e/815aea21/61a0d5a2/d44aa2bc.png)
:
- Nginx , «Nginx — , ?!». , , , , Erlang' , . .
- Mochiweb . -, Erlang', — .
- FastCGI, PHP-, , , «» AMQP (, ), — , .
— RabbitMQ
— , . « » , .
AMQP. , . , : . , PHP: , .
(pub-sub)
RabbitMQ pub-sub . , PHP , - . PHP ( PECL AMQP):
<?php
// RabbitMQ
$cnn = new AMQPConnection();
$cnn->connect();
// ,
$ex = new AMQPExchange( $cnn );
$ex->declare( 'event-exchange', AMQP_EX_TYPE_TOPIC );
//
$ex->publish( 'message', 'some.object.event' );
?>
, - Erlang',
some.object.event
REST:
http://example.com/example-action
. Erlang, , ( -PHP, ):
//
amqp_declare_exchange( 'event-exchange', AMQP_EX_TYPE_TOPIC );
amqp_declare_queue( 'external-app-queue' );
//
amqp_bind( 'external-app-queue', 'event-exchange', 'some.object.*' );
//
amqp_subscribe( 'external-app-queue' );
// ,
while ( 1 )
{
$msg = receive_message();
file_get_contents( "http://example.com/example-action?msg=$msg" );
}
, PHP-
event-exchange
some.object.event
, ,
external-app-queue
,
some.object.event
, . , , Erlang-, , callback' ( — REST- HTTP).
, :)
FastCGI
FastCGI- Erlang'? - . , php-fpm Windows, , , , , . - PHP, LAMP.
, , , .
- Comet
- Erlang' — (long-polling) — Erlang' . , comet -, .
Comet , , Erlang-- -, long-polling , http- push- . :
- Javascript- , .
- Erlang-, RabbitMQ , . , , .
- PHP- RabbitMQ, comet-, .
- , . push-.
- callback push- .
- Push- ( long-polling).
, , , , : , . :
- HTTP-REST API. .
- PHP- ( Erlang'), «» AMQP .
Cron
Erlang. , . , , . Erlang' , , , (. ), . , AMQP, REST API .
, cron', , , ( , - ), , PHP (, ), , , PHP-.
, :), , :
- - PHP.
- PHP .
- - real-time .
- Erlang'.
? Welcome!