blog

FastCGIキャッシュによるサービス低下

FastCGIキャッシュは、多くの友人が共有する前に行っている、別の何かを言う:キャッシュの使用が、リアルタイムの考慮のために、通常の状況下で、キャッシュが浸透しているが、クエリの異常の場合にのみ。こ...

Jan 17, 2014 · 13 min. read
シェア

自然界では、多くの生き物が生と死のテストに直面し、多くの場合、最もよく知られているヤモリである驚くべき応答を行います、決定的な瞬間は、むしろ座って死を待つよりも、尾のように悪くない、生きる希望と引き換えに自傷を通して。インターネットプロジェクトは、また、多くの生と死のテストは、次のようなものがあります:アクセスサージ、データベースのダウンタイムなど、この時点で、合理的な劣化プログラムがない場合は、終了は行き止まりにバインドされています。

どのような問題であっても、いったん実際の状況から切り離されてしまうと、議論の意義が失われてしまいます。続行するには、それはケースの背景を導入する価値があるかもしれません:PHPのウェブサイトは、読み取りベース、もともとCDNの後ろに隠れて、非常に安定して動作し、その後、リアルタイム需要に新たな重点の多くを追加し、彼らは、システムの安定性に影響を与えるにつながったCDNを削除します。重い歴史的な手荷物のため、以前のアーキテクチャの完全な放棄は現実的ではないと思われるので、ソリューション***は、可能な限り透過的にすることができ、元のアーキテクチャに影響を与えることはできませんし、最終的に私は、サービス低下プログラムを達成するために選択しました。

FastCGIキャッシュは、多くの友人など、共有する前に行っている:スーパーグループ蕁麻疹、概念的なことは、私は繰り返しませんが、何か違うと言う:キャッシュの使用が、リアルタイムの考慮のために、通常の状況下でキャッシュが浸透している異常クエリの場合にのみ、アーキテクチャは次のとおりです:

劣化

実装の重要なポイントは、error_page例外を処理し、サービスの劣化を完了することです:

limit_conn_zone $server_name zone=perserver:1m; 
error_page 500 502 503 504 = @degradation; 
fastcgi_cache_path /tmp 
       levels=1:2 
       keys_zone=degradation:100m 
                   inactive=10d 
                   max_size=10g; 
upstream php { 
    server .1:9000; 
    server .1:9001; 
} 
server { 
    listen 80; 
    limit_conn perserver 1000; 
    server_name *.xip.io; 
    root /usr/local/www; 
    index index.html index.htm index.php; 
    location / { 
        try_files $uri $uri/ /index.php$is_args$args; 
    } 
    location ~ \.php$ { 
        set $cache_key $request_method://$host$request_uri; 
        set $cache_bypass "1"; 
        if ($arg_degradation = "on") { 
            set $cache_bypass "0"; 
        } 
        try_files $uri =404; 
        include fastcgi.conf; 
        fastcgi_pass php; 
        fastcgi_intercept_errors on; 
        fastcgi_next_upstream error timeout; 
        fastcgi_cache degradation; 
        fastcgi_cache_lock on; 
        fastcgi_cache_lock_timeout 1s; 
        fastcgi_cache_valid 200 301 302 10h; 
        fastcgi_cache_min_uses 10; 
        fastcgi_cache_use_stale error 
                                timeout 
                                invalid_header 
                                updating 
                                http_500 
                                http_503; 
        fastcgi_cache_key $cache_key; 
        fastcgi_cache_bypass $cache_bypass; 
        add_header X-Cache-Status $upstream_cache_status; 
        add_header X-Response-Time $upstream_response_time; 
    } 
    location @degradation { 
        rewrite . $request_uri?degradation=on last; 
    } 
} 

ちょっとしたヒント:xip.io使用するドメイン名を設定すると、ホストを設定する必要がなくなり、デバッグが容易になります。

このコードはNginxにデフォルトで含まれている機能を使用しており、一般的なバージョンとして見ることができます。しかし、アーキテクチャ図のゴールと比較すると明らかなように、キャッシュのグローバルアクティベーションを実装していません。これはどうすればできるのでしょうか?最も簡単な方法は、単位時間あたりのエラー数によってシステムの健全性を判断し、対応する閾値を設定し、制限を超えたらグローバルにキャッシュをアクティブにすることです:

lua_shared_dict fault 1m; 
 
limit_conn_zone $server_name zone=perserver:1m; 
 
error_page 500 502 503 504 = @degradation; 
 
fastcgi_cache_path /tmp 
                   levels=1:2 
                   keys_zone=degradation:100m 
                   inactive=10d 
                   max_size=10g; 
 
upstream php { 
    server .1:9000; 
    server .1:9001; 
} 
init_by_lua ' 
    get_fault_key = function(timestamp) 
        if not timestamp then 
            timestamp = ngx.time() 
        end 
        return os.date("fault:minute:%M", timestamp) 
    end 
    get_fault_num = function(timestamp) 
        local fault = ngx.shared.fault 
        local key = get_fault_key(timestamp) 
        return tonumber(fault:get(key)) or 0 
    end 
    incr_fault_num = function(timestamp) 
        local fault = ngx.shared.fault 
        local key = get_fault_key(timestamp) 
        if not fault:incr(key, 1) then 
            fault:set(key, 1, 600) 
        end 
    end 
'; 
server { 
    listen 80; 
    limit_conn perserver 1000; 
    server_name *.xip.io; 
    root /usr/local/www; 
    index index.html index.htm index.php; 
    location / { 
        rewrite_by_lua ' 
            if ngx.var.arg_degradation then 
                return ngx.exit(ngx.OK) 
            end 
 
            local ok = true 
 
            for i = 0, 1 do 
                local num = get_fault_num(ngx.time() - i * 60) 
                if num > 1000 then 
                    ok = false 
                    break 
                end 
            end 
           if not ok then 
                local query = "degradation=on" 
                if ngx.var.args then 
                    ngxngx.var.args = ngx.var.args .. "&" .. query 
                else 
                    ngx.var.args = query 
                end 
            end 
        '; 
        try_files $uri $uri/ /index.php$is_args$args; 
    } 
    location ~ \.php$ { 
        set $cache_key $request_method://$host$request_uri; 
 
        set $cache_bypass "1"; 
        if ($arg_degradation = "on") { 
            set $cache_bypass "0"; 
        } 
        try_files $uri =404; 
        include fastcgi.conf; 
        fastcgi_pass php; 
        fastcgi_intercept_errors on; 
        fastcgi_next_upstream error timeout; 
        fastcgi_cache degradation; 
        fastcgi_cache_lock on; 
        fastcgi_cache_lock_timeout 1s; 
        fastcgi_cache_valid 200 301 302 10h; 
        fastcgi_cache_min_uses 10; 
        fastcgi_cache_use_stale error 
                                timeout 
                                invalid_header 
                                updating 
                                http_500 
                                http_503; 
        fastcgi_cache_key $cache_key; 
        fastcgi_cache_bypass $cache_bypass; 
        add_header X-Cache-Status $upstream_cache_status; 
        add_header X-Response-Time $upstream_response_time; 
    } 
    location @degradation { 
        content_by_lua ' 
            if ngx.var.arg_degradation then 
                return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) 
            end 
            local res = ngx.location.capture( 
                ngx.var.request_uri, {args = "degradation=on"} 
            ) 
            ngx.status = res.status 
            for name, value in pairs(res.header) do 
                ngx.header[name] = value 
            end 
            ngx.print(res.body) 
            incr_fault_num() 
        '; 
    } 
} 

注:実際には、キャッシュキーの名前を取得するロジックは少し複雑です。

システムが正常なときは、ダイナミックモードで実行され、データはPHP-FPMを通してレンダリングされます。システムが異常なときは、グローバルキャッシュがアクティブになり、静的モードで実行され、データはキャッシュを通してレンダリングされます。テストを通して、システムが正常から異常に切り替わったとき、PHP-FPMが破棄されたため、RPSが1000から10000に跳ね上がることがわかりました。不死身の一騎が敵に倒されると、いつも立ち上がり、さらにエネルギーを爆発させていました。

また、それは注意する必要があります:障害が発生した場合、キャッシュの有効期限が多数ある場合、それはキャッシュの再構築を伴うので、それはまだパフォーマンスに影響を与える可能性がありますPHP - FPMと相互作用するので、この時点では特に良い解決策はありませんが、Nginxのバージョンが十分な場合は、fastcgi_cache_revalidateの活性化を検討することができます。Nginxのバージョンが十分な場合は、fastcgi_cache_revalidateをアクティブにすることを検討することができます、この方法では、一度PHP-FPMは、システムが異常な状況にあると判断し、直接304を返すことができますモラトリアムを達成するために。

...

FastCGI キャッシュによるサービス低下は **** 解決策ですか?そうではありません!例えば、複数のサーバーが関係している場合、ディスクIOに加え、多くの冗長なキャッシュが必要になります。これは****ソリューションではありませんが、シンプルで、私が困難な問題を解決しようとしているときに使っているものです:問題を軽減するための糞ソリューション、そして問題を解決するための****ソリューション。後ほど、FastCGIキャッシュの代わりに一貫したハッシュを持つMemcachedを使用することを検討します。

Read next

アンドロイド4.4のSMSと電話のインターフェイスが公開される

AndroidのチーフSundar Pichaiは、Android 4.4がそのコードネームとしてKitKatチョコレートバーを使用することを今月初めに発表し、4.4が過去の世代のJelly Beanベースのシステムとは大きく異なることを示唆しています。より多くの詳細は、それ以来明るみに出ている, KitKatのアップグレードは、古いマシンの最適化に焦点を当てることを示唆, Androidの断片化を改善し、いくつかの文体の変更を加える.\n\n

Jan 16, 2014 · 1 min read