Exporteer je Next.js-site zonder jezelf te DDOS-en

Paul Grieselhuber

Paul Grieselhuber

Jun 27, 2019

Dit was onze situatie toen we de lancering naderden van een recente Next.js website met grote content. We waren ongeveer 3 weken verwijderd van de lancering en wilden beginnen met het instellen van de productieserver, het testen van de implementatie, export, etc.

Alles verliep soepel totdat we bij het Next.js statische exportgedeelte van de implementatie kwamen. Tot nu toe in het project had ons team altijd statische exporttests uitgevoerd vanaf hun lokale ontwikkelmachines die op enige fysieke afstand stonden van de productieserver. Zo ver dat het onwaarschijnlijk was dat de ontwikkelmachines de productieserver (de locatie van de API voor het project) zouden overbelasten.

Als je nog steeds probeert om statische export op je project geïnstalleerd te krijgen, bekijk dan onze detailpost op de WPGraphQL blog.

De favoriete fout van iedereen: 502

Bijna meteen nadat we de export van dezelfde server als de API hadden gestart, vulden onze terminals zich met 502 fouten, met name:

Error while running `getMarkupFromTree` { Error: Network error: Unexpected token < in JSON at position 0
    at new ApolloError (/var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:92:26)
    at /var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:1581:34
    at /var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:2001:15
    at Set.forEach (<anonymous>)
    at /var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:1999:26
    at Map.forEach (<anonymous>)
    at QueryManager.broadcastQueries (/var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:1997:20)
    at /var/www/next/node_modules/apollo-boost/node_modules/apollo-client/bundle.umd.js:1476:29
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)
  graphQLErrors: [],
  networkError:
   { ServerParseError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at /var/www/next/node_modules/apollo-link-http-common/lib/index.js:35:25
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)
     name: 'ServerParseError',
     response:
      Response {
        size: 0,
        timeout: 0,
        [Symbol(Body internals)]: [Object],
        [Symbol(Response internals)]: [Object] },
     statusCode: 502,
     bodyText: '<html>\r\n<head><title>502 Bad Gateway</title></head>\r\n<body bgcolor="white">\r\n<center><h1>502 Bad Gateway</h1></center>\r\n<hr><center>nginx/1.10.3 (Ubuntu)</center>\r\n</body>\r\n</html>\r\n' },
  message: 'Network error: Unexpected token < in JSON at position 0',
  extraInfo: undefined }

Dit was een WPGraphQL (onze-review) API, uitgevoerd vanaf een Wordpress site. Als je al enige tijd Wordpress sites bouwt op substantiële schaal, kun je waarschijnlijk de fout raden die we kregen van PHP:

[error] 1248#1248: *5807411 connect() to unix:/run/php/php7.0-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: website.com, request: "GET /this/page HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "www.website.com"

Als je wel eens een 502 foutmelding hebt gehad op een Wordpress site, dan weet je ook dat je dag zojuist is verpest. Er zijn een bijna oneindig aantal oorzaken waar deze foutmelding naar kan verwijzen.

De-DDOS jezelf

Het werd duidelijk na enige discussie met @p-k op Spectrum (ht voor het uitstekende speurwerk hierover), dat het probleem hier is dat het Next.js exportproces op meerdere threads draait, en vanwege de nabijheid van de applicaties en de snelheid van uitvoering, DDOS je in wezen jezelf elke keer dat je je site exporteert.

Aangezien we van plan zijn om meerdere keren per dag te exporteren als de inhoud van de site wordt bijgewerkt, zou dit natuurlijk een non-starter zijn geweest. Dit is ook de reden waarom we de site niet lokaal bouwen en de geëxporteerde site gewoon in productie nemen.

We moeten Next.js dus vertellen dat hij op minder threads en met een lagere concurrency moet draaien om deze site met succes op de productieserver te kunnen bouwen.

Eenvoudig genoeg: werk bijvoorbeeld uw package.json file, specifically the export script to include the --threads and --concurrency opties bij:

{
  "scripts": {
    ...
    "export": "next export --threads 1 --concurrency 1",
    ...
  },
  ...
}

Dit zou het probleem moeten oplossen, maar betekent veel langzamere exporteertijden. De onze ging van ongeveer 10-12 minuten naar ongeveer 60 minuten. Verdere tests zullen ons helpen te bepalen wat de API aankan in termen van extra threads en hogere concurrency. Ondertussen bereikt dit nog steeds ons doel van meerdere builds per dag.

Bekijk de volgende post in onze serie over het bouwen van statische Next.js sites, Next.js + Multiple Apollo Clients & GraphQL Sources

Paul Grieselhuber

Paul Grieselhuber

Founder, President

Paul has extensive background in software development and product design. Currently he runs rendr.

Boek een kennismakingsgesprek met onze productexperts.

Ons team van experts in web- en mobiele applicaties kijkt ernaar uit om uw volgende project met u te bespreken.

Boek een gesprek 👋