NodeJS – Tăng hiệu suất server

4.7/5 - (34 votes)

Trong các phần trước chúng ta đã xây dựng một ứng dụng có đầy đủ các chức năng CRUD (các thao tác thêm, sửa, xóa, cập nhật) giống như một ứng dụng bình thường.

Bây giờ giả sử dụng ứng dụng của chúng ta nổi tiếng đến mức có đến 1 triệu người dùng truy cập mỗi ngày. Một tiến trình server phải phục vụ 1 triệu người mỗi ngày là rất mệt, có một cách giải quyêt đó là chạy nhiều instance cùng một lúc để “san sẻ gánh nặng” cho nhau. Nếu bạn chưa bao giờ nghe qua khái niệm instance thì có thể hình dung nó giống như một biến hay một đối tượng vậy, tức là ở đây chúng ta tạo nhiều đối tượng server để chạy.

Khi bạn tạo một ứng dụng Express thì trong thư mục bin của project, có file www, file này không có phần mở rộng tuy nhiên nó cũng chỉ là một file text nên chúng ta có thể mở ra xem với bất kỳ trình text editor nào:

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('notes:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
    var port = parseInt(val, 10);

    if (isNaN(port)) {
        // named pipe
        return val;
    }

    if (port >= 0) {
        // port number
        return port;
    }

    return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
    if (error.syscall !== 'listen') {
        throw error;
    }

    var bind = typeof port === 'string'
      ? 'Pipe ' + port
      : 'Port ' + port;

    // handle specific listen errors with friendly messages
    switch (error.code) {
    case 'EACCES':
        console.error(bind + ' requires elevated privileges');
        process.exit(1);
        break;
    case 'EADDRINUSE':
        console.error(bind + ' is already in use');
        process.exit(1);
        break;
    default:
        throw error;
    }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
    var addr = server.address();
    var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
    debug('Listening on ' + bind);
}

Trong file này có 2 dòng là:

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

Ý nghĩa của 2 dòng này là chạy server trên cổng được định nghĩa trong biến môi trường PORT, nếu biến môi trường PORT không có thì chạy trên cổng mặc định là 3000.

Để có thể chạy nhiều instance server cùng một lúc thì chúng ta chỉ cần chạy chúng trên các cổng khác nhau là được. Bằng cách thiết lập biến môi trường PORT cho mỗi lần chạy, chúng ta sẽ chạy được nhiều instance server.

Ví dụ:

C:\NodeJS\notes>SET PORT=3030
C:\NodeJS\notes>npm start

> notes@0.0.0 start F:\NodeJS\notes
> node ./bin/www

  notes:server Listening on port 3030 +0ms

Chúng ta thiết lập biến môi trường PORT có giá trị là 3030 bằng lệnh SET, lưu ý là việc thiết lập biến môi trường thông qua lệnh SET chỉ có hiệu lực trong terminal (Command Prompt) đó thôi, khi thoát terminal thì biến này sẽ mất. Sau đó chúng ta chạy server như thường thì server lúc này sẽ chạy trên cổng 3030.

Sau đó chúng ta lại mở một trình terminal khác lên và cũng chạy lại những lệnh như trên, chỉ khác số PORT là sẽ có thêm một instance khác, ví dụ:

C:\NodeJS\notes>SET PORT=4040
C:\NodeJS\notes>npm start

> notes@0.0.0 start F:\NodeJS\notes
> node ./bin/www

  notes:server Listening on port 4040 +0ms

capturecapture

Thoạt nhìn thì có vẻ 2 instance đều là một, nhưng thực chất chúng là 2 đối tượng server khác nhau, chẳng qua là vì chúng đều trả về cùng một tài nguyên nên nội dung HTML trả về giống nhau. Mỗi instance đều có bộ nhớ riêng, có dữ liệu riêng. Đặc biệt là ở đây chúng ta không lưu các ghi chú trong cơ sở dữ liệu mà lưu trong bộ nhớ RAM, do đó nếu bạn tạo một ghi chú mới ở instance có cổng 3030 thì chỉ có bên đó mới thấy được, còn ở cổng 4040 thì không thể thấy được.

capturecapture

Tất nhiên là trong thực tế thì chúng ta muốn dữ liệu trả về phải đồng nhất (tức là 2 bên phải giống nhau), do đó dữ liệu nên/phải được lưu trong các file tài nguyên dùng chung, chẳng hạn như sử dụng cơ sở dữ liệu. Mục đích của việc sử dụng cơ sở dữ liệu là để lưu trữ lâu dài, đặc biệt là với các tập dữ liệu có các mối quan hệ phức tạp.Trong các phần sau chúng ta sẽ bắt đầu đi vào tìm hiểu cách lưu trữ dữ liệu.

0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments