20

私は、1 日あたり 100 万から 200 万のヒットがあると見積もっているサイトを持つクライアントのプロジェクトに取り組むことを任されています。彼は、新しいブランドの登録ごとにシードを取得する必要がある 5,800 万人のユーザーの既存のデータベースを持っています。サイトのコンテンツのほとんどは、外部 API が提供するデータから提供されます。Mongo セットアップに保存されているほとんどのデータは、プロファイル情報と保存された API パラメーターです。

NginX はポート 80 で実行され、ポート 8000 ~ 8010 でノード クラスターへの負荷分散が行われます。

私の質問は、キャッシングをどうするかです。私は LAMP のバックグラウンドを持っているので、PHP で静的 HTML ファイルを作成し、それらを提供して MySQL の負荷を最小限に抑えるか、より高いレベルのキャッシュが必要なサイトに Memcached を使用することに慣れています。この設定は私には少し異質です。

最小の応答時間と CPU 負荷に関して最も理想的なのはどれですか?

1: NginX によるページレベルのキャッシュ

参照: http://andytson.com/blog/2010/04/page-level-caching-with-nginx/

server {
    listen            80;
    servername        mysite.com;

    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  Host       $host;

    location / {
        proxy_pass    http://localhost:8080/;
        proxy_cache   anonymous;
    }

    # don't cache admin folder, send all requests through the proxy
    location /admin {
        proxy_pass    http://localhost:8080/;
    }

    # handle static files directly. Set their expiry time to max, so they'll
    # always use the browser cache after first request
    location ~* (css|js|png|jpe?g|gif|ico)$ {
        root          /var/www/${host}/http;
        expires       max;
    }
}


2: キャッシュ バケットとしての Redis

hash()関数は、numbers()このページの関数です: http://jsperf.com/hashing-strings

function hash(str) {
    var res = 0,
        len = str.length;
    for (var i = 0; i < len; i++) {
        res = res * 31 + str.charCodeAt(i);
    }
    return res;
}

var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef';
var key    = hash(apiUrl).toString(); // 1.8006908172911553e+136

myRedisClient.set(key,theJSONresponse, function(err) {...});


3: ノードは JSON ファイルを書き込みます

hash()関数は、numbers()このページの関数です: http://jsperf.com/hashing-strings

function hash(str) {
    var res = 0,
        len = str.length;
    for (var i = 0; i < len; i++) {
        res = res * 31 + str.charCodeAt(i);
    }
    return res;
}

var fs     = require('fs');
var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef';
var key    = hash(apiUrl).toString(); // 1.8006908172911553e+136

fs.writeFile('/var/www/_cache/' + key + '.json', theJSONresponse, function(err) {...});


4:手前にニスを塗る

私はいくつかの調査を行い、このサイトに示されているようなベンチマークは、このソリューションから私を遠ざけていますが、それが最も理にかなっている場合は、まだ検討する用意があります: http://todsul.com/nginx-varnish

4

3 に答える 3

18

組み合わせを行い、Redis を使用して短い TTL を持つセッション ユーザー API 呼び出しをキャッシュし、Nginx を使用して長期的な RESTless データと静的アセットをキャッシュします。リストされているオプションの中で、ファイル システムの IO が最も遅く、最も CPU を集中的に使用するので、JSON ファイルは書きません。

于 2013-03-21T19:29:07.583 に答える
5
  1. nginx のページ レベル キャッシングは、静的コンテンツのキャッシングに適しています。しかし、動的コンテンツの場合、それは良くありません。たとえば、コンテンツがアップストリームで変更された場合、どのようにキャッシュを無効にしますか?

  2. Redis はインメモリ データ ストアに最適です。しかし、キャッシュとして使用するのは好きではありません。メモリ量が限られているため、常にメモリ不足を心配する必要があります。はい、redis で期限切れのキーの戦略を設定できます。しかし、それは余分な作業であり、それでもキャッシュ プロバイダーにしたいほど良くはありません。

選択肢 3 と 4 の経験がない。

オプションとして memcache がここに含まれていないことに驚いています。私の経験からすると、キャッシュ プロバイダーとしては堅実です。redis にない memcache 機能の 1 つは、指定した有効期限までにキーが期限切れにならないことを保証しないことです。これはデータ ストアには悪いことですが、memcache はキャッシングの最適な候補になります。memcache に割り当てたメモリを使い果たすことを心配する必要はありません。memcache は、それらのキーの有効期限がまだ満たされていない場合でも、使用頻度の低いキー (使用頻度の低いキャッシュ) を削除します。

Nginx は、この組み込みのmemcache モジュールを提供します。しっかりしています。オンラインでグーグルで検索すると、いくつかのチュートリアルがあります。

これが一番好きです(下のリンクを参照)。キャッシュの無効化は簡単です。たとえば、アップストリームでページが更新された場合、アップストリームのアプリ サーバーから memcache キーを削除するだけです。著者は、応答時間が 4 倍に増加したと主張しています。あなたのユースケースには十分だと信じてください。

http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/

于 2013-03-25T22:53:38.410 に答える
1

ワニスに関しては、あなたが見つけたサイトのベンチマークを解読するつもりはありませんが、それらは非常に悪い数値であり、実際のトラフィックの多い実装とは何の共通点もありません (ワニスの最適化についてグーグルで検索し、100-200k を示すベンチマークを参照してください)。 8k ではなく req/s)。

Nginx もページ キャッシュに適した選択肢であり、1 日あたり 1 ~ 2M のヒットがあるため、極端なパフォーマンスは必要ありません。ですから、より快適に作業できる方を選んでください。

2 ノード ソリューションは、実際には最悪の選択です。信頼性とパフォーマンスの両方を提供するために、ページ キャッシュは動的アプリケーションから分離する必要があります。

さらに、redis/memcached は、オブジェクト キャッシュまたは一般的に使用される逆シリアル化されたデータのキャッシュとして使用する場合、アプリケーションのスケーリングに最も役立ちます。

于 2013-03-25T11:00:42.883 に答える