Node.js иловани серверда node server.js билан ишга тушириш синов учун етарли, лекин реал лойиҳада бу йўл тез орада муаммога олиб келади. Код ичидаги кутилмаган хато бутун жараённи тўхтатади, SSH уланиш узилганда илова ҳам ўчади, сервер қайта юкланганда эса уни кимдир қўлда қайта ишга тушириши керак бўлади. PM2 айнан шу вазифаларни ўз зиммасига оладиган жараён менежери. У иловани фонда ушлайди, йиқилса дарҳол қайта кўтаради ва барча чиқишни лог файлларга ёзиб боради.
PM2 ўрнатиш ва биринчи ишга тушириш
PM2 npm орқали глобал пакет сифатида ўрнатилади. Бунинг учун серверда Node.js аллақачон ўрнатилган бўлиши керак. Ўрнатгандан кейин иловани битта буйруқ билан ишга тушириш ва унга тушунарли ном бериш мумкин, шунда кейинчалик уни номи орқали бошқарасиз.
npm install -g pm2
cd /var/www/misol-app
pm2 start server.js --name misol-app
pm2 list
pm2 list жадвали ҳар бир жараённинг ҳолати, неча марта қайта ишга тушгани, ишлатаётган процессор ва хотира миқдорини кўрсатади. Агар "restart" устунидаги сон тез ўсиб бораётган бўлса, демак илова ишга тушиши билан хато бериб йиқиляпти ва логларни текшириш вақти келди.
Ecosystem файли: созламаларни бир жойда сақлаш
Буйруқ қаторига ҳар сафар ўнлаб параметр ёзиш ноқулай ва хатога олиб келади. PM2 бунинг ўрнига ecosystem файлидан фойдаланишни таклиф қилади. Бу файл лойиҳа папкасида туради, Git'да сақланади ва жамоанинг ҳар бир аъзоси иловани бир хил созламалар билан ишга туширади. Қуйидаги мисолда порт, муҳит ўзгарувчилари ва хотира чегараси кўрсатилган.
// ecosystem.config.js
module.exports = {
apps: [{
name: "misol-app",
script: "server.js",
cwd: "/var/www/misol-app",
instances: 1,
max_memory_restart: "300M",
env: {
NODE_ENV: "production",
PORT: 3000
}
}]
};
pm2 start ecosystem.config.js
pm2 restart ecosystem.config.js --update-env
max_memory_restart параметри илова белгиланган хотира миқдоридан ошиб кетса, уни автоматик қайта ишга туширади. Бу хотира оқиши бор иловаларда серверни тўлиқ чўкиб қолишдан сақлайди, лекин муаммонинг ўзини ҳал қилмайди, шунинг учун сабабини кодда излаш керак. --update-env эса ўзгартирилган муҳит ўзгарувчиларини қайта ўқишга мажбур қилади.
Логлар билан ишлаш
PM2 ҳар бир илова учун икки хил лог юритади: оддий чиқиш ва хатолар. Улар стандарт ҳолатда фойдаланувчининг ~/.pm2/logs папкасида сақланади. Жонли кузатиш учун pm2 logs буйруғи қулай, охирги бир неча юз қаторни кўриш учун эса --lines параметри ишлатилади.
pm2 logs misol-app
pm2 logs misol-app --lines 200
pm2 flush misol-app
Вақт ўтиши билан лог файллар катта ҳажмга етиб, дискни тўлдириб қўйиши мумкин. Бунинг олдини олиш учун лог айланишини созлайдиган модулни ўрнатиш тавсия этилади. У эски логларни сиқиб, белгиланган сондан ортиқларини ўчириб боради.
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 7
Кластер режим: барча ядролардан фойдаланиш
Node.js битта жараёнда асосан битта процессор ядросидан фойдаланади. Серверда бир нечта ядро бўлса, PM2 кластер режими илованинг бир нечта нусхасини ишга тушириб, кирувчи сўровларни улар орасида тақсимлайди. Бу режим фақат ҳолатини хотирада сақламайдиган иловаларга мос келади: сессиялар Redis ёки базада сақланиши керак, акс ҳолда фойдаланувчи ҳар сафар бошқа нусхага тушиб, тизимдан чиқиб кетади.
pm2 start server.js --name misol-app -i max
pm2 reload misol-app
reload буйруғи нусхаларни бирма-бир янгилайди, шунинг учун янги кодни жойлашда сайтингиз бир лаҳза ҳам ўчмайди. Оддий restart эса барча нусхаларни бирданига тўхтатиб қайта ёқади.
Сервер қайта юкланганда автоматик ишга тушиш
PM2 ўзи ҳам тизим юкланганда ишга тушиши керак, акс ҳолда сервер қайта юклангандан кейин ҳеч бир илова ишламайди. Бунинг учун икки қадам бажарилади: аввал startup скрипти яратилади, кейин жорий жараёнлар рўйхати сақланади.
pm2 startup
# ekranda chiqqan sudo env PATH=... buyrug'ini nusxalab bajaring
pm2 save
Кейинчалик янги илова қўшсангиз ёки бирортасини ўчирсангиз, pm2 save ни қайта бажаришни унутманг. Акс ҳолда сервер қайта юкланганда эски рўйхат тикланади.
Амалий мисол: хусусий мактаб сайти ва API
Тошкентдаги хусусий мактаб example.uz доменида иккита Node.js хизматига эга: ота-оналар учун баҳолар API'си ва Telegram орқали хабар юборувчи кичик ишчи. Иккаласи ҳам битта ecosystem файлида ёзилган, API кластер режимда икки нусхада, ишчи эса битта нусхада ишлайди. Чораклик баҳолар чиққан куни сўровлар кўпайганда API нусхалари юкни бўлишиб олади, хотира чегараси эса хотира оқиши бўлса ҳам серверни ҳимоя қилади. Дастурчи янги версияни жойлашда фақат git pull ва pm2 reload ecosystem.config.js бажаради.
Nginx билан бирга ишлатиш
PM2 иловани ишлатади, лекин уни интернетга тўғридан-тўғри очиш ўрнига олдига Nginx қўйиш яхшироқ. Nginx 80 ва 443 портларни қабул қилади, SSL сертификатини улайди ва сўровларни ичкаридаги 3000 портга узатади. Қуйида энг оддий прокси созламаси келтирилган.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Бундай созлаш учун root ҳуқуқи бор сервер керак бўлади. sayt.uz кабинетидан VPS олиб, унга Node.js, PM2 ва Nginx ўрнатсангиз, юқоридаги барча қадамларни тўлиқ назорат билан бажаришингиз мумкин.