ブロックキャッシングによるパフォーマンスの改善

ブロックキャッシュとssiの主題は、Habréで何度も取り上げられました。 以下に、ブロックキャッシングを使用した別の実装と、これらの原則を使用したフレームワークのソースコードを紹介します 。 そして、それがどのように機能するか-以下をお読みください。

ブロックキャッシュスキーム



MVCアプローチについて少し



このフレームワークは、「できるだけシンプルに」という原則に基づいています。 MVCパターンを使用してHTML出力のビルドの進行状況を見ると、プッシュとポーリングの2つのアプローチがあります。



最初のアプローチでは、フロントコントローラーは、モデルを実行する多数のコントローラーを呼び出し、Viewを使用して多数のブロックを形成します。これらのブロックは、Viewの前面で組み立てられます。



2番目のアプローチ-1つのViewテンプレートが処理されます。このテンプレートでは、対応するコントローラーを呼び出すコールバック関数があり、それらがHTMLブロックを形成します。 たとえば、このアプローチはZendFrameworkで使用されます。



この場合、最初のアプローチが使用されましたが、PHPスクリプトはアセンブリに関与せず、ssi(サーバー側インクルード)を介して直接WEBサーバー(nginx)に関与します。 SSIディレクティブが使用されます:includeおよびecho。 これにより、次のことが可能になります。 フレームワーク自体(ZFの4倍のパフォーマンスであるため、すぐに名前を付けました)はnginxと密接に統合されており、nginx configの一部はプロジェクトの直接の部分です。 ( 誰かがそれを好まない...味と色のコンパニオンはありません )このため、ディレクティブinclude /path/to/project/conf/local.nginx.confをnginx.confに含める必要があります

仕組みについて少し説明します



WEBの従来のMVCスキーム-各コントローラーは、URLの特定の部分に関連付けられています。 URL部分はアクションにバインドされ、部分はパラメーターにバインドされます。



上記のように、nginxはコントローラー機能の一部を引き継ぎます。 URL解決は、ロケーションディレクティブを使用して行われます。 コントローラー(ページ)、アクション(アクション)、およびパラメーターによってすべてを解決できます。 ただし、同じZFよりも柔軟性があります。 locationディレクティブにpageパラメーターを含めるようにしてください。その値によって適切なクラスが選択されます。 彼らは適切なブロックコントローラーを呼び出したと信じています。

設定の一部の例: set $app_script run_app.php;

. . .

location ~ ^/catalog/(\w+)/? {

fastcgi_pass localhost:9000;

fastcgi_param page catalog;

fastcgi_param cat_name $1;

include fastcgi_params;

}





set $app_script run_app.php;

. . .

location ~ ^/catalog/(\w+)/? {

fastcgi_pass localhost:9000;

fastcgi_param page catalog;

fastcgi_param cat_name $1;

include fastcgi_params;

}







この例は、fcgiパラメーターpage = catalogが渡され、cat_nameがURLの最後の部分と等しいことを示しています。 PHPスクリプトはrun_app.phpという名前になります。run_app.phpは、ページディレクトリからcatalogPageクラス(ロケーションページ/ catalogPage.php)をインスタンス化し、run()メソッドを実行します。 url / catalog / bmvの環境変数cat_nameでは、値はbmvになります。



SSIとの連携方法



場所によるタキシングは、外部と内部の2つの部分に分かれています。 外部-これは、書き換えを使用した適切なssiテンプレートの選択です。 内部はプライベートコントローラの場所です。



サンプルSSIテンプレート(index.tpl):

< script >

<!--# include virtual = "$js" -->

</ script >

< table >

< tr >

< td > left block

<!--#include virtual="$top" -->

</ td >

content

< td valign ="top" > content block < br >

<!--#include virtual="$int" -->

</ td >

</ tr >

</ table >



* This source code was highlighted with Source Code Highlighter .






設定の一部の例:
set $ int "/ssi$request_uri" ;

set $top "/ssi/top10$request_uri" ;

. . .

location /catalog {

set $js "js/catalog.js" ;

rewrite ^(.*)$ /index.tpl;

}



location /ssi {

internal ; # ,

location /ssi/catalog/(\w+)/? {

fastcgi_pass localhost:9000;

fastcgi_param page catalog;

fastcgi_param cat_name $1;

fastcgi_param ssi 1;

include fastcgi_params;

}



location /ssi/top10/(\w+)/? {

fastcgi_pass localhost:9000;

fastcgi_param page top10;

fastcgi_param top_name $1;

fastcgi_param ssi 1;

include fastcgi_params;

}

}



* This source code was highlighted with Source Code Highlighter .








最初の場所は、変数$ js = js / catalog.jsでindex.tplに書き換えられます

index.tplテンプレートでは、必要なjsスクリプトが置き換えられ、#include ssiディレクティブを使用して必要なブロックが呼び出されます。 この例では、内部の場所/ ssi / catalog /が機能し、PHP run_appスクリプトを呼び出します。このスクリプトは、catalogPageクラスをインスタンス化し、run()メソッドを実行し、同様にtop10ブロックを実行します。



memcachedの仕組み



写真を見てください。 ここではすべてが明確です。場所/ top10でアドレス指定する代わりに、場所/ mcで直接memekeshにアクセスします。 キャッシュが無効(空)の場合、ngx_memcache_moduleモジュールは404エラーを返します。 404エラーを処理し、指定された場所mcbへの内部リダイレクトを行います。 PHPスクリプトはHTMLを作成し、キャッシュに配置する必要があります。 これについてあまり心配する必要はありません。クラスでパラメーターを指定すると、基本クラスで発生します。

protected $ _Cached = true;

public $ CachingKey = '/ top_ $ top_name';



設定例:

location ~ ^/catalog/(\w+) {

rewrite ^(.*)$ /index.tpl;

set $memkey "top_$1" ;

}



location /mc {

set $memcached_key $memkey;

default_type text/html;

memcached_pass localhost:11211;

error_page 404 @mcb; // ,

//

}



location @mcb {

fastcgi_pass localhost:9000;

fastcgi_param page block;

fastcgi_param blocknum $blocknum;

include fastcgi_params;

}



* This source code was highlighted with Source Code Highlighter .








キャッシング機能:

php_memcache拡張機能を使用する場合、機能はありません。



ライブラリlibmemcachedおよびphp_memcachedが使用されている場合、コンテンツの圧縮はデフォルトで処理されます。

次のオプションが可能です。



謝辞



まず第一に、イゴール・シソエフsysoev.ruに感謝します。これがなければ、このコードと多くの高性能Runetプロジェクトはなかったでしょう。

また、ロケーションをフロントコントローラーとして使用するというアイデアを提供してくれたKonstantin Baryshnikov(fixxxer)にも感謝します。

Alexey Rybak(漁師)の彼の電撃戦に感謝します。これは私のプロジェクト、特にこのフレームワークで3年以上も積極的に使用しています。

さて、php-fpmの作者であるAndrei Nigmatulin氏(今夜)は、彼のプロジェクトでrunetのハイロードに大きく貢献しました。



PS。 何かがあなたのために始まっていない場合、それは問題ではありません。 それは別の時に判明します、主なことは心を失うことではありません。 それまでの間、一休みしてHabrを読んでください。



All Articles