24

前に、またはRESTful API(Rubyで記述)へのGETリクエストの最初のレイヤーとしてキャッシュレイヤーを作成するための最良の方法を考えています。

一部のGETリクエストでも、APIはリクエストしているユーザー/アプリケーションを検証する必要があるため、すべてのリクエストをキャッシュできるわけではありません。つまり、キャッシュ可能なリクエストと、キャッシュされた各回答が有効である期間を構成する必要があります。いくつかのケースでは、たとえば15秒以下の非常に短い有効期限が必要です。また、有効期限にまだ達していない場合でも、APIアプリケーションによってキャッシュエントリを期限切れにすることができるはずです。

私はすでに多くの可能な解決策、私の2つの最良のアイデアについて考えました:

  • APIの最初のレイヤー(ルーティングの前でも)、自分でロジックをキャッシュ(すべての構成オプションを手元に用意するため)、回答と有効期限をMemcachedに保存

  • Webサーバープロキシ(高度に構成可能)、おそらくSquidのようなものですが、これまでこのようなケースでプロキシを使用したことはなく、それについてはまったくわかりません。

また、Varnishのようなキャッシュソリューションについても考えました。「通常の」WebアプリケーションにVarnishを使用しました。これは印象的ですが、構成は特別なものです。しかし、それが最速の解決策であれば、私はそれを使用します。

もう1つの考えは、Solrインデックスにキャッシュすることでした。これは、ほとんどのリクエストについてデータベースにクエリを実行しないように、データレイヤーですでに使用しています。

誰かがこのトピックについて読むためのヒントや良い情報源を持っているなら、私に知らせてください。

4

5 に答える 5

5

memcachedは優れたオプションであり、これは可能なオプションとしてすでに言及されていると思います。また、Redisは、このレベルの別のオプションとして多くの賞賛を受けているようです。

アプリケーションレベルでは、ファイルごとやモジュールごとにキャッシュするためのよりきめ細かいアプローチの観点から、ローカルストレージは、応答をドロップするだけの単純な場合でも、ユーザーが何度も何度も要求する可能性のある一般的なオブジェクトのオプションです。オブジェクトをセッションに入れて再利用できるようにするのではなく、別のhttpREST呼び出しを行って適切にコーディングします。

現在、人々はワニスとイカについて議論を交わしており、どちらにも長所と短所があるようです。どちらが優れているかについてはコメントできませんが、多くの人が、調整されたApacheサーバーを備えたワニスは動的なWebサイトに最適だと言います。

于 2012-12-24T22:16:43.463 に答える
5

まず、RESTfulになるようにRESTfulAPIを構築します。つまり、認証されたユーザーは、認証の詳細を含めるために必要なURLのすべての状態を保持するために、キャッシュされたコンテンツを取得することもできます。もちろん、ここではヒット率は低くなりますが、キャッシュ可能です。

多くのログインユーザーがいる場合、一部のモデルが共有されていなくても(優れたOOP構造で)多くのモデルが共有されるため、フルページキャッシュの背後にある種のモデルキャッシュがあると非常に有益です。

次に、フルページキャッシュの場合、すべてのリクエストをWebサーバーから遠ざけ、特に次のステップ(この場合はRuby)の動的処理から遠ざけるのが最善です。通常のWebサーバーからページ全体をキャッシュする最速の方法は、常にWebサーバーの前にあるキャッシュプロキシです。

ワニスは私の意見ではそれが得られるのと同じくらい良くて簡単です、しかし何人かは確かにイカを好みます。

于 2012-12-25T14:00:27.817 に答える
4

RESTはHTTPのものであるため、リクエストをキャッシュする最良の方法はHTTPキャッシングを使用することである可能性があります。

応答でETagを使用することを検討し、「304 NotModified」で応答するリクエストのETagを確認し、ETagが同じ場合はRack::Cacheを使用してキャッシュデータを提供します。これは、キャッシュ制御の「パブリック」コンテンツに最適です。

Rack :: Cacheは、ストレージのニーズに合わせてmemcacheを使用するように構成するのが最適です。

先週、Rack :: CacheがETagを使用してキャッシュされたコンテンツを検出し、新しいクライアントに返す興味深い方法についてブログに投稿しました:http: //blog.craz8.com/articles/2012/12/19/rack-cache-および-etags-for-even-faster-rails

Railsを使用していない場合でも、Rackミドルウェアツールはこのようなものに非常に適しています。

于 2012-12-25T06:37:53.437 に答える
1

Redisキャッシュが最適なオプションです。 こちらを確認してください。

オープンソースです。高度なキー値のキャッシュと保存。

于 2015-05-06T06:55:36.233 に答える
0

私はRESTビューでこのようにredisを正常に使用しました:

from django.conf import settings
import hashlib
import json
from redis import StrictRedis
from django.utils.encoding import force_bytes

def get_redis():
    #get redis connection from RQ config in settings
    rc = settings.RQ_QUEUES['default']
    cache = StrictRedis(host=rc['HOST'], port=rc['PORT'], db=rc['DB'])
    return cache



class EventList(ListAPIView):
    queryset = Event.objects.all()
    serializer_class = EventSerializer
    renderer_classes = (JSONRenderer, )


    def get(self, request, format=None):
        if IsAdminUser not in self.permission_classes:  # dont cache requests from admins


            # make a key that represents the request results you want to cache
            #  your requirements may vary
            key = get_key_from_request()

            #  I find it useful to hash the key, when query parms are added
            #  I also preface event cache key with a string, so I can clear the cache
            #   when events are changed
            key = "todaysevents" + hashlib.md5(force_bytes(key)).hexdigest()        

            # I dont want any cache issues (such as not being able to connect to redis)
            #  to affect my end users, so I protect this section
            try:
                cache = get_redis()
                data = cache.get(key)
                if not data:
                    #  not cached, so perform standard REST functions for this view
                    queryset = self.filter_queryset(self.get_queryset())
                    serializer = self.get_serializer(queryset, many=True)
                    data = serializer.data

                    #  cache the data as a string
                    cache.set(key, json.dumps(data))

                    # manage the expiration of the cache 
                    expire = 60 * 60 * 2  
                    cache.expire(key, expire)
                else:
                    # this is the place where you save all the time
                    #  just return the cached data 
                    data = json.loads(data)

                return Response(data)
            except Exception as e:
                logger.exception("Error accessing event cache\n %s" % (e))

        # for Admins or exceptions, BAU
        return super(EventList, self).get(request, format)

イベントモデルの更新で、イベントキャッシュをクリアします。これはほとんど実行されないため(管理者のみがイベントを作成し、それほど頻繁には作成しません)、常にすべてのイベントキャッシュをクリアします

class Event(models.Model):

...

    def clear_cache(self):
        try:
            cache = get_redis()
            eventkey = "todaysevents"
            for key in cache.scan_iter("%s*" % eventkey):
                cache.delete(key)
        except Exception as e:
            pass


    def save(self, *args, **kwargs):
        self.clear_cache()
        return super(Event, self).save(*args, **kwargs)
于 2018-01-11T22:52:12.200 に答える