Kiến thức hay về Tối ưu hóa Lambda function với Nodejs

5th Oct 2022
Kiến thức hay về Tối ưu hóa Lambda function với Nodejs
Table of contents

Gần đây mình có nghiên cứu lại mấy vấn đề về lập trình Lambda function và mày mò vào Node Summit và có nhận thấy một số vấn đề sau:

Về cơ bản với Lambda, AWS đã làm gần hết mọi thứ về management, scale function, kết nối đến các dịch vụ như DynamoDB, SQS,… Gần như chúng ta chỉ cần tập  trung vào việc coding. Tuy nhiên, để mọi thứ tốt hơn cho người dùng thì cần giảm latency (độ trễ), trả lời nhanh hơn và dễ debug hơn trong những trường hợp cần thiết và chính trong source code Lambda function tức là:

  • Cải thiện latency
  • Tìm ra bug performance
  • Debug.

Tối ưu code

Bài viết này sẽ nói về các cách tối ưu coding là chính, những phần khác thì hãy xem kỹ topic nhé.

Đầu tiên bao giờ cũng cần tìm hiểu xem Lambda hoạt động như nào nhưng trước tiên mình sẽ đưa ra một ví dụ điển hình về lambda function:

const dynamodb = require('aws-sdk/clients/dynamodb');
const docClient = new dynamodb.DocumentClient();
const tableName = process.env.SAMPLE_TABLE;
exports.getByIdHandler = async (event) => {
    const { httpMethod, path, pathParameters } = event;
    if (httpMethod !== 'GET') {
        throw new Error(`Unsupported method`);
    }
    console.log('received:', JSON.stringify(event));
    const { id } = pathParameters;
    const params = {
        TableName: tableName,
        Key: { id },
    };
    const { Item } = await docClient.get(params).promise();
    const response = {
        statusCode: 200,
        body: JSON.stringify(Item),
    };
    return response;
};

Đây là một ví dụ rất điển hình với việc: Khởi tạo SDK, xử lý request, query database và đưa ra kết quả, trước đó sẽ là download source code và khởi chạy lambda function. Bạn hãy ghép nó vào mô hình lifecycle của lambda function như ở bên dưới.

Như hình bên trên toàn bộ Lifecycle của AWS Lambda bao gồm Cold Start và Warm Start.
Như hình bên trên toàn bộ Lifecycle của AWS Lambda bao gồm Cold Start và Warm Start.

Warm start: bao gồm phần thời gian code chạy, Cold start: thời gian chuẩn bị.

Như vậy có thể thấy rằng phần warm start là phần coding đơn thuần và tối ưu hóa như chúng ta optimize source code khi sử dụng các framework hay runtime khác. Mặt khác, mọi người thường nghĩ rằng Lambda Function sẽ thực hiện toàn bộ các bước trên mỗi lần execute nhưng không, Lambda sẽ không khởi chạy lại Cold Start, miễn là bạn không cập nhật source code nhưng chỉ trong 15 phút thôi như vậy là quá đủ. Việc giảm thiểu độ trễ latency sẽ bắt đầu từ đây.

Lambda

Như hình trên cứ sau một khoảng thời gian nhất định Lambda function lại thực hiện Cold Start, những chỗ thời gian execute cao bất thường ấy, hãy để function Lambda luôn sẵn sàng để execute.

Môi trường để chạy Lambda code

Một cách chính thống hơn thì có thể tìm hiểu AWS đề cập đến Lambda execution context (Môi trường để chạy Lambda code), môi trường này sẽ bị đóng băng sau khi sử dụng xong function và được giã đông khi chạy lần tiếp. Ngoài ra, AWS cũng đề xuất một vài thủ thuật để tối ưu hóa Lambda function:

  • Đầu tiên bắt đầu với handler method, Các object được khai báo bên ngoài handler vẫn được khởi tạo, cung cấp tối ưu hóa bổ sung khi handler được gọi lại. Ví dụ: nếu Lambda kết nối đến database (RDS, DynamoDB), thay vì kết nối đi kết nối lại, kết nối được tái sử dụng qua các lần invoke khác nhau trong một lambda instance. Một cách đơn giản có thể lazy load connection, như bây giờ AWS đã cải tiến SDK để dùng keep alive hoặc đơn giản là chuyển những thứ nặng nề ra khỏi handler, cache lại AWS SDK Client
    const AWS = require('aws-sdk')
    // http or https
    const https = require('https');
    const agent = new https.Agent({
      keepAlive: true
    });
  
    const dynamodb = new AWS.DynamoDB({
      httpOptions: {
        agent
      }
    });
    fuction fuckingHeavyFunction() {
    }

    const outsideHeavyResult = fuckingHeavyFunction(); // run on every Lambda init instance.

    exports.handler = async (event) => {
      const heavyResult = fuckingHeavyFunction(); // run on every lambda request
      return response;
    };
  • Mỗi Lambda function có 512Mb lưu trữ ở /tmp, bạn có thể lưu trữ bất kỳ thứ gì. Vùng lưu trữ này sẽ được đóng băng cùng với Execution context, như vậy bạn có thể lưu trữ nhiều thứ ở trong này, ví dụ những tính toán, variable ít thay đổi có thể lưu trữ lại và dùng lại cho lần tiếp theo.
  • Nếu sử dụng background process trong Lambda function, hãy chắc chắn nó được hoàn toàn hoàn thành khi Lambda function kết thúc, vì có thể nó được sử dụng lại và tiếp tục chạy. Dẫn đến những bug không như ý. Nhưng nói chung cũng không nên nghĩ rằng Lambda sẽ sử dụng lại các tài nguyên khi chạy lại Lambda function, hãy chuẩn bị lại các tài nguyên hoặc kiểm tra việc sử dụng cho chắc chắn.
Bạn thấy bài viết này như thế nào?
0 reactions

Add new comment

Image CAPTCHA
Enter the characters shown in the image.

Related Articles

Hiện nay, việc quản lý các web applications khá là phức tạp, ví dụ bạn phải quản lý load balancer, vài web servers, database servers

In this video we'll be setting up a new React App with AWS Amplify to add Sign up, Login and Logout in the easiest way possible.

In this hands on workshop Amazon Developer Advocate Nader Dabit shows us how to get started with serverless GraphQL using AWS Amplify.