
วิธีเริ่มต้นใช้งาน VUE3.0 อย่างรวดเร็ว: เข้าสู่การเรียนรู้
หลังจากที่บริการของเราเปิดตัวแล้ว สภาพแวดล้อมที่ทำงานอยู่จะถูกกำหนดเวลาอย่างหลีกเลี่ยงไม่ได้ (เช่น คอนเทนเนอร์, pm2 เป็นต้น) การอัปเกรดบริการจะทำให้รีสตาร์ท และข้อยกเว้นต่างๆ จะทำให้ กระบวนการที่จะล้มเหลว โดยทั่วไป สภาพแวดล้อมที่ทำงานอยู่จะมีการตรวจสอบสุขภาพของกระบวนการบริการจะรีสตาร์ทกระบวนการเมื่อกระบวนการผิดปกติ อย่างไรก็ตาม กลยุทธ์การจัดกำหนดการของสภาพแวดล้อมที่ทำงานอยู่จะถือว่ากระบวนการบริการของเราเป็นเหมือนกล่องดำ และไม่สนใจสภาพการทำงานภายในของกระบวนการบริการ ดังนั้น กระบวนการบริการของเราจำเป็นต้องรับรู้ถึงการดำเนินการตามกำหนดการของสภาพแวดล้อมที่ทำงานอยู่อย่างจริงจัง จากนั้นจึงดำเนินการ ออกจากการดำเนินการล้างข้อมูลบางส่วน
ดังนั้นวันนี้เราจะแยกแยะสถานการณ์ต่างๆ ที่อาจทำให้กระบวนการ Node.js ออก และสิ่งที่เราสามารถทำได้โดยการฟังเหตุการณ์การออกจากกระบวนการเหล่านี้
หลักการ:
เมื่อกระบวนการต้องการออก จะไม่มีสิ่งใดมากไปกว่าสองสถานการณ์ หนึ่งคือ กระบวนการออกอย่างแข็งขัน และอีกประการหนึ่งคือ ได้รับสัญญาณของระบบที่กำหนดให้กระบวนการออก
ออกจากการแจ้งเตือนสัญญาณระบบ
สัญญาณระบบทั่วไปแสดงอยู่ในเอกสารอย่างเป็นทางการของ Node.js โดยหลักๆ แล้วเราจะเน้นไปที่สัญญาณบางส่วน:
เมื่อได้รับสัญญาณออกที่ไม่บังคับ กระบวนการ Node.js จะสามารถฟังสัญญาณทางออกและดำเนินการตรรกะการออกแบบกำหนดเองบางอย่างได้ ตัวอย่างเช่น เราเขียนเครื่องมือ cli ที่ใช้เวลานานในการดำเนินการงาน หากผู้ใช้ต้องการออกจากกระบวนการโดยการกด Ctrl+c ก่อนที่งานจะเสร็จสิ้น ผู้ใช้จะได้รับแจ้งให้รอ:
const readline = need(' อ่านบรรทัด');
process.on('SIGINT', () => {
// เราใช้ readline เพื่อใช้งานการโต้ตอบในบรรทัดคำสั่ง const rl = readline.createInterface({
อินพุต: กระบวนการ.stdin,
เอาท์พุต: process.stdout
-
rl.question('งานยังไม่เสร็จสิ้น คุณแน่ใจหรือไม่ว่าต้องการออก', answer => {
ถ้า (ตอบ === 'ใช่') {
console.log('การดำเนินการงานถูกขัดจังหวะ, ออกจากกระบวนการ');
กระบวนการออก (0);
} อื่น {
console.log('งานดำเนินต่อไป...');
-
rl.ปิด();
-
-
// จำลองงานที่ใช้เวลา 1 นาทีในการดำเนินการ const longTimeTask = () => {
console.log('เริ่มงาน...');
setTimeout(() => {
console.log('สิ้นสุดงาน');
}, 1,000 * 60);
-
longTimeTask(); ทุกครั้งที่กด ctrl + c ผู้ใช้จะได้รับแจ้ง:

กระบวนการออกจาก
Node.js อย่างแข็งขัน โดยส่วนใหญ่รวมถึงสถานการณ์ต่อไปนี้:
เรารู้ว่า pm2 มีผลกระทบต่อกระบวนการ daemon ในกรณีของคุณ เมื่อกระบวนการของคุณออกโดยมีข้อผิดพลาด pm2 จะรีสตาร์ทกระบวนการของคุณ กระบวนการลูกในโหมดคลัสเตอร์ของ Node.js (จริงๆ แล้ว pm2 มีตรรกะที่คล้ายกัน):
constคลัสเตอร์ = need('cluster' );
const http = ต้องการ ('http');
const numCPUs = ต้องการ ('os'). cpus (). ความยาว;
กระบวนการ const = ต้องการ ('กระบวนการ');
// รหัสกระบวนการหลักถ้า (cluster.isMaster) {
console.log(`เริ่มกระบวนการหลัก: ${process.pid}`);
// ขึ้นอยู่กับจำนวนคอร์ cpu ให้สร้างกระบวนการทำงานสำหรับ (ให้ i = 0; i < numCPUs; i++) {
คลัสเตอร์.ส้อม();
-
// ฟังเหตุการณ์ออกจากกระบวนการของผู้ปฏิบัติงานคลัสเตอร์on('exit', (ผู้ปฏิบัติงาน, รหัส, สัญญาณ) => {
console.log(`ออกจากกระบวนการของผู้ปฏิบัติงาน ${worker.process.pid} แล้ว รหัสข้อผิดพลาด: ${code || signal} กำลังรีสตาร์ท...`);
//รีสตาร์ทกระบวนการลูกคลัสเตอร์.fork();
-
-
// รหัสกระบวนการของผู้ปฏิบัติงานถ้า (cluster.isWorker) {
// ฟังเหตุการณ์ข้อผิดพลาดที่ไม่ได้ตรวจสอบ process.on('uncaughtException', error => {
console.log(`เกิดข้อผิดพลาดในกระบวนการของผู้ปฏิบัติงาน ${process.pid}`, ข้อผิดพลาด);
process.emit('ตัดการเชื่อมต่อ');
กระบวนการทางออก (1);
-
//สร้างเว็บเซิร์ฟเวอร์
// แต่ละกระบวนการของผู้ปฏิบัติงานจะฟังพอร์ต 8000 (Node.js จะจัดการภายในและจะไม่ทำให้เกิดความขัดแย้งของพอร์ต)
http.createServer((req, res) => {
res.writeHead(200);
res.end('สวัสดีชาวโลกn');
}).ฟัง(8000);
console.log(`เริ่มกระบวนการของผู้ปฏิบัติงาน: ${process.pid}`);
} แนวทางปฏิบัติของแอปพลิเคชัน
สถานการณ์ต่างๆ ที่กระบวนการ Node.js ได้รับการวิเคราะห์ข้างต้น ตอนนี้เราจะสร้างเครื่องมือสำหรับตรวจสอบการออกจากกระบวนการ เมื่อกระบวนการ Node.js ออกจากระบบ ผู้ใช้จะได้รับอนุญาตให้ดำเนินการตรรกะทางออกของตนเอง:
// exit-hook.js
//บันทึกงานทางออกที่ต้องดำเนินการ const งาน = [];
//เพิ่มงานทางออก const addExitTask = fn => Tasks.push(fn);
const handleExit = (รหัส ข้อผิดพลาด) => {
// ...การใช้งาน handleExit แสดงไว้ด้านล่าง};
//ฟังเหตุการณ์ทางออกต่างๆ process.on('exit', code => handleExit(code));
// ตามข้อกำหนด POSIX เราใช้หมายเลขสัญญาณ 128 + เพื่อรับรหัสทางออกสุดท้าย // โปรดดูภาพด้านล่างสำหรับหมายเลขสัญญาณ คุณสามารถดำเนินการ kill -l ภายใต้ระบบ Linux เพื่อดูกระบวนการหมายเลขสัญญาณทั้งหมด ('SIGHUP', () => handleExit(128 + 1));
process.on('SIGINT', () => handleExit(128 + 2));
process.on('SIGTERM', () => handleExit(128 + 15));
// กด ctrl+break เพื่อออกจากกระบวนการสัญญาณ on('SIGBREAK', () => handleExit(128 + 21));
// รหัสออก 1 แสดงถึงข้อผิดพลาดที่ไม่ได้ตรวจจับซึ่งทำให้กระบวนการออกจากกระบวนการ on('uncaughtException', error => handleExit(1, error));
process.on('unhandledRejection', error => handleExit(1, error)) ;

ต่อไปเราจำเป็นต้องใช้ฟังก์ชัน exit ของกระบวนการจริง handleExit เนื่องจากฟังก์ชันงานที่ส่งผ่านโดยผู้ใช้อาจเป็นแบบซิงโครนัสหรือแบบอะซิงโครนัส เราสามารถใช้ process.nextTick เพื่อให้แน่ใจว่าโค้ดการซิงโครไนซ์ของผู้ใช้ได้รับการดำเนินการ ซึ่งสามารถเข้าใจกระบวนการได้ง่าย .nextTick จะถูกดำเนินการหลังจากการเรียกใช้โค้ดซิงโครนัสในแต่ละขั้นตอนลูปเหตุการณ์เสร็จสมบูรณ์ (เข้าใจ process.nextTick) สำหรับงานอะซิงโครนัส เราต้องการให้ผู้ใช้โทรกลับเพื่อแจ้งให้เราทราบว่างานอะซิงโครนัสเสร็จสมบูรณ์แล้ว:
// ทำเครื่องหมายว่า กำลังออก หลีกเลี่ยงการดำเนินการหลายครั้งของ la isExiting = false;
const handleExit = (รหัส ข้อผิดพลาด) => {
ถ้า (isExiting) กลับมา;
กำลังออก = จริง;
// ทำเครื่องหมายว่ามีการดำเนินการออกเพื่อหลีกเลี่ยงการเรียกหลายครั้งเพื่อให้ hasDoExit = fasle;
const doExit = () => {
ถ้า (hasDoExit) กลับมา;
hasDoExit = จริง
process.nextTick(() => กระบวนการทางออก (รหัส))
-
// บันทึกจำนวนงานอะซิงโครนัสที่มีให้ asyncTaskCount = 0;
// หลังจากที่งานอะซิงโครนัสสิ้นสุดลง การโทรกลับที่ผู้ใช้จำเป็นต้องโทรให้ la ayncTaskCallback = () => {
process.nextTick(() => {
asyncTaskCount--
ถ้า (asyncTaskCount === 0) doExit()
-
-
//ดำเนินการภารกิจทางออกทั้งหมดforEach(taskFn => {
// หากจำนวนพารามิเตอร์ของฟังก์ชัน taskFn มากกว่า 1 จะถือว่าพารามิเตอร์การเรียกกลับถูกส่งไปและเป็นงานแบบอะซิงโครนัสถ้า (taskFn.length > 1) {
asyncTaskCount++
TaskFn (ข้อผิดพลาด ayncTaskCallback)
} อื่น {
TaskFn (ข้อผิดพลาด)
-
-
// หากมีงานอะซิงโครนัสถ้า (asyncTaskCount > 0) {
// หลังจากผ่านไปมากกว่า 10 วินาที ให้บังคับออกจาก setTimeout(() => {
ทำออก();
}, 10 * 1,000)
} อื่น {
ทำออก()
-
}; ณ จุดนี้ เครื่องมือตรวจสอบการออกจากกระบวนการของเราเสร็จสมบูรณ์ คุณสามารถดูกระบวนการนี้ แบบ async-exit-hook ได้
อย่าง
สมบูรณ์ ออกจาก
เว็บเซิร์ฟเวอร์ของเรา เมื่อรีสตาร์ท ถูกกำหนดเวลาโดยคอนเทนเนอร์ที่ทำงานอยู่ (pm2 หรือนักเทียบท่า ฯลฯ) หรือเมื่อมีข้อยกเว้นเกิดขึ้นและกระบวนการออก เราหวังว่าจะดำเนินการออก เช่น ดำเนินการตอบสนองต่อคำขอที่เชื่อมต่อกับ บริการ, ทำความสะอาดการเชื่อมต่อฐานข้อมูล, พิมพ์บันทึกข้อผิดพลาด, เรียกใช้การแจ้งเตือน ฯลฯ หลังจากเสร็จสิ้นการดำเนินการออกแล้วออกจากกระบวนการ เราสามารถใช้เครื่องมือตรวจสอบการออกจากกระบวนการเพื่อนำไปใช้:
const http = need(' http');
//สร้างเว็บเซิร์ฟเวอร์
เซิร์ฟเวอร์ const = http.createServer ((req, res) => {
res.writeHead(200);
res.end('สวัสดีชาวโลกn');
}).ฟัง(8000);
// ใช้เครื่องมือที่เราพัฒนาด้านบนเพื่อเพิ่มงานออกจากกระบวนการ addExitTask((error, callback) => {
// พิมพ์บันทึกข้อผิดพลาด, แจ้งเตือน, ปล่อยการเชื่อมต่อฐานข้อมูล ฯลฯ console.log ('กระบวนการออกอย่างผิดปกติ' ข้อผิดพลาด)
// หยุดรับคำขอใหม่ server.close((error) => {
ถ้า (ข้อผิดพลาด) {
console.log('หยุดรับคำขอใหม่ผิดพลาด' ข้อผิดพลาด)
} อื่น {
console.log('หยุดรับคำขอใหม่')
-
-
// วิธีที่ง่ายกว่าคือการรอช่วงระยะเวลาหนึ่ง (ที่นี่เรารอ 5 วินาที) เพื่อให้คำขอที่มีอยู่เสร็จสมบูรณ์ // หากคุณต้องการให้แน่ใจว่าคำขอทั้งหมดได้รับการประมวลผลอย่างสมบูรณ์ คุณต้องบันทึกการเชื่อมต่อแต่ละรายการและรอจนกระทั่ง การเชื่อมต่อทั้งหมดจะถูกปล่อยออกมา ดำเนินการออกคำสั่ง // คุณสามารถอ้างถึงไลบรารีโอเพ่นซอร์ส https://github.com/sebhildebrandt/http-graceful-shutdown
setTimout (โทรกลับ, 5 * 1,000)
}) สรุป
จากข้อความข้างต้น ฉันเชื่อว่าคุณคงทราบถึงสถานการณ์ต่างๆ ที่ทำให้กระบวนการ Node.js หยุดทำงานแล้ว หลังจากที่บริการออนไลน์แล้ว แม้ว่าเครื่องมือเช่น k8s และ pm2 จะสามารถดึงกระบวนการขึ้นมาได้อย่างต่อเนื่องเมื่อกระบวนการออกอย่างผิดปกติเพื่อให้แน่ใจว่ามีความพร้อมใช้งานของบริการ เราควรรับรู้ถึงความผิดปกติหรือการกำหนดเวลาของกระบวนการในโค้ดอย่างจริงจัง ดังนั้น เพื่อให้สามารถจับปัญหาได้ล่วงหน้า