Cau Hoi Phong Van Backend Node.js: Huong Dan Day Du 2026

25 cau hoi phong van backend Node.js thuong gap nhat. Event loop, async/await, streams, clustering va hieu suat duoc giai thich chi tiet.

Cau Hoi Phong Van Backend Node.js - Huong Dan Day Du

Phong van backend Node.js danh gia su hieu biet ve co che noi bo cua runtime, kha nang lam chu cac mau bat dong bo va thiet ke ung dung co hieu suat cao. Huong dan nay bao gom cac cau hoi thuong gap nhat, tu kien thuc co ban den cac khai niem san xuat nang cao.

Meo Phong Van

Nha tuyen dung danh gia cao nhung cau tra loi ket hop ly thuyet voi vi du thuc te. Voi moi cau hoi, minh hoa bang doan ma hoac tinh huong cu the cho thay kinh nghiem thuc tien.

Kien Thuc Co Ban Node.js

Cau Hoi 1: Event Loop la gi va no hoat dong nhu the nao?

Event Loop la co che cot loi cho phep Node.js xu ly cac thao tac bat dong bo theo kieu non-blocking mac du chay tren mot luong duy nhat. No dieu phoi viec thuc thi ma JavaScript, callback va event.

event-loop-demo.jsjavascript
// Demonstration of Event Loop execution order

console.log('1. Script start (synchronous)');

// setTimeout goes to the Timer Queue
setTimeout(() => {
  console.log('5. setTimeout callback (Timer Queue)');
}, 0);

// setImmediate goes to the Check Queue
setImmediate(() => {
  console.log('6. setImmediate callback (Check Queue)');
});

// Promise goes to the Microtask Queue (priority)
Promise.resolve().then(() => {
  console.log('3. Promise.then (Microtask Queue)');
});

// process.nextTick has the highest priority
process.nextTick(() => {
  console.log('2. process.nextTick (nextTick Queue)');
});

console.log('4. Script end (synchronous)');

// Output order: 1, 4, 2, 3, 5, 6

Event Loop tuan theo mot thu tu chinh xac khi xu ly cac hang doi: truoc het la ma dong bo, sau do nextTick, microtask (Promise), timer, callback I/O, setImmediate, va cuoi cung la callback close.

Cau Hoi 2: Su khac biet giua process.nextTick() va setImmediate() la gi?

Cau hoi nay danh gia su hieu biet chi tiet ve muc do uu tien thuc thi trong Event Loop.

nextTick-vs-immediate.jsjavascript
// Behavior comparison

// process.nextTick executes BEFORE the next Event Loop phase
process.nextTick(() => {
  console.log('nextTick 1');
  process.nextTick(() => {
    console.log('nextTick 2 (nested)');
  });
});

// setImmediate executes in the Check phase of the Event Loop
setImmediate(() => {
  console.log('setImmediate 1');
  setImmediate(() => {
    console.log('setImmediate 2 (nested)');
  });
});

// Output: nextTick 1, nextTick 2, setImmediate 1, setImmediate 2

process.nextTick() duoc xu ly ngay sau thao tac hien tai, truoc khi Event Loop tiep tuc. Su dung qua nhieu co the chan Event Loop. setImmediate() de doan hon va duoc khuyen dung de hoan thuc thi.

Canh Bao Starvation

Goi de quy process.nextTick() co the lam Event Loop bi doi va ngan chan xu ly I/O. Hay dung setImmediate() cho cac thao tac khong quan trong.

Cau Hoi 3: Node.js xu ly loi trong ma bat dong bo nhu the nao?

Xu ly loi bat dong bo khac biet co ban so voi ma dong bo. Neu khong xu ly dung cach, mot loi co the lam ung dung bi crash.

error-handling.jsjavascript
// Asynchronous error handling patterns

// Pattern 1: Callbacks with error-first convention
function readFileCallback(path, callback) {
  const fs = require('fs');
  fs.readFile(path, 'utf8', (err, data) => {
    if (err) {
      // Error is ALWAYS the first argument
      return callback(err, null);
    }
    callback(null, data);
  });
}

// Pattern 2: Promises with catch
async function readFilePromise(path) {
  const fs = require('fs').promises;
  try {
    const data = await fs.readFile(path, 'utf8');
    return data;
  } catch (err) {
    // Centralized error handling
    console.error(`File read error: ${err.message}`);
    throw err; // Re-throw for propagation
  }
}

// Pattern 3: Global handling of unhandled rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled rejection:', reason);
  // In production: log and graceful shutdown
});

// Pattern 4: Handling uncaught exceptions
process.on('uncaughtException', (err) => {
  console.error('Uncaught exception:', err);
  // CRITICAL: always terminate the process after
  process.exit(1);
});

Trong moi truong san xuat, moi Promise phai co .catch() hoac nam trong khoi try/catch. Cac handler toan cuc dong vai tro la luoi an toan, khong phai giai phap chinh.

Lap Trinh Bat Dong Bo va Dong Thoi

Cau Hoi 4: Giai thich su khac biet giua song song va dong thoi trong Node.js

Node.js co tinh dong thoi nhung khong song song theo mac dinh. Su phan biet nay la nen tang de hieu ve hieu suat.

concurrency-vs-parallelism.jsjavascript
// CONCURRENCY: multiple tasks progress by alternating (single-thread)
async function concurrentTasks() {
  console.time('concurrent');

  // These calls are concurrent, not parallel
  const results = await Promise.all([
    fetch('https://api.example.com/users'),    // Non-blocking I/O
    fetch('https://api.example.com/products'), // Non-blocking I/O
    fetch('https://api.example.com/orders'),   // Non-blocking I/O
  ]);

  console.timeEnd('concurrent'); // ~time of the longest request
  return results;
}

// PARALLELISM: with Worker Threads for CPU-bound tasks
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
  // Main thread delegates CPU-intensive work
  async function parallelComputation() {
    console.time('parallel');

    const workers = [
      createWorker({ start: 0, end: 1000000 }),
      createWorker({ start: 1000000, end: 2000000 }),
      createWorker({ start: 2000000, end: 3000000 }),
    ];

    const results = await Promise.all(workers);
    console.timeEnd('parallel');
    return results.reduce((a, b) => a + b, 0);
  }

  function createWorker(data) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, { workerData: data });
      worker.on('message', resolve);
      worker.on('error', reject);
    });
  }
} else {
  // Code executed in the Worker Thread
  const { workerData } = require('worker_threads');
  let sum = 0;
  for (let i = workerData.start; i < workerData.end; i++) {
    sum += Math.sqrt(i); // CPU-intensive calculation
  }
  parentPort.postMessage(sum);
}

Voi cac thao tac I/O-bound (mang, file), tinh dong thoi ban dau la du. Voi cac tac vu CPU-bound (tinh toan nang, ma hoa), Worker Threads cho phep song song thuc su.

Cau Hoi 5: Module Cluster hoat dong nhu the nao?

Module Cluster cho phep tao nhieu tien trinh Node.js chia se cung mot cong, tu do tan dung tat ca cac loi CPU co san.

cluster-example.jsjavascript
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isPrimary) {
  console.log(`Primary ${process.pid} is running`);
  console.log(`Forking ${numCPUs} workers...`);

  // Fork one worker per CPU core
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  // Handle crashing workers
  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died (${signal || code})`);
    console.log('Starting a new worker...');
    cluster.fork(); // Automatic restart
  });

  // Inter-process communication
  cluster.on('message', (worker, message) => {
    console.log(`Message from worker ${worker.id}:`, message);
  });

} else {
  // Workers share the TCP port
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end(`Handled by worker ${process.pid}\n`);

    // Send stats to primary
    process.send({ type: 'request', pid: process.pid });
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

Can bang tai duoc he dieu hanh xu ly tu dong (round-robin tren Linux/macOS). Trong moi truong san xuat, PM2 don gian hoa viec quan ly nay voi che do cluster tich hop.

Sẵn sàng chinh phục phỏng vấn Node.js / NestJS?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Streams va Buffers

Cau Hoi 6: Khi nao nen su dung Streams thay vi cac phuong phap truyen thong?

Streams cho phep xu ly du lieu theo tung phan (chunk) thay vi tai tat ca vao bo nho. Rat quan trong cho file lon va cac kich ban streaming.

streams-comparison.jsjavascript
const fs = require('fs');

// ❌ BAD: loads entire file into memory
async function readEntireFile(path) {
  const data = await fs.promises.readFile(path); // Blocks if file > RAM
  return processData(data);
}

// ✅ GOOD: chunk-based processing with Stream
function readWithStream(path) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    const readStream = fs.createReadStream(path, {
      highWaterMark: 64 * 1024, // 64KB per chunk
    });

    readStream.on('data', (chunk) => {
      // Progressive processing, constant memory
      chunks.push(processChunk(chunk));
    });

    readStream.on('end', () => resolve(chunks));
    readStream.on('error', reject);
  });
}

// ✅ BEST: pipeline for chaining transformations
const { pipeline } = require('stream/promises');
const zlib = require('zlib');

async function compressFile(input, output) {
  await pipeline(
    fs.createReadStream(input),   // Source
    zlib.createGzip(),            // Transform
    fs.createWriteStream(output)  // Destination
  );
  // Automatic error handling and backpressure management
}

Su dung Streams bat cu khi nao kich thuoc du lieu co the vuot qua vai MB, hoac cho xu ly thoi gian thuc (upload, log, du lieu mang).

Cau Hoi 7: Giai thich khai niem backpressure

Backpressure xay ra khi ben san xuat du lieu nhanh hon ben tieu thu. Neu khong quan ly, bo nho se bi tran.

backpressure-demo.jsjavascript
const fs = require('fs');

// ❌ Problem: no backpressure handling
function badCopy(src, dest) {
  const readable = fs.createReadStream(src);
  const writable = fs.createWriteStream(dest);

  readable.on('data', (chunk) => {
    // If write() returns false, the internal buffer is full
    // But here reading continues anyway → memory leak
    writable.write(chunk);
  });
}

// ✅ Solution: respect the writable signal
function goodCopy(src, dest) {
  const readable = fs.createReadStream(src);
  const writable = fs.createWriteStream(dest);

  readable.on('data', (chunk) => {
    const canContinue = writable.write(chunk);

    if (!canContinue) {
      // Pause reading until buffer drains
      readable.pause();
    }
  });

  writable.on('drain', () => {
    // Buffer drained, resume reading
    readable.resume();
  });

  readable.on('end', () => writable.end());
}

// ✅ BEST: pipe() handles everything automatically
function bestCopy(src, dest) {
  const readable = fs.createReadStream(src);
  const writable = fs.createWriteStream(dest);

  // pipe() handles backpressure natively
  readable.pipe(writable);
}

Phuong thuc pipe() hoac pipeline() xu ly backpressure tu dong. Voi cac truong hop phuc tap, can tu xay dung logic pause/resume.

Hieu Suat va Toi Uu Hoa

Cau Hoi 8: Lam the nao de xac dinh va khac phuc memory leak?

Memory leak la van de pho bien trong Node.js. Biet cach phat hien va khac phuc chung la dieu can thiet trong moi truong san xuat.

memory-leak-patterns.jsjavascript
// ❌ Leak 1: closures that retain references
function createLeakyHandler() {
  const hugeData = Buffer.alloc(100 * 1024 * 1024); // 100MB

  return function handler(req, res) {
    // hugeData remains in memory as long as handler exists
    res.end('Hello');
  };
}

// ✅ Fix: limit the scope
function createSafeHandler() {
  return function handler(req, res) {
    // Data created and released on each request
    const data = fetchData();
    res.end(data);
  };
}

// ❌ Leak 2: event listeners not cleaned up
class LeakyClass {
  constructor() {
    // Added on each instantiation, never removed
    process.on('message', this.handleMessage);
  }
  handleMessage(msg) { /* ... */ }
}

// ✅ Fix: explicit cleanup
class SafeClass {
  constructor() {
    this.boundHandler = this.handleMessage.bind(this);
    process.on('message', this.boundHandler);
  }
  handleMessage(msg) { /* ... */ }

  destroy() {
    // Mandatory cleanup
    process.removeListener('message', this.boundHandler);
  }
}

// Diagnostics with native tools
function diagnoseMemory() {
  const used = process.memoryUsage();
  console.log({
    heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
    heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
    external: `${Math.round(used.external / 1024 / 1024)}MB`,
    rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
  });
}

// Enable manual garbage collector for testing
// node --expose-gc app.js
if (global.gc) {
  global.gc();
  diagnoseMemory();
}

Trong moi truong san xuat, su dung cac cong cu nhu clinic.js, heap snapshot tu Chrome DevTools, hoac cac giai phap APM (Application Performance Monitoring) nhu DataDog hoac New Relic.

Cau Hoi 9: Lam the nao de toi uu hieu suat API Node.js?

Cau hoi nay danh gia kien thuc ve cac ky thuat toi uu hoa o nhieu cap do.

performance-optimization.jsjavascript
// 1. CACHING: reduce expensive calls
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 }); // 5-minute TTL

async function getCachedUser(id) {
  const cacheKey = `user:${id}`;
  let user = cache.get(cacheKey);

  if (!user) {
    user = await db.users.findById(id);
    cache.set(cacheKey, user);
  }

  return user;
}

// 2. CONNECTION POOLING: reuse DB connections
const { Pool } = require('pg');
const pool = new Pool({
  max: 20,                // Max simultaneous connections
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

// 3. COMPRESSION: reduce response size
const compression = require('compression');
app.use(compression({
  filter: (req, res) => {
    // Only compress if > 1KB
    return compression.filter(req, res);
  },
  threshold: 1024,
}));

// 4. BATCHING: group operations
async function batchInsert(items) {
  const BATCH_SIZE = 1000;

  for (let i = 0; i < items.length; i += BATCH_SIZE) {
    const batch = items.slice(i, i + BATCH_SIZE);
    await db.items.insertMany(batch);
  }
}

// 5. LAZY LOADING: load on demand
async function getUserWithPosts(userId, includePosts = false) {
  const user = await db.users.findById(userId);

  if (includePosts) {
    user.posts = await db.posts.findByUserId(userId);
  }

  return user;
}

Viec toi uu hoa phai duoc dinh huong boi profiling. Hay do luong truoc khi toi uu de xac dinh cac nut that co that.

Quy Tac 80/20

80% van de hieu suat den tu 20% ma nguon. Hay su dung profiling de xac dinh cac khu vuc quan trong nay truoc khi toi uu mot cach mu quang.

Bao Mat

Cau Hoi 10: Lam the nao de bao ve API Node.js khoi cac cuoc tan cong pho bien?

Bao mat la chu de phong van thuong xuyen. The hien kien thuc ve cac lo hong OWASP la dieu duoc ky vong.

security-best-practices.jsjavascript
const express = require('express');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss-clean');

const app = express();

// 1. SECURITY HEADERS with Helmet
app.use(helmet());

// 2. RATE LIMITING against brute-force attacks
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100,                  // 100 requests per IP
  message: 'Too many requests, please try again later',
  standardHeaders: true,
  legacyHeaders: false,
});
app.use('/api/', limiter);

// 3. SANITIZATION against NoSQL injections
app.use(mongoSanitize());

// 4. XSS PROTECTION
app.use(xss());

// 5. STRICT INPUT VALIDATION
const { body, validationResult } = require('express-validator');

app.post('/api/users',
  [
    body('email').isEmail().normalizeEmail(),
    body('password').isLength({ min: 8 }).escape(),
    body('name').trim().escape(),
  ],
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // Continue processing
  }
);

// 6. SQL INJECTION PROTECTION (with parameters)
async function safeQuery(userId) {
  // ✅ Parameterized query
  const result = await pool.query(
    'SELECT * FROM users WHERE id = $1',
    [userId]
  );
  return result.rows;
}

// ❌ NEVER string concatenation
async function unsafeQuery(userId) {
  // Vulnerable to SQL injection
  const result = await pool.query(
    `SELECT * FROM users WHERE id = ${userId}`
  );
}

Trong moi truong san xuat, can bo sung them: CORS nghiem ngat, HTTPS bat buoc, ghi log bao mat, xoay vong bi mat va kiem tra phu thuoc dinh ky (npm audit).

Kien Truc va Mau Thiet Ke

Cau Hoi 11: Giai thich mau Repository trong Node.js

Mau Repository truu tuong hoa viec truy cap du lieu va tao dieu kien cho viec kiem thu va bao tri.

repository-pattern.jsjavascript
// Abstract interface (for TypeScript, or documentation)
class UserRepository {
  async findById(id) { throw new Error('Not implemented'); }
  async findByEmail(email) { throw new Error('Not implemented'); }
  async create(userData) { throw new Error('Not implemented'); }
  async update(id, userData) { throw new Error('Not implemented'); }
  async delete(id) { throw new Error('Not implemented'); }
}

// Concrete implementation with Prisma
class PrismaUserRepository extends UserRepository {
  constructor(prisma) {
    super();
    this.prisma = prisma;
  }

  async findById(id) {
    return this.prisma.user.findUnique({ where: { id } });
  }

  async findByEmail(email) {
    return this.prisma.user.findUnique({ where: { email } });
  }

  async create(userData) {
    return this.prisma.user.create({ data: userData });
  }

  async update(id, userData) {
    return this.prisma.user.update({
      where: { id },
      data: userData,
    });
  }

  async delete(id) {
    return this.prisma.user.delete({ where: { id } });
  }
}

// Implementation for testing
class InMemoryUserRepository extends UserRepository {
  constructor() {
    super();
    this.users = new Map();
    this.idCounter = 1;
  }

  async findById(id) {
    return this.users.get(id) || null;
  }

  async create(userData) {
    const user = { id: this.idCounter++, ...userData };
    this.users.set(user.id, user);
    return user;
  }
  // ... other methods
}

// Service using the repository (dependency injection)
class UserService {
  constructor(userRepository) {
    this.userRepository = userRepository;
  }

  async getUser(id) {
    const user = await this.userRepository.findById(id);
    if (!user) throw new Error('User not found');
    return user;
  }
}

Mau nay cho phep thay doi cach trien khai luu tru ma khong can sua doi logic nghiep vu.

Cau Hoi 12: Lam the nao de trien khai he thong hang doi cong viec?

Hang doi cho phep hoan cac tac vu nang va dam bao thuc thi dang tin cay.

job-queue.jsjavascript
const Queue = require('bull');

// Create queue with Redis as backend
const emailQueue = new Queue('email', {
  redis: {
    host: 'localhost',
    port: 6379,
  },
  defaultJobOptions: {
    attempts: 3,          // Number of attempts
    backoff: {
      type: 'exponential',
      delay: 2000,        // Initial delay between attempts
    },
    removeOnComplete: 100, // Keep last 100 completed jobs
  },
});

// Producer: add jobs to the queue
async function sendWelcomeEmail(userId, email) {
  await emailQueue.add('welcome', {
    userId,
    email,
    template: 'welcome',
  }, {
    priority: 1,          // High priority
    delay: 5000,          // 5-second delay
  });
}

// Consumer: process jobs
emailQueue.process('welcome', async (job) => {
  const { userId, email, template } = job.data;

  // Update progress
  job.progress(10);

  const html = await renderTemplate(template, { userId });
  job.progress(50);

  await sendEmail(email, 'Welcome!', html);
  job.progress(100);

  return { sent: true, email };
});

// Event handling
emailQueue.on('completed', (job, result) => {
  console.log(`Job ${job.id} completed:`, result);
});

emailQueue.on('failed', (job, err) => {
  console.error(`Job ${job.id} failed:`, err.message);
});

// Recurring jobs (cron)
emailQueue.add('newsletter', { type: 'weekly' }, {
  repeat: {
    cron: '0 9 * * MON', // Every Monday at 9am
  },
});

Bull voi Redis la giai phap pho bien nhat. Voi nhu cau don gian hon, agenda hoac bee-queue la cac lua chon nhe.

Cau Hoi Nang Cao

Cau Hoi 13: Module native N-API hoat dong nhu the nao?

N-API cho phep tao cac module native bang C/C++ voi API on dinh tren cac phien ban Node.js.

native-module.cppcpp
// Native module for CPU-intensive calculations

#include <napi.h>

// Synchronous function exposed to JavaScript
Napi::Number Fibonacci(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  // Argument validation
  if (info.Length() < 1 || !info[0].IsNumber()) {
    Napi::TypeError::New(env, "Number expected")
      .ThrowAsJavaScriptException();
    return Napi::Number::New(env, 0);
  }

  int n = info[0].As<Napi::Number>().Int32Value();

  // Iterative Fibonacci calculation
  long long a = 0, b = 1;
  for (int i = 0; i < n; i++) {
    long long temp = a + b;
    a = b;
    b = temp;
  }

  return Napi::Number::New(env, static_cast<double>(a));
}

// Module initialization
Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(
    Napi::String::New(env, "fibonacci"),
    Napi::Function::New(env, Fibonacci)
  );
  return exports;
}

NODE_API_MODULE(native_module, Init)
javascript
// Usage from JavaScript
const native = require('./build/Release/native_module');

// 10x faster than JavaScript equivalent
const result = native.fibonacci(50);

Cac module native huu ich cho cac phep tinh chuyen sau, tich hop cac thu vien C/C++ hien co hoac truy cap API he thong.

Cau Hoi 14: Giai thich Garbage Collector V8

Hieu ve GC giup viet ma giam thieu do tre va tieu thu bo nho.

gc-optimization.jsjavascript
// V8 GC uses two spaces: Young and Old Generation

// 1. Young Generation: short-lived objects
function shortLivedObjects() {
  for (let i = 0; i < 1000; i++) {
    const temp = { data: i }; // Allocated then collected quickly
  }
  // Minor GC (Scavenge) very fast
}

// 2. Old Generation: objects that survive multiple GCs
const cache = new Map(); // Survives, promoted to Old Generation

// ❌ Problematic pattern: many promoted objects
function createManyLongLived() {
  const objects = [];
  for (let i = 0; i < 100000; i++) {
    objects.push({ id: i, data: new Array(100).fill(0) });
  }
  return objects; // All promoted to Old Gen = slow major GC
}

// ✅ Optimized pattern: object reuse
class ObjectPool {
  constructor(factory, size = 100) {
    this.pool = Array.from({ length: size }, factory);
    this.available = [...this.pool];
  }

  acquire() {
    return this.available.pop() || this.pool[0];
  }

  release(obj) {
    // Reset and return to pool
    Object.keys(obj).forEach(k => obj[k] = null);
    this.available.push(obj);
  }
}

// GC monitoring
const v8 = require('v8');

function getHeapStats() {
  const stats = v8.getHeapStatistics();
  return {
    totalHeap: `${Math.round(stats.total_heap_size / 1024 / 1024)}MB`,
    usedHeap: `${Math.round(stats.used_heap_size / 1024 / 1024)}MB`,
    heapLimit: `${Math.round(stats.heap_size_limit / 1024 / 1024)}MB`,
  };
}

Co --max-old-space-size cho phep tang gioi han Old Generation cho cac ung dung su dung nhieu bo nho.

Cau Hoi 15: Lam the nao de trien khai graceful shutdown?

Graceful shutdown cho phep hoan thanh cac yeu cau dang xu ly va dong ket noi dung cach truoc khi dung server.

graceful-shutdown.jsjavascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Simulate a long request
  setTimeout(() => {
    res.writeHead(200);
    res.end('Done');
  }, 2000);
});

// Tracking active connections
let connections = new Set();

server.on('connection', (conn) => {
  connections.add(conn);
  conn.on('close', () => connections.delete(conn));
});

// Graceful shutdown function
async function shutdown(signal) {
  console.log(`${signal} received, starting graceful shutdown...`);

  // 1. Stop accepting new connections
  server.close(() => {
    console.log('HTTP server closed');
  });

  // 2. Close idle connections
  for (const conn of connections) {
    conn.end();
  }

  // 3. Close DB connections, queues, etc.
  await Promise.all([
    database.disconnect(),
    redisClient.quit(),
    messageQueue.close(),
  ]);

  // 4. Safety timeout
  setTimeout(() => {
    console.error('Forced shutdown after timeout');
    process.exit(1);
  }, 30000);

  console.log('Graceful shutdown completed');
  process.exit(0);
}

// Listen for termination signals
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));

// Start server
server.listen(3000, () => {
  console.log('Server running on port 3000');
});

Trong moi truong san xuat voi container (Docker, Kubernetes), graceful shutdown la yeu to then chot cho viec trien khai khong co thoi gian ngung.

Sẵn sàng chinh phục phỏng vấn Node.js / NestJS?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Cau Hoi Hanh Vi

Cau Hoi 16: Mo ta mot van de hieu suat da giai quyet

Cau hoi nay danh gia kinh nghiem thuc te. Cau tra loi nen duoc cau truc theo dinh dang STAR (Situation, Task, Action, Result).

Vi du cau tra loi co cau truc:

text
Situation: A reporting API was timing out on requests
            exceeding 100,000 records.

Task:       Reduce response time from 45s to under 5s.

Action:
1. Profiling with clinic.js → identified JSON serialization as bottleneck
2. Implemented streaming with Transform streams
3. Database-side pagination
4. Added Redis caching for frequent queries

Result:     Response time reduced to 2s, memory usage decreased by 10x.

Cau Hoi 17: Lam the nao de quan ly cac phu thuoc va cap nhat chung?

package.json - Versioning best practicesjavascript
{
  "dependencies": {
    // ✅ Exact versions for production
    "express": "4.18.2",

    // ✅ Caret for compatible minor updates
    "lodash": "^4.17.21",

    // ❌ Avoid latest or *
    // "some-lib": "*"
  },
  "devDependencies": {
    // Quality tools
    "npm-check-updates": "^16.0.0"
  },
  "scripts": {
    // Vulnerability check
    "audit": "npm audit --audit-level=moderate",

    // Interactive update
    "update:check": "ncu",
    "update:apply": "ncu -u && npm install"
  },
  "engines": {
    // Specify required Node.js version
    "node": ">=20.0.0"
  }
}

Can de cap den viec su dung package-lock.json, Dependabot hoac Renovate cho tu dong hoa va kiem thu hoi quy truoc moi lan cap nhat lon.

Ket Luan

Phong van backend Node.js danh gia ca su hieu biet ly thuyet ve cac co che noi bo va kha nang giai quyet cac van de san xuat thuc te. Lam chu Event Loop, cac mau bat dong bo va ky thuat toi uu la nen tang duoc ky vong cho cac vi tri backend developer cap cao.

Danh Sach Kiem Tra Chuan Bi

  • ✅ Hieu cach hoat dong cua Event Loop va cac giai doan cua no
  • ✅ Lam chu su khac biet giua callback, Promise va async/await
  • ✅ Biet cac mau xu ly loi bat dong bo
  • ✅ Biet khi nao su dung Streams so voi phuong phap truyen thong
  • ✅ Xac dinh va khac phuc memory leak
  • ✅ Ap dung cac phuong phap bao mat tot nhat theo OWASP
  • ✅ Trien khai clustering va graceful shutdown
  • ✅ Su dung cac cong cu profiling (clinic.js, Chrome DevTools)

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Viec chuan bi ky thuat nen duoc bo sung bang cac du an thuc te. Xay dung mot API san xuat, dong gop cho cac du an ma nguon mo Node.js hoac giai cac thach thuc tren cac nen tang nhu LeetCode giup cung co kien thuc nay.

Thẻ

#nodejs
#interview
#backend
#javascript
#technical interview

Chia sẻ

Bài viết liên quan