Nodejsまたはexpressのレスポンスに'content-encoding':'gzip'を設定します。

5119 ワード

環境:Nodejs/express+Apache
タイトルのように、バックエンドのexpress Serverでserver上の大きなファイルを読み込む必要がある場合や、戻ってくるデータが比較的大きい対象の場合(例えば、数十Mのデータの場合)は、stream/pipeでdataを処理することを考え、フロー方式は実用的で効率的なツールを提供して、比較的大きいdataの処理を処理し、その後直接にrespnseに出力することができます。しかし、理解が必要なのは、例えばgzipやdeflateを圧縮してブラウザに戻したほうがいいです。
あるいは要求されたすべてのデータは圧縮された形式でブラウザに戻ります。ここで圧縮された倍率は大体、圧縮前:50 Mぐらい、圧縮後3 Mぐらいです。基本的には10倍以上の圧縮率がありますので、ネットワーク間の伝送においては性能が大幅に向上します。
ここの例はnodejsを使っています。他の言語でjavaを使うのも同じです。言語は単にパッケージ化して、tcp、httpプロトコルを実現しただけです。最適化の最後はこれらを理解しなければなりません。
>>なぜ圧縮されたのか、ここでよく説明されています。 https://blog.csdn.net/liangxw1/article/details/84835199
//stream/pipeでdataに戻るにはreponseでhttpのレスポンスが必要です。 headerの中の Accept-Enccoding:gzipまたはdeflateは、server端で圧縮し、browser client端でdataを解凍して表示することができます。コードは以下の通りです。
module.exports.getTest = function (req, res) {
    // A
    // filepath,   filepath         *.json.gz   
    //  ,       json     *.json.gz ,     stream/pipe  response    ,
    //            (   )*.json.gz   json  
    // 
    //          :                    ,    res.json(data)    ,         ,
    //      stream/pipe                ,     ,        ,
    //     ,        response ,     Apache        gzip  deflate     ,        ??    ,***          ***
    //    AddOutputFilterByType DEFLATE application/octet-stream??
    //                  res.writeHead       content-encoding,        *.json.gz          ,     ,       
    fs.exists(filepath, function (exists) {
        if (exists === true) {

            const srcReadStream = fs.createReadStream(filepath);

            // Success with response body
            // res.status(200);
            //  ,        ,                      gzip  deflate   content-encoding
            res.writeHead(200, { 'content-encoding': 'gzip' });
            srcReadStream.pipe(res);
            
            srcReadStream.on('close', function () {
                // It can go here after close event
                srcReadStream.destroy();
            });
            
            srcReadStream.on('error', function (err) {
                srcReadStream.destroy();
            });
        } else {

            ...
        }
    });
}
 
関連資料を調べて、戻りのレスポンスの中でデータを圧縮して返します。少なくとも次の二つのところでできます。
  • アプリケーションのコードの中で、判定要求のhttp headerの中の Accept-Enccoding:gzip、deflateはどのタイプの圧縮と解凍をサポートしていますか?その後、戻りのレスポンスにContent-Enccodingを設定します。gzipやdeflateなど
  •          nodejs/expressでは、copressionというプラグインは、圧縮後にclient browserに転送することができます。その後、browserは正しく解凍して表示することができます。
             しかし、このような方法は個人的にはあまり推奨されていません。nodejsにとって、大量の処理と圧縮の動作は性能に影響を与える可能性があります。また、Apacheサーバーでできるなら、もっといいはずです。まず、nodejsに対する圧力が小さいので、コードは変更しなくてもいいです。侵入性は小さいです。
        2.Appacheサーバでは、以下の設定を有効にします。
    https://httpd.apache.org/docs/2.4/mod/mod_deflate.
    https://varvy.com/pagespeed/enable-compression.html
    LoadModule deflate_module modules/mod_deflate.so
    
    //                        
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/html text/plain text/xml
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    
    //      ,     ,     ??
    DeflateFilterNote Input instream
    DeflateFilterNote Output outstream
    DeflateFilterNote Ratio ratio
    stream/pipeでreponseに戻るのではなく、expessのres.jsonを使って、上の21875;1を使って、クライアントとserver端でデータを圧縮して転送と解凍する効果があります。
    次のような方式のstream/pipe方式は大丈夫です。これは上の第一の方式に似ています。
    //参考: https://stackoverflow.com/questions/3894794/node-js-gzip-compression
    // server example
    // Running a gzip operation on every request is quite expensive.
    // It would be much more efficient to cache the compressed buffer.
    var zlib = require('zlib');
    var http = require('http');
    var fs = require('fs');
    http.createServer(function(request, response) {
      var raw = fs.createReadStream('sample-drag.html');
      var acceptEncoding = request.headers['accept-encoding'];
      if (!acceptEncoding) {
        acceptEncoding = '';
      }
    
      // Note: this is not a conformant accept-encoding parser.
      // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
      if (acceptEncoding.match(/\bgzip\b/)) {
        response.writeHead(200, { 'content-encoding': 'gzip' });
        raw.pipe(zlib.createGzip()).pipe(response);
      } else if (acceptEncoding.match(/\bdeflate\b/)) {
        response.writeHead(200, { 'content-encoding': 'deflate' });
        raw.pipe(zlib.createDeflate()).pipe(response);
      } else {
        response.writeHead(200, {});
        raw.pipe(response);
      }
    }).listen(1337);
    
    
    //      
    exports.helloWorld = function helloWorld(req, res) {
      const zlib = require('zlib');
    
      // Obtain JSON stream from your source...
    
      res.status(200);
    
      res.set('Content-Type', 'text/plain');
      res.set('Content-Encoding', 'gzip');
    
      json.pipe(zlib.createGzip()).pipe(res);
    };