Nikada ne biste trebali proizvoditi izravno protiv Node.js. Može biti.

Ponekad se zapitam znam li uopće išta o tome.

Prije samo nekoliko tjedana razgovarao sam s prijateljem koji je izravno spomenuo: "nikada ne biste pokrenuli aplikaciju izravno protiv Nodea u proizvodnji".

Energično sam kimnuo glavom dajući znak da se također nikad neću natjecati protiv Nodea u proizvodnji jer ... hahaha ... .svi to znaju. Ali ja to nisam znao! Jesam li to trebao znati?! ?? JESAM LI JOŠ DOZVOLJEN PROGRAMIRATI?

Kad bih nacrtao Vennov dijagram onoga što znam u odnosu na ono što osjećam kao što svi drugi znaju, izgledalo bi ovako ...

Usput, ta sitna točkica postaje sve manja što sam starija.

Postoji bolji dijagram koji je stvorila Alicia Liu koji mi je nekako promijenio život. Kaže da je više ovako ...

Jako volim ovaj dijagram jer želim da bude istinit. Ne želim provesti ostatak svog života kao sićušna, sve manja plava točka beznačajnosti.

TAKO DRAMATIČNO. Krivi Pandora. Ne kontroliram što će se dalje reproducirati dok pišem ovaj članak, a Dashboard Confessional je lijek za heluvu.

Pa, pod pretpostavkom da je Alicijin dijagram istinit, želio bih podijeliti s vama ono što sada znam o pokretanju Node aplikacija u proizvodnji. Možda se naši relativni Vennovi dijagrami na ovoj temi ne preklapaju.

Prvo se pozabavimo izjavom "nikada nemojte pokretati aplikacije izravno protiv Nodea u proizvodnji".

U proizvodnji se nikada nemojte izravno pokretati protiv Nodea

Može biti. Ali možda i nije. Razgovarajmo o obrazloženju ove izjave. Prvo, pogledajmo zašto ne.

Recimo da imamo jednostavan Express server. Najjednostavniji Express poslužitelj kojeg se mogu sjetiti ...

const express = require("express"); const app = express(); const port = process.env.PORT || 3000; // viewed at //localhost:3000 app.get("/", function(req, res) { res.send("Again I Go Unnoticed"); }); app.listen(port, () => console.log(`Example app listening on port ${port}!`));

Pokrenuli bismo ovo s početnom skriptom u package.jsondatoteci.

"scripts": { "dev": "npx supervisor index.js", "start": "node index.js" }

Ovdje postoje neka dva problema. Prvi je problem razvoja, a drugi problem proizvodnje.

Razvojni je problem u tome što kada mijenjamo kod, moramo zaustaviti i pokrenuti aplikaciju kako bismo pokupili naše promjene.

Da bismo to riješili, obično koristimo neku vrstu upravitelja procesa Node poput supervisorili nodemon. Ovi će paketi gledati naš projekt i ponovno pokretati naš poslužitelj kad god napravimo promjene. Obično to radim ovako ...

"scripts": { "dev": "npx supervisor index.js", "start": "node index.js"}

Tada trčim npm run dev. Imajte na umu da npx supervisorovdje radim što mi omogućuje korištenje supervisorpaketa bez potrebe za instaliranjem. I ❤️ 2019. Uglavnom.

Naš je drugi problem što još uvijek trčimo izravno protiv Nodea i već smo rekli da je to loše i sad ćemo otkriti zašto.

Ovdje ću dodati još jedan put koji pokušava pročitati datoteku s diska koja ne postoji. Ovo je pogreška koja se lako može pojaviti u bilo kojoj stvarnoj aplikaciji.

const express = require("express"); const app = express(); const fs = require("fs"); const port = process.env.PORT || 3000; // viewed at //localhost:3000 app.get("/", function(req, res) { res.send("Again I Go Unnoticed"); }); app.get("/read", function(req, res) { // this does not exist fs.createReadStream("my-self-esteem.txt"); }); app.listen(port, () => console.log(`Example app listening on port ${port}!`));

Ako ovo pokrenemo izravno protiv Nodea npm starti read odemo do krajnje točke, dobit ćemo pogrešku jer ta datoteka ne postoji.

Koji - nema veze, zar ne? To je jedna pogreška. Događa se.

NE. Velika stvar. Ako se vratite na terminal, vidjet ćete da je aplikacija potpuno propala.

Što znači da ako se vratite u preglednik i pokušate otići na korijenski URL web stranice, dobit ćete istu stranicu s pogreškom. Jedna pogreška u jednoj metodi oborila je aplikaciju za sve .

To je loše. Kao stvarno loše. To je jedan od glavnih razloga zašto ljudi kažu "nikad se nemojte izravno protiviti Nodeu u proizvodnji" .

U REDU. Dakle, ako ne možemo pokrenuti Node u proizvodnji, koji je pravi način za pokretanje Nodea u proizvodnji?

Opcije za proizvodni čvor

Imamo nekoliko mogućnosti.

Jedno od njih bilo bi jednostavno koristiti nešto poput supervisorili nodemonu proizvodnji na isti način na koji ih koristimo u razvoju. To bi uspjelo, ali ovi su alati malo lakši. Bolja opcija je nešto što se zove pm2.

pm2 spašavanje

pm2 je Node upravitelj procesa koji ima puno zvukova i zvižduka. Kao i sve ostalo "JavaScript", instalirate ga (globalno) iz npm- ili možete jednostavno koristiti npxponovno. Ne želim ti reći kako živjeti svoj život.

Postoji mnogo načina za pokretanje aplikacije s pm2. Najjednostavniji način je samo nazvati pm2 startsvoju ulaznu točku.

"scripts": { "start": "pm2 start index.js", "dev": "npx supervisor index.js" },

I vidjet ćete nešto slično u terminalu ...

To je naš postupak koji se odvija u pozadini i nadzire ga pm2. Ako posjetite readkrajnju točku i srušite program, pm2 će ga automatski ponovo pokrenuti. Ništa od toga nećete vidjeti na terminalu jer radi u pozadini. Ako želiš gledati kako pm2 radi svoje, moraš trčati pm2 log 0. To 0je ID procesa za koji želimo vidjeti zapisnike.

Idemo tamo! Možete vidjeti kako pm2 ponovno pokreće aplikaciju kad prestane raditi zbog naše neobrađene pogreške.

Također možemo izvući našu naredbu za razvoj i imati datoteke pm2 za gledanje za nas i ponovo pokrenuti sve promjene.

"scripts": { "start": "pm2 start index.js --watch", "dev": "npx supervisor index.js" },

Imajte na umu da, jer pm2 pokreće stvari u pozadini, ne možete se samo ctrl+cizvući iz pokrenutog procesa pm2. Morate to zaustaviti dodavanjem osobnog dokumenta ili imena.

pm2 stop 0

pm2 stop index

Također imajte na umu da pm2 zadržava referencu na postupak kako biste ga mogli ponovno pokrenuti.

Ako želite izbrisati tu referencu procesa, morate pokrenuti pm2 delete. Proces možete zaustaviti i izbrisati u jednoj naredbi pomoću delete.

pm2 delete index

Također možemo koristiti pm2 za pokretanje više procesa naše aplikacije. pm2 će automatski uravnotežiti opterećenje u tim instancama.

Višestruki procesi s načinom rada vilice pm2

pm2 ima mnoštvo mogućnosti konfiguracije, a one su sadržane u datoteci "ekosustav". Da biste ga stvorili, pokrenite pm2 init. Dobit ćete nešto poput ovoga ...

module.exports = { apps: [ { name: "Express App", script: "index.js", instances: 4, autorestart: true, watch: true, max_memory_restart: "1G", env: { NODE_ENV: "development" }, env_production: { NODE_ENV: "production" } } ] };

Zanemarit ću odjeljak "implementacija" u ovom članku, jer nemam pojma što čini.

U odjeljku "aplikacije" definirate aplikacije koje želite da pm2 pokreće i nadgleda. Možete pokrenuti više njih. Mnogo ovih postavki konfiguracije vjerojatno je samo po sebi razumljivo. Ovdje se želim usredotočiti na postavljanje instanci .

pm2 can run multiple instances of your application. You can pass in a number of instances that you want to run and pm2 will spin up that many. So if we wanted to run 4 instances, we could have the following configuration file.

module.exports = { apps: [ { name: "Express App", script: "index.js", instances: 4, autorestart: true, watch: true, max_memory_restart: "1G", env: { NODE_ENV: "development" }, env_production: { NODE_ENV: "production" } } ] };

Then we just run it with pm2 start.

pm2 is now running in “cluster” mode. Each of these processes is running on a different CPU on my machine, depending on how many cores I have. If we wanted to run a process for each core without knowing how many cores we have, we can just pass the max parameter to the instances value.

{ ... instances: "max", ... }

Let’s find out how many cores I’ve got in this machine.

8 CORES! Holy crap. I’m gonna install Subnautica on my Microsoft issued machine. Don’t tell them I said that.

The good thing about running processes on separate CPU’s is that if you have a process that runs amok and takes up 100% of the CPU, the others will still function. If you pass in more instances than you have cores, pm2 will double up processes on CPU’s as necessary.

You can do a WHOLE lot more with pm2, including monitoring and otherwise wrangling those pesky environment variables.

One other item of note: if for some reason you want pm2 to run your npm start script, you can do that by running npm as the process and passing the -- start. The space before the “start” is super important here.

pm2 start npm -- start

In Azure AppService, we include pm2 by default in the background. If you want to use pm2 in Azure, you don’t need to include it in your package.json file. You can just add an ecosystem file and you’re good to go.

OK! Now that we’ve learned all about pm2, let’s talk about why you may not want to use it and it might indeed be ok to run directly against Node.

Running directly against Node in production

I had some questions on this so I reached out to Tierney Cyren who is part of the enormous orange circle of knowledge, especially when it comes to Node.

Tierney pointed out a few drawbacks to using Node based process managers like pm2.

The main reason is that you shouldn’t use Node to monitor Node. You don’t want to use the thing that you are monitoring to monitor that thing. It’s kind of like you asking my teenage son to supervise himself on a Friday night: Will that end badly? It might, and it might not. But you’re about to find out the hard way.

Tierney recommends that you not have a Node process manager running your application at all. Instead, have something at a higher level which watches multiple separate instances of your application. For example, an ideal setup would be if you had a Kubernetes cluster with your app running on separate containers. Kubernetes can then monitor those containers and if any of them go down, it can bring them back and report on their health.

In this case, you can run directly against Node because you are monitoring at a higher level.

As it turns out, Azure is already doing this. If we don’t push a pm2 ecosystem file to Azure, it will start the application with our package.json file start script and we can run directly against Node.

"scripts": { "start": "node index.js" }

In this case, we are running directly against Node and it’s OK. If the application were to crash, you’ll notice that it comes back. That’s because in Azure, your app runs in a container. Azure is orchestrating the container in which your app is running and knows when it faceplants.

But you still only have one instance here. It takes the container a second to come back online after it crashes meaning that there could be a few seconds of downtime for your users.

Ideally, you would want more than one container running. The solution to this would be to deploy multiple instances of your application to multiple Azure AppService sites and then use Azure Front Door to load balance the apps behind a single IP address. Front Door will know when a container is down and will route traffic to other healthy instances of your application.

Azure Front Door Service | Microsoft Azure

Deliver, protect and track the performance of your globally distributed microservice applications with Azure Front Door…azure.microsoft.com

systemd

Another suggestion that Tierney had is to run Node with systemd. I don’t understand too much (or anything at all) about systemd and I’ve already messed this phrasing up once already, so I’ll let Tierney say it in his own words…

Ova je opcija moguća samo ako imate pristup Linuxu u svojoj implementaciji i ako kontrolirate način pokretanja Nodea na razini usluge. Ako svoj Node.js postupak izvodite u dugotrajnom Linux VM-u, poput Azure VM-a, na dobrom ste mjestu za pokretanje Node.js-a sa systemd. Ako samo razmeštate datoteke na usluzi poput Azure AppService ili Heroku ili se pokrećete unutar kontejneriziranog okruženja poput Azure Container Instance, vjerojatno biste se trebali kloniti ove mogućnosti.

Pokretanje aplikacije Node.js sa Systemd - 1. dio

Sljedeću sjajnu aplikaciju napisali ste u Nodeu i spremni ste je predstaviti svijetu. Što znači da možete ... nodesource.com

Node.js radne niti

Tierney also wants you to know that Worker Threads are coming in Node. This will allow you to start your app on multiple “workers” (threads) thusly negating the need for something like pm2. Maybe. I don’t know. I didn’t really read the article.

Node.js v11.14.0 Documentation

The worker_threads module enables the use of threads that execute JavaScript in parallel. To access it: const worker =…nodejs.org

Be an Adult

Tierney’s last suggestion was to just handle the error and write some tests like an adult. But who has time for that?

The tiny circle abides

Now you know most of what is in the tiny blue circle. The rest is just useless facts about emo bands and beer.

For more information on pm2, Node and Azure, check out the following resources…

  • //pm2.keymetrics.io/
  • Node.js deployment on VS Code
  • Deploy a simple Node site to Azure