C ++ Webアプリケーション、またはFastCGIデーモンを使いこなす

最近では、NodeJSなどのツールのおかげで、Webアプリケーションを作成することは何もありません。 5行のコードでバイナリ、jsパイルをダウンロードし、自慢できます。 Expressを接続してさらに5行追加すると、ルーティング、テンプレート、セッション、その他の機能を備えた本格的なWebアプリケーションが得られます。 とてもシンプルなので退屈です。 そして、それは私にとって興味深いものになりました。5年前に見たことがない私の古い友人C ++との関係はどうですか。 かつて、ActionScriptやその他のJavaScriptが私を誘惑し、何度も助けてくれた良き友人を完全に忘れていました。 Configurable Omnipotent Custom Applications Integrated Network Engine(Cocaineの略) に関する 最近の 記事に照らして、CocaineのHTTPインターフェイス機能に基づいたFastcgi Daemonというプロジェクトに出会いました。 そして、知り合いになる



Fastcgi Daemon-C ++での高負荷FastCGIアプリケーションを設計するためのYandexのオープンソースフレームワーク。



それは



Fastcgi Daemonは、Yandexで開発されたオープンソースフレームワークで、C ++で高負荷のFastCGIアプリケーションを作成するように設計されています。



残念ながら、これは公式リポジトリのREADMEにあります。

github.com/lmovsesjan/Fastcgi-Daemon/wiki/_pagesで詳細なドキュメントを入手できますが、完全な作業には不十分です。 たとえば、そこでのインストール全体には1行が必要です。



sudo apt-get install fastcgi-daemon2-init libfastcgi-daemon2-dev libfastcgi2-syslog
      
      





しかし、Ubuntuの公式リポジトリおよびその他(おそらく私は見栄えが悪い)で、これらのパッケージは見つかりませんでした。 この記事では、このツールのインストール、構成、および使用に関する調査を収集することにしました。 以下のすべてのソースと既製のdebファイルは、 github.com / nickalie / HelloFastCGIから入手できます。



設置



このプロジェクトはUbuntuでサポートされているため、以下のすべての操作は、Ubuntu 12.04 64ビットで最新の更新を適用して実行しました。

開始するには、必要なすべての依存関係をインストールします。 これを行うには、次のコマンドを使用します。



 sudo apt-get install -y build-essential git debhelper automake1.9 autotools-dev libboost-dev libboost-thread-dev libfcgi-dev libxml2-dev libboost-regex-dev libtool libssl-dev autoconf-archive
      
      





ここで、Fastcgi Daemonを使用してリポジトリのクローンを作成します。 ここでは、2つのオプションを選択できます。



最初のオプションを選択しました



 git clone https://github.com/golubtsov/Fastcgi-Daemon.git
      
      





新しくダウンロードしたプロジェクトがあるフォルダーに移動します。



 cd Fastcgi-Daemon
      
      





アセンブリを開始します



 dpkg-buildpackage -rfakeroot
      
      





出力は、親ディレクトリにあるdebファイルをインストールする準備ができています。 やる



 cd ..
      
      





そして



 sudo dpkg -i ./libfastcgi-daemon2-dev_2.10-13_amd64.deb \ ./libfastcgi-daemon2_2.10-13_amd64.deb \ ./fastcgi-daemon2-init_2.10-13_amd64.deb \ ./fastcgi-daemon2_2.10-13_amd64.deb \ ./libfastcgi2-syslog_2.10-13_amd64.deb
      
      





FastCGIと連携できるWebサーバーも必要です。 私は自分のニーズにnginxを使用していますが、ドキュメントでも同じことが推奨されています



 sudo apt-get install nginx
      
      





このWebサーバーの最新バージョンを使用する場合は、その前に



 sudo add-apt-repository ppa:nginx/stable && sudo apt-get update
      
      





これでインストールは終了です。 最初のアプリケーションに渡します。



アプリ



ファイルHelloFastCGI.cppを作成し、次のコードをそこに入れます。



 #include <fastcgi2/component.h> #include <fastcgi2/component_factory.h> #include <fastcgi2/handler.h> #include <fastcgi2/request.h> #include <iostream> #include <sstream> class HelloFastCGI : virtual public fastcgi::Component, virtual public fastcgi::Handler { public: HelloFastCGI(fastcgi::ComponentContext *context) : fastcgi::Component(context) { } virtual void onLoad() { } virtual void onUnload() { } virtual void handleRequest(fastcgi::Request *request, fastcgi::HandlerContext *context) { request->setContentType("text/plain"); std::stringbuf buffer("Hello " + (request->hasArg("name") ? request->getArg("name") : "stranger")); request->write(&buffer); } }; FCGIDAEMON_REGISTER_FACTORIES_BEGIN() FCGIDAEMON_ADD_DEFAULT_FACTORY("HelloFastCGIFactory", HelloFastCGI) FCGIDAEMON_REGISTER_FACTORIES_END()
      
      





最も関心のあるメソッドはhandleRequestです。 彼はリクエストを処理する人です。 このメソッドで何が起こるかをコードが理解することを願っていますが、念のために説明します。 リクエスト(POSTまたはGET)に「name」パラメーターがある場合、「Hello%name%」というテキストを出力します。それ以外の場合は「Hello stranger」を出力します。



fastcgi ::要求クラスは、要求と応答の両方を担当しますが、通常、この機能は、たとえば同じNodeJSのように、2つのクラスまたはオブジェクトに分割されます。

すぐに使用できるように、Cookieを操作したり、任意のHTTPステータス、ヘッダーなどを設定したりできます。一般に、WebサービスやWebアプリケーションの開発には紳士用キットを使用できます。 デフォルトでない限り、セッションは実装されていませんが、2つのカウントにねじ込まれています。 次回はこれについてお話します



羊に戻りましょう。 次に、このクラスを共有ライブラリにコンパイルする必要があります。



 g++ HelloFastCGI.cpp -O2 -fPIC -lfastcgi-daemon2 -shared -o libHelloFastCGI.so
      
      





次に、HelloFastCGI.conf構成ファイルを準備する必要があります(拡張子が「conf」であることが重要です)。



 <?xml version="1.0"?> <fastcgi xmlns:xi="http://www.w3.org/2001/XInclude"> <pools> <pool name="main" threads="1" queue="5000"/> </pools> <handlers> <handler pool="main" url="/hellofascgi"> <component name="HelloFastCGIComponent"/> </handler> </handlers> <components> <component name="HelloFastCGIComponent" type="MainModule:HelloFastCGIFactory"/> <component name="daemon-logger" type="logger:logger"> <level>INFO</level> <ident>hellofastcgi</ident> </component> </components> <modules> <module name="MainModule" path="./libHelloFastCGI.so"/> <module name="logger" path="/usr/lib/fastcgi2/fastcgi2-syslog.so"/> </modules> <daemon> <logger component="daemon-logger"/> <endpoint> <backlog>128</backlog> <socket>/tmp/fastcgi_daemon.sock</socket> <threads>1</threads> </endpoint> <pidfile>/var/run/fastcgi2/HelloFastCGI.pid</pidfile> <monitor_port>20012</monitor_port> </daemon> </fastcgi>
      
      







「/ hellofastcgi」( www.somedomain.com/hellofastcgiなど )に到達するリクエストのハンドラーがあります。 このハンドラーは、HelloFastCGIComponentコンポーネントであり、MainModuleモジュールにあります。 より正確には、HelloFastCGIFactoryファクトリーはモジュール内にあり、必要なコンポーネントを取得できます。 MainModuleは、最近コンパイルされたlibHelloFastCGI.soからリソースを引き出します。 また、「ソケット」タグの内容にも注意を払う価値があります。これは、Unixソケットにすぎません。これは、nginx設定ですぐに指定する必要があります。 「Pidfile」-FastCGI-Daemonを悪魔化するときに重要です。 その名前はconf-fileの名前と一致する必要があり、唯一の違いは拡張子にあります。 デーモンがstart / stop / restartを実行できるようにするには、pidが「/ var / run / fastcgi2 /」にある必要があります。



Webサーバーをセットアップするときが来ました。 新しくインストールしたnginxでこれをすべて行うので、それ以上苦労せずに、/ etc / nginx / sites-available / defaultをルールします。 内容はおよそ次のとおりです。



 server { listen 80; location / { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; fastcgi_pass unix:/tmp/fastcgi_daemon.sock; } }
      
      





nginxを再起動します



 sudo service nginx restart
      
      





アプリケーションを起動します



 fastcgi-daemon2 --config=HelloFastCGI.conf
      
      





すべてが正しく行われ、ブラウザでlocalhost / hellofastcgiを開くと、次のように表示されます。



 Hello stranger
      
      





引数localhost / hellofastcgi?を追加しますName = nick and get



 Hello nick
      
      





やれやれ! あなたもそうすることを願っています。



ただし、Fastcgi Daemonは通常のアプリケーションとしてコンソールで実行されるようになりました。 約束された悪魔はどこにありますか? これについては以下で説明します。



デーモンのセットアップ



幸いなことに、Fastcgi DaemonとDaemonは非常に簡単に悪魔化できます(トートロジーについては謝罪します)。



以前に作成したHelloFastCGI.confを取得し、libHelloFastCGI.soへの相対パスを絶対パスに置き換えて、/ etc / fastcgi2 / availableに配置します。



これで、通常の方法でデーモンを起動/停止/再起動できます。



 sudo service fascgi-daemon2 start/stop/restart <appname>/all
      
      





私たちの場合、それは



 sudo service fastcgi-daemon2 start HelloFastCGI
      
      





/ etc / fastcgi2 / availableで利用可能なすべてのアプリケーションを実行するには、キーワード「all」を使用します



 sudo service fastcgi-daemon2 start all
      
      





また、アプリケーションが予期せずクラッシュした場合、自動的に再起動することも重要です。



ベンチマーク



好奇心のために、Fastcgi DaemonとNodeJSのパフォーマンスを比較することにしました。 これを行うために、JSで同様のアプリケーションをスケッチしました。



 var http = require('http'); var url = require('url'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); var query = url.parse(req.url, true).query; res.end('Hello ' + (query.name ? query.name : 'stranger')); }).listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
      
      





実験の純度を高めるために、nginxでproxy_passを構成してノードで動作するようにしました。

Apacheベンチでテスト済み:



 ab -c 100 -n 20000 http://IPorURL/hellofastcgi?name=Nikolay
      
      





そして



 ab -c 100 -n 20000 http://IPorURL/?name=Nikolay
      
      





結果:



Fastcgiデーモン



 Concurrency Level: 100 Time taken for tests: 15.181 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Non-2xx responses: 20000 Total transferred: 6460000 bytes HTML transferred: 3440000 bytes Requests per second: 1317.45 [#/sec] (mean) Time per request: 75.904 [ms] (mean) Time per request: 0.759 [ms] (mean, across all concurrent requests) Transfer rate: 415.56 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.5 0 4 Processing: 12 75 31.2 68 474 Waiting: 9 73 31.4 66 471 Total: 12 76 31.3 68 475 Percentage of the requests served within a certain time (ms) 50% 68 66% 80 75% 85 80% 88 90% 96 95% 106 98% 114 99% 125 100% 475 (longest request)
      
      







NodeJS



 Concurrency Level: 100 Time taken for tests: 23.038 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 2700000 bytes HTML transferred: 260000 bytes Requests per second: 868.12 [#/sec] (mean) Time per request: 115.192 [ms] (mean) Time per request: 1.152 [ms] (mean, across all concurrent requests) Transfer rate: 114.45 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.6 0 52 Processing: 39 114 21.7 109 306 Waiting: 28 112 21.5 107 305 Total: 40 115 21.7 109 306 Percentage of the requests served within a certain time (ms) 50% 109 66% 117 75% 125 80% 130 90% 145 95% 155 98% 168 99% 186 100% 306 (longest request)
      
      





これはすべて、Core i7から1つのコアが割り当てられているVirtualBoxを中心に展開されていることに言及する価値があります。

その結果、Fastcgi Daemonのほうが半分の時間差がありましたが、これはNodeJSにとってそれほど悪くはないと思います。 これは、NodeJSのプロセッサ消費量が50%に達し、メモリ-最大45 MB(静止時5.6 MB)に過ぎないことです。 Fastcgi Daemonは、プロセッサの20%以下と9.5 MBのRAM(4.5 MBの静止時)しか消費しませんでした。 つまり、後者はリソースに対してより友好的であり、驚くことではありません。 比較が真空中で完全に球形であることが明らかになった。 良い方法では、より飽和したコードを実行し、データベースに接続し、両方のアプリケーションをマルチスレッドモードで実行する必要があります。 しかし、初心者にはこれで十分です。



結論の代わりに



私の意見では、非常に興味深いプロジェクトがYandexの腸から出てきました。 Fastcgi DaemonはC ++でのWebアプリケーションの作成を大幅に簡素化するという事実に加えて、既製のアプリケーションを便利に管理するために必要なinit.dスクリプトも含まれています。 次回は、セッション、データベース、およびテンプレートを使用したFastcgiデーモンに基づく承認用のサービスの作成について説明します。



All Articles