javascript - Nginx node.js express sťahovanie veľkých súborov sa zastaví na 1.08GB


Mám túto aplikáciu node.js, ktorú sprostredkúva Nginx (v produkcii). Trasa vyzerá nejako takto:

exports.download = function(req, res){

    var id = req.params.id;

    if (id && id == 'latest')
    {
        res.download(config.items.release_directory+'/<1.6GB-file>.zip', function(err){
            if (err) {
                console.log(err);
            } else {
                // do something
            }
        });
    }
    else
    {
        res.redirect(301, '/');
    }

};

Takže, pri kliknutí na správnu trasu/URL prehliadač začne sťahovať veľký súbor, ale potom vždy zastaví na 1,08 GB (súbor má asi 1,6 GB), čím ho skracuje.

Naozaj nechápem prečo. Máš nejaké nápady?

EDIT: config.items.release_directory je statický adresár Express deklarovaný ako:

app.use('/releases', express.static(path.join(__dirname, '..', 'releases')));

EDIT2: Pri vývoji s grunt, ktorý priamo spúšťa aplikáciu bez Nginx, to funguje dobre.

VYRIEŠENÉ: prečítajte si komentáre nižšie, problém je premenná proxy_max_temp_file_size v Nginx

Odpoveď č. 1

Tu ide o konfiguráciu nginx, nie o kód nodejs.

nginx zapisuje dočasné súbory na disk pred ich odoslaním klientovi, často je dobrý nápad toto cache vypnúť, ak má stránka slúžiť veľké statické súbory, napríklad takto:

location / {
    proxy_max_temp_file_size 0;
}

(bez limitu)

Odpoveď č. 2

Dôrazne odporúčam nenastavovať proxy_max_temp_file_size 0, pretože to bude mať za následok odstránenie akéhokoľvek proxy bufferu pre všetky vaše koncové body.

To znamená, že váš aplikačný server nebude schopný vyprázdniť údaje odpovede do NGINX bufferu (z ktorého môže downstream klient čítať, kedykoľvek má dostatočné pripojenie) a byť uvoľnený/odblokovaný. Namiesto toho váš aplikačný server bude čakať na klienta (bez NGINX proxy medzi tým), aby si stiahol údaje.

Alternatívne môžete inštruovať svoj NGINX proxy, aby vyberavo nebufroval dáta odpovede pri streamovaní vašich zip súborov, aby ste predišli akýmkoľvek potenciálnym problémom s tým, že dočasný súbor bufferu NGINX sa naplní a preruší streamovanie sťahovania (čo bola moja skúsenosť).

Toto môžete dosiahnuť tým, že vo vašom Node.js endpoint-e urobíte niečo podobné ako nasledujúce:

res.set('X-Accel-Buffering', 'no');

Týmto spôsobom budú údaje priamo streamované z Expressu ku klientom, ale iba pre koncové body, pre ktoré nechcete, aby boli údaje odpovede ukladané do vyrovnávacej pamäte (pravdepodobne vaše streamovacie koncové body).