書いてくれjsミドルウェア、サービス側キャッシュを実現(demoソースコード付)


ExpressをNodeとする.jsの枠組みは、今では日中天のように発展している.私はその柔軟で拡張しやすい設計理念が大好きです.特に、このフレームワークのミドルウェアアーキテクチャ設計は、アプリケーションに新しい特性を追加することをより標準化し、コストを最小限に抑える.この文章では、非常に簡単でコンパクトなミドルウェアを作成し、サービス側のキャッシュ機能を完了し、パフォーマンスを最適化してみます.
ミドルウェアについて
ミドルウェアといえば、Expressの公式サイトでは次のように説明されています.
「Expressは独自の機能が非常にシンプルで、完全にルーティングとミドルウェアでweb開発のフレームワークを構成しています.本質的には、Expressアプリケーションはさまざまなミドルウェアを呼び出すことです.」
いろいろなミドルウェアを使って開発したことがあるかもしれませんが、ミドルウェアの原理を理解していないかもしれませんし、Expressソースコードに深く入り込んで、その実現を探究したこともありません.ここでは長々と分析するつもりはありませんが、使用面では下図を参照してください.
興味があって、深く入り込みたい読者に自分で分析することを提案して、どんな問題があっても私と討論することを歓迎します.深く入り込むつもりがなくても、次のミドルウェアの作成に対する理解には影響しません.
サービス側キャッシュについて
キャッシュは、ページのパフォーマンスを向上させるために広く応用されています.キャッシュといえば、「クライアントキャッシュ、CDNキャッシュ、サーバ側キャッシュ…」というのが読者の頭の中に浮かぶかもしれません.別の次元では、「200(from cache)、expire、eTag......」などの概念.
もちろん、フロントエンド開発者として、これらのキャッシュコンセプトは、特定のユーザーアクセスに対して、パフォーマンスの最適化が単一のユーザーに反映されていることを理解する必要があります.例えば、私は初めてページAを開くのに時間がかかりすぎて、次のページを開くのはキャッシュの役割で時間が短縮されました.
しかし、サーバ側には別の次元が存在し、このようなシーンを考えてみましょう.
静的ページBがあります.このページサービス側はデータベースから一部のデータb 1を取得する必要があります.b 1に基づいて一部のデータb 2を計算する必要があります.また、さまざまな複雑度の操作をしなければなりません.最終的には、戻る必要がある完全なページBを「東拼西凑」することができます.プロセス全体に2 sかかります.
では、直面している災害は、user 1がページを開くのに2 sかかり、user 2が同じようにページを開くのに2 sかかることです.これらのページはすべて静的ページBであり、内容は全く同じである.この災害を解決するために、この場合もキャッシュが必要です.このキャッシュは、サービス側キャッシュ(server-side cache)と呼ばれます.
まとめると、サービス側キャッシュの目的は、同じページリクエストに対して同じページ内容を返すことである.このプロセスはまったく異なるユーザとは独立している.
上の言葉は少し拗ねていて、英語を参考にしてもっとはっきり表現することができます.
The goal of server side cache is responding to the same content for the same request independently of the client’s request.
したがって、以下に示すdemoは、最初のリクエストが到着すると、サービス側がHTMLを返すのに5秒かかる.次にページを再要求すると、キャッシュにヒットしますが、どのユーザーがアクセスするかは、数ミリ秒で完全なページを得ることができます.
Show me the code & Demo
実は上述したキャッシュの概念はとても簡単で、少しバックエンドの経験のある学生はすべてよく理解することができます.しかし、この文章は科学普及の基本概念のほかに、Expressミドルウェアの思想を紹介し、自分でサービス側キャッシュミドルウェアを実現することが重要です.
仕事を始めましょう.最終Demoコード、Githubアドレスへようこそ.
npm上のmemory-cacheというパッケージを使用して、キャッシュの読み書きを容易にします.最終的なミドルウェアコードは簡単です.
'use strict'

var mcache = require('memory-cache');

var cache = (duration) => {
  return (req, res, next) => {
    let key = '__express__' + req.originalUrl || req.url
    let cachedBody = mcache.get(key)
    if (cachedBody) {
      res.send(cachedBody)
      return
    } else {
      res.sendResponse = res.send
      res.send = (body) => {
        mcache.put(key, body, duration * 1000);
        res.sendResponse(body)
      }
      next()
    }
  }
}


簡単にするために、cacheのkeyとしてリクエストURLを使用しました.
  • それ(cache key)とその対応するvalue値が存在する場合、そのvalue値は直接返される.
  • それ(cache key)とそれに対応するvalue値が存在しない場合、Express sendメソッドをブロックします.最終的に戻る前に、このkey-valueを格納します.

  • キャッシュの有効時間は10秒です.
    最終的に判断の外で、私たちのミドルウェアは制御権を次のミドルウェアに渡します.
    最終的に次のコードを使用してテストします.
    app.get('/', cache(10), (req, res) => {
      setTimeout(() => {
        res.render('index', { title: 'Hey', message: 'Hello there', date: new Date()})
      }, 5000) //setTimeout was used to simulate a slow processing request
    })
    

    settimeoutを用いて超長(5 s)の動作をシミュレートした.
    ブラウザのコントロールパネルを開くと、キャッシュの有効期限は10秒以内です.
    なぜcacheミドルウェアがそう書くのか、next()がなぜミドルウェアが制御権を伝えるのか、私は展開するつもりはありません.興味のある方はExpressソースをご覧ください.
    まだいくつかの小さな問題があります
    私たちのページをよく見て、実装コードを体得してみましょう.注意深い読者は、さっきの実装でページ全体をキャッシュし、date:new Date()をjadeテンプレートindexに転送したという問題を発見することができるかもしれません.jade里.では、キャッシュにヒットした場合、10秒以内にページを動的にリフレッシュして同期することはできません.10秒のキャッシュが期限切れになるまで.
    また、上記のミドルウェアを使用して、サービス側キャッシュを行うことができるのはいつですか?もちろん静的な内容でしか使えません.また、PUT、DELETE、POSTの動作は、同様のキャッシュ処理を行うべきではない.
    同様に、npmモジュール:memory-cacheを使用しました.メリットとデメリットは次のとおりです.
  • 読み書きは迅速で簡単で、他の依存は必要ありません.
  • サーバまたはこのプロセスが停止すると、キャッシュ内のコンテンツはすべて失われます.
  • memcacheは、キャッシュコンテンツを自分のプロセスのメモリに格納ので、この部分は複数のNodeに格納できない.jsプロセス間で共有されます.

  • これらの弊害really matterがあれば,実際の開発ではRedisのような分散型cacheサービスを選択することができる.同様にnpmでexpress-redis-cacheモジュールで使用することができます.
    まとめ
    実際の開発シーンでは、サービス側キャッシュはcommon senseとなっているが、Node.jsの世界では、その中の間の思想を体得し、自分で手動でサービスを編纂し、同じように楽しみが尽きない.
    実践と結びつけて、本当にページ全体をキャッシュするのは(demoのように)お勧めの方法ではないと思います(当時の実際のシーンの実際の分析)、同様に要求urlをキャッシュとして使用するkeyも考慮されます.たとえば、ページ内の静的なコンテンツの一部が他のページで繰り返し使用される可能性があり、多重化が問題になります.
    実際のシーンでは、すべての設計と論理は自分のビジネス状況に責任を負わなければなりません.需要から離れて実現を語るのは,みなごろつきだ.このdemoは簡単で軽くて、必要な読者がGithubアドレスにアクセスすることができて、いろいろな模様を游ぶことを歓迎します.
    Happy Coding!
    PS:著者Github倉庫と知乎問答リンクは様々な形式の交流を歓迎します.