Esportate il vostro sito Next.js senza subire DDOS
Paul Grieselhuber
Questa era la nostra situazione quando ci siamo avvicinati al lancio di un recente sito web di grandi contenuti alimentato da Next.js. Mancavano circa 3 settimane al lancio e volevamo iniziare la configurazione del server di produzione, la distribuzione di prova, le esportazioni, ecc.
Tutto è filato liscio fino a quando non siamo arrivati alla parte di distribuzione delle esportazioni statiche di Next.js. Finora nel progetto, il nostro team aveva sempre eseguito i test di esportazione statica dalle proprie macchine di sviluppo locali, che si trovavano a una certa distanza fisica dal server di produzione. Una distanza tale da rendere improbabile che le macchine di sviluppo sovraccaricassero il server di produzione (dove si trovano le API del progetto).
Se state ancora cercando di configurare le esportazioni statiche nel vostro progetto, date un'occhiata al nostro dettagliato post sul blog di WPGraphQL.
L'errore preferito da tutti: 502
Non appena abbiamo lanciato l'esportazione dallo stesso server dell'API, i nostri terminali si sono riempiti di errori 502, in particolare:
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 }
Si trattava di una WPGraphQL (our review) API, eseguita da un sito Wordpress. Se avete costruito siti Wordpress su larga scala per un po' di tempo, probabilmente potete indovinare l'errore che abbiamo ricevuto da 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"
Se vi siete imbattuti in un errore 502 su un sito Wordpress, sapete anche che la vostra giornata è stata appena rovinata. Esiste un numero pressoché infinito di cause a cui questo errore potrebbe riferirsi.
De-DDOS te stesso
Dopo aver discusso con @p-k su Spectrum (ht per l'eccellente lavoro di ricerca), è emerso chiaramente che il problema è che il processo di esportazione di Next.js viene eseguito su più thread e, a causa della vicinanza delle applicazioni e della velocità di esecuzione, ogni volta che si esporta il sito si va in DDOS.
Dal momento che abbiamo in programma di esportare più volte al giorno, man mano che i contenuti del sito vengono aggiornati, questo sarebbe stato ovviamente un problema non risolvibile. Questo è anche il motivo per cui non costruiamo il sito in locale e distribuiamo semplicemente il sito esportato in produzione.
Quindi, dobbiamo dire a Next.js di funzionare su un numero minore di thread e con una minore concurrency per poter costruire con successo questo sito sul server di produzione.
È abbastanza semplice: aggiornare le opzioni di package.json
file, specifically the export script to include the --threads
and --concurrency
, per esempio:
{
"scripts": {
...
"export": "next export --threads 1 --concurrency 1",
...
},
...
}
Questo dovrebbe risolvere il problema, ma comporterà tempi di esportazione molto più lenti. I nostri sono passati da circa 10-12 minuti a circa 60 minuti. Ulteriori test ci aiuteranno a determinare cosa può gestire l'API in termini di thread aggiuntivi e di maggiore concorrenza. Nel frattempo, questo raggiunge il nostro obiettivo di più build al giorno.
Il prossimo post della nostra serie sulla costruzione di siti statici Next.js, Next.js + Client Apollo multipli e sorgenti GraphQL