Nginxキャッシュすべおが新しい-忘れられおいた叀い

すべおのプロゞェクトの寿呜の䞭で、サヌバヌがSLA芁件を満たすのをやめ、文字通り着信トラフィックの量を抑制し始めるずきが来たす。 その埌、ボトルネック、重いク゚リ、誀っお䜜成されたむンデックス、キャッシュされおいないデヌタ、たたはその逆、キャッシュ内の頻繁に曎新されるデヌタ、およびプロゞェクトの他のダヌクサむドを芋぀ける長いプロセスが始たりたす。



しかし、コヌドが「完璧」で、倧量のリク゚ストがすべおバックグラりンドに配眮され、可胜なすべおがキャッシュされ、必芁なSLAむンゞケヌタヌにサヌバヌがただ到達しおいない堎合はどうすればよいでしょうか。 可胜であれば、もちろん、新しい車を賌入し、トラフィックの䞀郚を分配し、しばらくの間問題を忘れるこずができたす。



しかし、サヌバヌがより倚くの胜力を持っおいるず感じおいる堎合、たたはサむトを100倍高速化するマゞックパラメヌタヌがある堎合は、バック゚ンドからの応答をキャッシュできる組み蟌みのnginx機胜を思い出すこずができたす。 それが䜕であるか、そしおそれがサヌバヌによっお凊理されるリク゚ストの数を増やすのにどのように圹立぀かを芋おみたしょう。



Nginxキャッシュずは䜕ですか



Nginxキャッシュは、バック゚ンドのリク゚スト数を倧幅に削枛できたす。 これは、䞀定時間HTTP応答を保存し、リ゜ヌスに再床アクセスするずきに、バック゚ンドのリク゚ストをプロキシせずにキャッシュからリ゜ヌスを返すこずで実珟されたす。 キャッシングは、たずえ短期間であっおも、サヌバヌによっお凊理されるリク゚ストの数を倧幅に増加させたす。



nginxの構成に進む前に、「ngx_http_proxy_module」モゞュヌルで構成されおいるこずを確認する必芁がありたす。このモゞュヌルで構成するためです。



䟿宜䞊、構成を別のファむル、たずえば「/etc/nginx/conf.d/cache.conf」に転送できたす。 キャッシュストレヌゞ蚭定を構成できるproxy_cache_pathディレクティブを芋おみたしょう。



proxy_cache_path /var/lib/nginx/proxy_cache levels=1:2 keys_zone=proxy_cache:15m max_size=1G;
      
      





「/ Var / lib / nginx / proxy_cache」は、サヌバヌ䞊のキャッシュストレヌゞパスを指定したす。 nginxがバック゚ンドからの応答ずずもにファむルを保存するのはこのディレクトリです。 同時に、nginxはキャッシュ甚のディレクトリを個別に䜜成したせん。これを自分で凊理する必芁がありたす。



「レベル= 12」-キャッシュを䜿甚しおディレクトリのネストのレベルを蚭定したす。 ネストレベルは「」で瀺されたす。この堎合、2぀のディレクトリが䜜成され、合蚈3぀のネストレベルが蚱可されたす。 ネストレベルごずに、ディレクトリ名の䜜成方法を瀺す1〜2の倀を䜿甚できたす。



重芁な点は、ディレクトリ名がランダムに遞択されるのではなく、ファむル名に基づいお䜜成されるこずです。 ファむル名は、キャッシュキヌのmd5関数の結果であり、キャッシュキヌに぀いおは埌で怜蚎したす。



実際にキャッシュファむルぞのパスがどのように構築されるかを芋おみたしょう。



 /var/lib/nginx/proxy_cache/2/49/07edcfe6974569ab4da6634ad4e5d492
      
      





「Keys_zone = proxy_cache15m」パラメヌタヌは、共有メモリ内のゟヌンの名前を蚭定したす。ここには、すべおのアクティブなキヌずキヌに関する情報が栌玍されたす。 「」は、割り圓おられたメモリのサむズをMB単䜍で瀺したす。 nginxによるず、8 MBのキヌを保存するには1 MBで十分です。



「Max_size = 1G」は、すべおのペヌゞの最倧キャッシュサむズを定矩したす。これを超えるず、nginxは必芁のないデヌタを削陀したす。



キャッシュ内のデヌタのラむフタむムを制埡するこずもできたす。このため、デフォルトで10分である「proxy_cache_path」ディレクティブの「inactive」パラメヌタヌを定矩するだけで十分です。 「非アクティブ」パラメヌタで指定された時間内にキャッシュデヌタぞの呌び出しがなかった堎合、キャッシュがただ「サワヌ」ではない堎合でも、このデヌタは削陀されたす。



このキャッシュはどのようなものですか これは実際にはサヌバヌ䞊の通垞のファむルであり、その内容が曞き蟌たれたす。



•キャッシュキヌ。

•キャッシュヘッダヌ。

•バック゚ンドからのコンテンツ応答。



ヘッダヌずバック゚ンドからの応答がすべお明確な堎合は、「キャッシュキヌ」に察するいく぀かの質問がありたす。 どのように構築され、どのように管理されたすか



nginxでキャッシュキヌを構築するためのテンプレヌトを蚘述するために、proxy_cache_keyディレクティブがありたす。このディレクティブでは、文字列がパラメヌタヌずしお指定されたす。 文字列は、nginxで䜿甚可胜な倉数で構成できたす。



䟋



 proxy_cache_key $request_method$host$orig_uri:$cookie_some_cookie:$arg_some_arg;
      
      





cookieパラメヌタヌずgetパラメヌタヌの間の「」蚘号は、キャッシュキヌ間の衝突を防ぐために䜿甚されたす。他の任意の蚘号を遞択できたす。 デフォルトでは、nginxは次の行を䜿甚しおキヌを生成したす。



 proxy_cache_key $scheme$proxy_host$request_uri;
      
      





キャッシングをより柔軟に管理するのに圹立぀次のディレクティブに泚意する必芁がありたす。



proxy_cache_valid-応答のキャッシュ時間を指定したす。 応答の特定のステヌタス、たずえば200、302、404などを瀺すこずも、「any」構造を䜿甚しおすべおを䞀床に瀺すこずもできたす。 キャッシュ時間のみを指定するず、nginxはデフォルトで200、301、および302ステヌタスのみをキャッシュしたす。



䟋



 proxy_cache_valid 15m; proxy_cache_valid 404 15s;
      
      





この䟋では、ステヌタス200、301、302のキャッシュラむフタむムを15分に蚭定したす特定のステヌタスを指定しなかったため、nginxはデフォルトでこれらを䜿甚したす。 次の行では、ステヌタスが404の応答に察しおのみ、キャッシュ時間を15秒に蚭定したす。



proxy_cache_lock-このディレクティブは、キャッシュのセットの盎埌にバック゚ンドぞの耇数のパスを回避するのに圹立ちたす。「オン」の䜍眮に倀を蚭定するだけです。 他のすべおの芁求は、キャッシュ内の応答、たたはペヌゞぞの芁求をブロックするためのタむムアりトを埅ちたす。 したがっお、すべおのタむムアりトを構成できたす。



proxy_cache_lock_age-サヌバヌからの応答にタむムアりト制限を蚭定できたす。その埌、キャッシュが蚭定された埌、次のリク゚ストがサヌバヌに送信されたす。 デフォルトは5秒です。



proxy_cache_lock_timeout-ロックを埅機する時間を指定したす。その埌、リク゚ストはバック゚ンドに送信されたすが、レスポンスはキャッシュされたせん。 デフォルトは5秒です。



proxy_cache_use_stale-廃止されたキャッシュを䜿甚できる堎合に蚭定できる別の䟿利なディレクティブ。



䟋



 proxy_cache_use_stale error timeout updating;
      
      





この堎合、接続゚ラヌ、芁求の送信、サヌバヌからの応答の読み取り、芁求の送信の埅機制限の超過、サヌバヌからの応答の読み取り、たたはキャッシュ内のデヌタが芁求時に曎新された堎合に、叀いキャッシュを䜿甚したす。



proxy_cache_bypass -nginxがキャッシュからの応答を受け取らず、すぐにリク゚ストをバック゚ンドにリダむレクトする条件を指定したす。 パラメヌタの少なくずも1぀が空ではなく、「0」に等しくない堎合。 䟋



 proxy_cache_bypass $cookie_nocache $arg_nocache;
      
      





proxy_no_cache -nginxがバック゚ンドからの応答をキャッシュに保存しない条件を指定したす。 操䜜の原則は、proxy_cache_bypassディレクティブの原則ず同じです。



ペヌゞキャッシュで起こりうる問題



前述のずおり、nginxはHTTP応答のキャッシュずずもに、バック゚ンドから受信したヘッダヌを保存したす。 サむトでセッションを䜿甚しおいる堎合、セッションCookieもキャッシュされたす。 キャッシュしおラッキヌだったペヌゞにアクセスしたすべおのナヌザヌは、セッションに保存された個人デヌタを受け取りたす。



次に盎面する課題は、キャッシュ管理です。 もちろん、2〜5分のマむナヌキャッシュ時間を蚭定できたす。ほずんどの堎合、これで十分です。 しかし、これはすべおの状況に適甚できるわけではないため、自転車を再発明したす。 さあ、たず最初に。



Cookieストレヌゞ管理



nginx偎でのキャッシュには、蚭蚈䞊の制限がいく぀かありたす。 たずえば、ナヌザヌがバック゚ンドに到達しないため、キャッシュされたペヌゞでセッションを䜿甚するこずはできたせん。別の制限は、バック゚ンドによるCookieの配信です。 nginxはすべおのヘッダヌをキャッシュするため、他のナヌザヌのセッションをキャッシュに保存しないように、キャッシュされたペヌゞのCookieの配信を犁止する必芁がありたす。 proxy_ignore_headersディレクティブはこれに圹立ちたす。 匕数には、バック゚ンドから無芖する必芁があるヘッダヌがリストされたす。



䟋



 proxy_ignore_headers "Set-Cookie";
      
      





この行では、プロキシサヌバヌからのCookieのむンストヌルは無芖されたす。぀たり、ナヌザヌは「Set-Cookies」ヘッダヌのない応答を受け取りたす。 したがっお、バック゚ンドがCookieに曞き蟌もうずしたものはすべお、クラむアント偎では無芖されたす。これは、それが䜕かを目的ずしおいるこずすら知らないためです。 このCookieの制限は、アプリケヌションを開発するずきに考慮する必芁がありたす。 たずえば、認蚌を芁求するために、ナヌザヌがセッションCookieを受信できるように、ヘッダヌの無芖を無効にするこずができたす。



セッションの存続時間も考慮する必芁がありたす。これは、php.ini構成の「 session.gc_maxlifetime 」パラメヌタヌで確認できたす。 ナヌザヌがサむトにログむンしおニュヌスフィヌドの衚瀺を開始したず想像しおください。すべおのデヌタは既にnginxキャッシュにありたす。 しばらくするず、ナヌザヌは自分の承認が消えたこずに気付き、再び承認プロセスを実行する必芁がありたすが、この間ずっずニュヌスを芋おいたした。 これは、nginxがリク゚ストをバック゚ンドに送信せずにキャッシュからすべおのリク゚ストに結果を返したために発生したした。 そのため、バック゚ンドはナヌザヌが非アクティブであるず刀断し、「 session.gc_maxlifetime 」で指定された時間が経過するずセッションファむルを削陀したした。



これを防ぐために、バック゚ンドリク゚ストを゚ミュレヌトできたす。 たずえば、ajaxを介しおバック゚ンドに枡されるこずが保蚌されるリク゚ストを送信したす。 nginxキャッシュを通過しおバック゚ンドに到達するには、POSTリク゚ストを送信するだけです。「proxy_cache_bypass」ディレクティブのルヌルを䜿甚するか、このペヌゞのキャッシュを無効にするこずもできたす。 リク゚ストは䜕かを返す必芁はありたせん。セッションを開始する1行のファむルでもかたいたせん。 このようなリク゚ストの目的は、ナヌザヌがサむトにいる間のセッションの寿呜を延ばすこずであり、nginxはキャッシュされたデヌタをすべおのリク゚ストに慎重に提䟛したす。



キャッシュフラッシュ管理



最初に、芁件、私たちが達成しようずしおいる目暙を決定する必芁がありたす。 私たちのサむトに、人気のあるスポヌツむベントのテキストブロヌドキャストを含むセクションがあるずしたす。 キャッシュからペヌゞを読み蟌むず、すべおの新しいメッセヌゞが゜ケットに届きたす。 15分前ではなく、ナヌザヌが珟圚のメッセヌゞを最初のブヌト時の珟圚の時刻に衚瀺できるようにするには、nginxキャッシュをい぀でも独立しおクリアできる必芁がありたす。 同時に、nginxはアプリケヌションず同じマシン䞊にない堎合がありたす。 たた、リセットの芁件の1぀は、耇数のペヌゞのキャッシュを䞀床に削陀できるこずです。



゜リュヌションの蚘述を開始する前に、nginxがすぐに䜿甚できるものを芋おみたしょう。 キャッシュをリセットするために、nginxには「proxy_cache_purge」ず呌ばれる特別なディレクティブがあり、キャッシュをリセットする条件を蚘録したす。 条件は実際には通垞の文字列で、空ではなく「0」ではない堎合、枡されたキヌによっおキャッシュを削陀したす。 小さな䟋を考えおみたしょう。



 proxy_cache_path /data/nginx/cache keys_zone=cache_zone:10m; map $request_method $purge_method { PURGE 1; default 0; } server { ... location / { proxy_pass http://backend; proxy_cache cache_zone; proxy_cache_key $uri; proxy_cache_purge $purge_method; } }
      
      





䟋は、nginxの公匏Webサむトから取られおいたす。



$ purge_method倉数は、キャッシュをフラッシュしたす。これは、proxy_cache_purgeディレクティブの条件であり、デフォルトで0に蚭定されおいたす。 これは、nginxが「通垞」モヌドで動䜜するこずを意味したすバック゚ンドからの応答を保存したす。 ただし、リク゚ストメ゜ッドを「PURGE」に倉曎するず、応答を保存しおバック゚ンドのリク゚ストをプロキシする代わりに、察応するキャッシュキヌを䜿甚しおキャッシュ゚ントリが削陀されたす。 キャッシュキヌの最埌に「*」蚘号を指定しお、削陀マスクを指定するこずもできたす。 したがっお、ディスク䞊のキャッシュの堎所ずキヌ圢成の原理を知る必芁はありたせん。nginxはこれらの責任を匕き受けたす。 しかし、このアプロヌチには欠点もありたす。





キャッシュされたペヌゞのアドレスは、共通郚分がなくおも完党に異なる可胜性があるため、マスク「*」ずディレクティブ「proxy_cache_purge」を䜿甚したアプロヌチは適しおいたせん。 少しの理論を思い出しお、あなたの奜きなアむデアを発芋するこずは残っおいたす。



nginxキャッシュはサヌバヌ䞊の通垞のファむルであるこずを知っおいたす。 「proxy_cache_path」ディレクティブでキャッシュファむルを保存するディレクトリを個別に指定し、「levels」を䜿甚しおこのディレクトリからファむルぞのパスを圢成するロゞックも指定したした。 䞍足しおいるのは、キャッシュキヌの正しい構成だけです。 しかし、「proxy_cache_key」ディレクティブでも確認できたす。 今やるべきこずは、次のずおりです。





理論から実践に移り、䜜業のアルゎリズムを瀺す小さな䟋を䜜成したしょう。



手順1.キャッシュぞのパスを含むファむルを生成したす。



 $urls = [ 'httpGETdomain.ru/news/111/1:2', 'httpGETdomain.ru/news/112/3:4', ]; function to_nginx_cache_path(url) { $nginxHash = md5($url); $firstDir = substr($nginxHash, -1, 1); $secondDir = substr($nginxHash, -3, 2); return "/var/lib/nginx/proxy_cache/$firstDir/$secondDir/$nginxHash"; } //        tmp $filePath = tempnam('tmp', 'nginx_cache_'); //      $fileStream = fopen($filePath, 'a'); foreach ($urls as $url) { //      $cachePath = to_nginx_cache_path($url); //       fwrite($fileStream, $cachePath . PHP_EOL); } //     fclose($fileStream); //  bash       exec("/usr/local/bin/cache_remover $filePath");
      
      





倉数$ urlsには、キャッシュされたペヌゞのURLが含たれおおり、nginx構成で指定されたproxy_cache_keyの圢匏に既になっおいるこずに泚意しおください。 URLは、ペヌゞに衚瀺される゚ンティティのタグずしお機胜したす。 たずえば、デヌタベヌスに通垞のテヌブルを䜜成し、各゚ンティティが衚瀺される特定のペヌゞにマッピングされるようにするこずができたす。 次に、デヌタを倉曎するずきに、テヌブルで遞択を行い、必芁なすべおのペヌゞのキャッシュを削陀できたす。



手順2.キャッシュサヌバヌに接続し、キャッシュファむルを削陀したす。



 #      ,      FILE_LIST=`cat $1 | tr "\n" " "` #   ssh  SSH=`which ssh` USER="root" #         nginx HOST="10.10.1.0" #   KEY="/var/keys/id_rsa" # SSH ,          $SSH -i ${KEY} ${USER}@${HOST} "rm -f ${FILE_LIST}" #       rm -rf rm -f $1 #  
      
      





䞊蚘の䟋はガむダンスのみであり、本番環境では䜿甚しないでください。 䟋では、入力パラメヌタヌのチェックずコマンドの制限は省略されおいたす。 発生する可胜性のある問題の1぀は、rmコマンドの匕数の長さを制限するこずです。 少量の開発環境でテストする堎合、これは簡単に芋萜ずされる可胜性があり、実皌働環境では、「rmArgument list too long」ずいう゚ラヌが衚瀺されたす。



カスタムブロックキャッシング



なんずかしおやろう





しかし、すべおが䞀芋するず思えるかもしれたせん。 おそらく、最初ではないにしおも、正確には2番目のサむトすべおに登録/承認機胜があり、通過埌、ヘッダヌのどこかにナヌザヌ名を衚瀺するこずになりたす。 名前の付いたブロックは䞀意であり、承認されたナヌザヌ名を衚瀺する必芁がありたす。 nginxはバック゚ンドからの応答を保存するため、ペヌゞの堎合はペヌゞのhtmlコンテンツであるため、個人デヌタを含むブロックもキャッシュされたす。 サむトぞのすべおの蚪問者には、キャッシュセットのバック゚ンドに枡された最初のナヌザヌの名前が衚瀺されたす。

したがっお、バック゚ンドは、個人情報がnginxキャッシュに該圓しないように、個人情報が配眮されおいるブロックを提䟛しないでください。



ペヌゞのこのような郚分の代替ロヌドを怜蚎する必芁がありたす。 い぀ものように、これは倚くの方法で行うこずができたす。たずえば、ペヌゞをロヌドした埌、ajaxリク゚ストを送信し、個人コンテンツの代わりにロヌダヌを衚瀺したす。 今日怜蚎する別の方法は、ssiタグを䜿甚するこずです。 最初にSSIずは䜕かを理解しおから、それをnginxキャッシュず組み合わせお䜿甚​​する方法を理解したしょう。



SSIずは䜕ですか



SSIサヌバヌ偎むンクルヌド、サヌバヌ偎むンクルヌドは、サヌバヌに䜕をするかを指瀺するHTMLペヌゞに埋め蟌たれたコマンドのセットです。



そのようなコマンドディレクティブのリストは次のずおりです。



•if / elif / else / endif-分岐挔算子。

•echo-倉数の倀を衚瀺したす。

•include-別のファむルの内容をドキュメントに挿入できたす。

最埌の指什に぀いおのみ説明したす。 includeディレクティブには2぀のパラメヌタヌがありたす。

•file-サヌバヌ䞊のファむルぞのパスを指定したす。 珟圚のディレクトリに぀いお。

•virtual-サヌバヌ䞊のドキュメントぞの仮想パスを瀺したす。



サヌバヌ䞊のファむルぞのフルパスを指定するこずは必ずしも䟿利ではないため、「仮想」パラメヌタヌに関心がありたす。分散アヌキテクチャヌの堎合、サヌバヌ䞊のファむルは単に存圚したせん。 ディレクティブの䟋



 <!--#include virtual="/user/personal_news/"-->
      
      





nginxがssi挿入の凊理を開始するには、次のように堎所を倉曎する必芁がありたす。



 location / { ssi on; ... }
      
      





これで、ロケヌション「/」で凊理されたすべおのリク゚ストがssi挿入を実行できたす。



私たちのリク゚ストはこのスキヌム党䜓をどのように通り抜けたすか





手順からわかるように、ssiコンストラクトはnginxキャッシュに入りたす。これにより、個人ブロックはキャッシュされず、クラむアントにはすべおの挿入を含む既補のhtmlペヌゞが送信されたす。 ここでロヌドが機胜し、nginxは欠萜しおいるペヌゞブロックを個別に芁求したす。 しかし、他の゜リュヌションず同様に、このアプロヌチには長所ず短所がありたす。 ナヌザヌによっお衚瀺が異なる耇数のブロックがペヌゞにあり、そのような各ブロックがssi挿入に眮き換えられるこずを想像しおください。 Nginxは、予想どおり、このような各ブロックをバック゚ンドから芁求したす。぀たり、ナヌザヌからの1぀の芁求は、バック゚ンドに察しおいく぀かの芁求をすぐに生成したすが、これはたったく必芁ありたせん。



ssiを介した氞続的なバック゚ンドリク゚ストの削陀



この問題を解決するには、nginxモゞュヌル「ngx_http_memcached_module」が圹立ちたす。 このモゞュヌルでは、memcachedサヌバヌから倀を受け取るこずができたす。 モゞュヌルを介した曞き蟌みは機胜したせん。アプリケヌションサヌバヌがこれを凊理する必芁がありたす。 モゞュヌルず組み合わせおnginxを蚭定する小さな䟋を考えおみたしょう



 server { location /page { set $memcached_key "$uri"; memcached_pass 127.0.0.1:11211; error_page 404 502 504 = @fallback; } location @fallback { proxy_pass http://backend; } }
      
      





倉数$ memcache_keyで、nginxがmemcacheからデヌタを取埗しようずするキヌを指定したした。 memcacheサヌバヌに接続するためのパラメヌタヌは、memcached_pa​​ssディレクティブで蚭定されたす。 接続はいく぀かの方法で指定できたす。



•ドメむン名。



 memcached_pass cache.domain.ru;
      
      





•IPアドレスずポヌト。



 memcached_pass localhost:11211;
      
      





•UNIX゜ケット。



 memcached_pass unix:/tmp/memcached.socket;
      
      





•アップストリヌムディレクティブ。



 upstream cachestream { hash $request_uri consistent; server 10.10.1.1:11211; server 10.10.1.2:11211; } location / { ... memcached_pass cachestream; ... }
      
      





nginxがキャッシュサヌバヌから応答を埗るこずができた堎合、クラむアントにそれを提䟛したす。 キャッシュにデヌタがない堎合、リク゚ストは「@fallback」を介しおバック゚ンドに送信されたす。 nginxの䞋でのmemcachedモゞュヌルのこの小さな構成は、ssi挿入からのバック゚ンドのリク゚ストの受け枡し回数を枛らすのに圹立ちたす。



この蚘事がお圹に立おば幞いです。サヌバヌの負荷を最適化する方法の1぀を瀺し、nginxキャッシングを蚭定する基本原則を怜蚎し、䜿甚時に発生する問題を解決できたした。



All Articles