Exportieren Sie Ihre Next.js-Website, ohne sich selbst zu DDOSen
Paul Grieselhuber
So sah unsere Situation aus, als wir uns dem Start einer neuen Next.js-basierten Website mit umfangreichen Inhalten näherten. Wir waren etwa 3 Wochen vor dem Start und wollten mit der Einrichtung des Produktionsservers, der Testbereitstellung, den Exporten usw. beginnen.
Alles lief reibungslos, bis wir zu den statischen Exporten von Next.js kamen, die Teil des Deployments waren. Bislang hatte unser Team die statischen Exporttests immer von den lokalen Entwicklungsrechnern aus durchgeführt, die weit vom Produktionsserver entfernt waren. So weit, dass es unwahrscheinlich war, dass die Entwicklungsmaschinen den Produktionsserver (den Ort der API für das Projekt) überlasten würden.
Wenn Sie immer noch versuchen, statische Exporte für Ihr Projekt einzurichten, lesen Sie unseren detailed Beitrag im WPGraphQL Blog.
Jedermanns Lieblingsfehler: 502
Kaum hatten wir den Export vom gleichen Server wie die API gestartet, füllten sich unsere Terminals mit 502-Fehlern, insbesondere:
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 }
Dies war eine WPGraphQL (our review) API, die von einer Wordpress-Website aus ausgeführt wurde. Wenn Sie seit einiger Zeit Wordpress-Websites in größerem Umfang erstellen, können Sie wahrscheinlich den Fehler erraten, den wir von PHP erhielten:
[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"
Wenn Sie schon einmal einen 502-Fehler auf einer Wordpress-Website gesehen haben, wissen Sie auch, dass Ihr Tag ruiniert ist. Es gibt eine fast unendliche Anzahl von Ursachen, auf die sich dieser Fehler beziehen könnte.
De-DDOS selbst
Nach einer Diskussion mit @p-k auf Spectrum (ht für die exzellente Recherche) wurde klar, dass das Problem hier darin besteht, dass der Next.js-Exportprozess in mehreren Threads abläuft, und aufgrund der Nähe der Anwendungen und der Ausführungsgeschwindigkeit führen Sie im Grunde jedes Mal, wenn Sie Ihre Website exportieren, ein DDOS durch.
Da wir planen, mehrmals am Tag zu exportieren, wenn die Inhalte der Website aktualisiert werden, wäre das natürlich ein Ding der Unmöglichkeit gewesen. Das ist auch der Grund, warum wir die Site nicht lokal erstellen und die exportierte Site einfach in die Produktion überführen.
Wir müssen also Next.js anweisen, auf weniger Threads und mit geringerer Gleichzeitigkeit zu laufen, um die Website erfolgreich auf dem Produktionsserver zu erstellen.
Das ist ganz einfach: Aktualisieren Sie zum Beispiel Ihre package.json
file, specifically the export script to include the --threads
and --concurrency
Optionen:
{
"scripts": {
...
"export": "next export --threads 1 --concurrency 1",
...
},
...
}
Damit sollte das Problem gelöst sein, aber die Exportzeiten werden dadurch viel langsamer. Bei uns ging es von etwa 10-12 Minuten auf etwa 60 Minuten. Weitere Tests werden uns helfen herauszufinden, was die API in Bezug auf zusätzliche Threads und höhere Gleichzeitigkeit bewältigen kann. In der Zwischenzeit haben wir unser Ziel, mehrere Builds pro Tag zu erstellen, erreicht.
Lesen Sie den nächsten Beitrag in unserer Serie über die Erstellung statischer Next.js-Sites, Next.js + Multiple Apollo Clients & GraphQL Sources