Exporteer je Next.js-site zonder jezelf te DDOS-en
Paul Grieselhuber
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