Simple server side cache for Express with Node.js——Express 實現簡單的服務器端緩存【翻譯】

原文地址在這裏: http://goenning.net/2016/02/10/simple-server-side-cache-for-expressjs/

第一次翻譯,不是很好,但大概意思應該還可以。有錯誤,請多多指正。

    express是我目前爲止見過擴展性最好的web框架。它的中間件結構使它可以輕鬆地以標準化方式添加額外的功能。
    本次主題,我們將會討論一個很小很簡單,但功能非常強大、有用的中間件。它將會幫助你提升你的express Web程序的性能,而且無需任何依賴。

關於服務端緩存


    無論是在 desktop, mobile or web哪一方面,Cache都常被我們用來提升程序性能。當處理web應用程序的時候,雖然可以使用當前所有瀏覽器都支持的響應頭來進行客戶端緩存,從而提升頁面加載效率。但當一個內容非常繁雜的頁面需要2s來進行HTML輸出的時候,即使啓用客戶端緩存該頁面,服務器仍然需要針對每一個來訪用戶進行頁面渲染。想想一個大型的新聞門戶網站首頁,難道他們要針對每一個用戶一遍又一遍地處理HTML嗎?
    這時候服務器緩存就派上用場了。使用服務器緩存的目標是對相同的客戶端請求返回相同的內容。在上面的例子裏,第一個請求仍然需要2s處理HTML,但是接下來請求將會命中緩存,服務器可以在幾毫秒內發送響應內容。
    有很多種方法可以實現服務器緩存,例如NGINX以及類似於CloudFlare的CDN。在這裏,我們將會使用nodejs和express來輕鬆簡便地實現它。

代碼展示


    我們的目標是輕鬆實現服務器緩存。接下來,我們開始吧!
    我們將充分利用 memory-cache npm模塊來將內容添加到緩存中。中間件如下:

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()
    }
  }
}

    它將把請求的url作爲key值進行緩存查詢。一旦查詢到緩存,將會直接發送響應報文。否則,就會在響應報文發送到客戶端之前,對響應進行緩存。然後調用下一個中間件。
    這裏有一個非常簡單的例子——關於如何緩存一個繁重的處理頁面。

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
})

     注意,上述路由包含兩個中間件。一個是關於緩存,另一個是真正用於處理請求的中間件。在這種情況下,當該路由收到第一次請求的時候,將不會立刻返回響應,而是會停留5s。但是在接下來的10s,連續的請求將會直接從緩存中得到響應,而不需要再去等待5s。有得必有失,該方法的缺點在你的響應報文中含有動態內容的時候將會展現出來。在上面的路由中,如果我們將當前時間作爲參數傳遞給視圖引擎,那麼緩存過期(10s)之前響應內容中都會含有相同的日期。

    這裏非常棒的一點就是,以上方法適用於HTML,JSON,XML以及其他任何內容類型的響應。

    你可以輕鬆地引入該中間件到已存在的站點中,來緩存任何你想要緩存的路由。

    注意:不要緩存 GET POST 方法

    在這個例子中,我們使用了在內存中緩存內容的NPM模塊,這有利有弊。

        - 在內存中緩存速度最快
        - 使用簡單,不需要添加額外的依賴。
        - 如果服務器或進程出現故障,緩存將會丟失
        - 由於每個進程在自己的內存區間存儲緩存內容,所以Node.js的多個進程之間內存不共享。

    要解決大部分問題的一個選擇是使用諸如 Redis 的分佈式緩存服務。它可以僅僅通過一個npm 模塊 express-redis-cache中間件來實現。

'use strict'

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

app.set('view engine', 'jade');

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()
    }
  }
}

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
})

app.get('/user/:id', cache(10), (req, res) => {
  setTimeout(() => {
    if (req.params.id == 1) {
      res.json({ id: 1, name: "John"})
    } else if (req.params.id == 2) {
      res.json({ id: 2, name: "Bob"})
    } else if (req.params.id == 3) {
      res.json({ id: 3, name: "Stuart"})
    }
  }, 3000) //setTimeout was used to simulate a slow processing request
})

app.use((req, res) => {
  res.status(404).send('') //not found
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

編程愉快

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章