- vừa được xem lúc

Xây dựng Serverless API với AWS API Gateway, Lambda (Nodejs), MongoDB Atlas

0 0 7

Người đăng: anhdung

Theo Viblo Asia

Bối cảnh

Cấp Cao Chiên Da được chủ tạch Tập đoàn Toàn Đập Đá giao nhiệm vụ trong một tuần phải xây dựng xong hệ thống quản lý thông tin thiết bị để phục vụ công tác chào mừng đại lễ kỷ niệm sắp tới.

Hệ thống khá phức tạp với nhiều thành phần công nghệ khác nhau, trong đó có một module cần một API nho nhỏ để gọi lấy thông tin là chính, việc cập nhật thông tin cũng cần nhưng không cần tức thì, chủ yếu dùng cho việc thống kê vào cuối ngày là chính.

GET, OPTIONS api.tapdoantoandapda.com/device-detail/?id=xxx
POST api.tapdoantoandapda.com/device-detail
GET api.tapdoantoandapda.com/device-pinout/?id=xxx

Với nhu cầu đó Chiên Da quyết định sẽ sử dụng Mongo Altlas gói miễn phí, vì cũng không có mấy endpoint và tính năng đơn giản nên sẽ sử dụng công nghệ Lambda serverless cộng với API Gateway (API GTW) để expose API này ra ngoài Internet. Ở ngay chỗ API GTW đã có tính năng cache và custom domain “có vẻ” đủ xài rồi nhưng với tiêu chí phục vụ chủ tịch là nhiệm vụ của mình, còn trả tiền bill cloud thì là của chủ tịch nên Chiên Da đã quyết định bổ sung thêm CloudFront là lớp cuối cùng để giao tiếp với end-user, qua đó có thể dễ dàng control cache cũng như là sử dụng alias domain được quản lý ở Route 53.

Nhân những ngày uể oải đợi nghỉ lễ sắp tới, à không, nhân những ngày sục sôi không khí nhà nhà thi đua số lượng line of code, người người thi đua tìm và bắt bug nên tôi đã dành chút thời gian để viết lại quá trình xây dựng hệ thống này trước là để sau này lỡ có phải nhìn lại code của chính bản thân thì cũng bớt chút cảm giác lạ lẫm sau là để cho quý anh chị em nào có cần thiết thì hãy sử dụng. Tôi rất lấy làm hân hạnh vì đều này, mong rằng sẽ hữu ích và giúp quý anh chị em có thêm được thời gian để sống cuộc đời bên ngoài màn hình. (Đây là đoạn tự sự của Chiên Da, tác giả bài viết -LTS).

MongoDB Atlas

Ở thời điểm viết bài này MongoDB cho phép sử dụng Shared Cluster với dung lượng lưu trữ 512MB ở trên cả 3 cloud provider AWS/ Azure/ GCP. Bạn có thể xem chi tiết tại https://www.mongodb.com/pricing.

Lambda Function

File app.mjs của mình sẽ như bên dưới

// Filename: app.mjs
'use strict';
console.log('init the function 15'); import * as mongoose from 'mongoose'; // START: Schema /** * Mongoose schema for the 'test' collection. * @typedef {Object} TestSchema * @property {string} name - The name of the test. */
const testSchema = new mongoose.Schema({ name: String });
// END: Schema /** * Handles the incoming request and returns the appropriate response based on the event and context. * * @param {Object} event - The event object containing information about the request. * @param {Object} context - The context object containing information about the runtime environment. * @return {Promise<Object>} The response object with a statusCode and body property. */
async function handleRequest(event, context) { const { httpMethod, path } = event; if ((httpMethod === "GET" || httpMethod === "OPTIONS") && path.indexOf("/device-detail") >= 0) { return await getDeviceDetail(event, context); } else if (httpMethod === "POST" && path.indexOf("/device-detail") >=0) { return await postDeviceDetail(event, context); } else if ((httpMethod === "GET" || httpMethod === "OPTIONS") && path.indexOf("/device-pinout") >= 0) { return await getDevicePinout(event, context); } else { return { statusCode: 404, body: "Not found", }; }
} /** * Handles the incoming event and context, and returns the result of handleRequest. * * @param {Object} event - The event object. * @param {Object} context - The context object. * @return {Promise} A promise that resolves to the result of handleRequest. */
export const handler = async (event, context) => { try { return await handleRequest(event, context); } catch (error) { console.error("Error adding new link:", error); return { statusCode: 500, body: JSON.stringify({ error: error.message, message: 'fetch_error', data: null, }), }; } };

File hỗ trợ kết nối MongoDB Atlas

// File: mongoConnectionHelper.mjs
// https://mongoosejs.com/docs/lambda.html import mongoose from 'mongoose';
let conn = null;
const uri = process.env.MONGODB_URI; export async function connect() { if (conn == null) { conn = mongoose.createConnection(uri, { serverSelectionTimeoutMS: 5000, useNewUrlParser: true, useUnifiedTopology: true, }); // `await`ing connection after assigning to the `conn` variable // to avoid multiple function calls creating new connections await conn.asPromise(); } return conn;
} 

Vì đặc trưng của Lambda function thì sẽ thực thi trong hàm handler nên mình sẽ xây dựng thêm hàm handleRequest để xử lý các endpoint nhận được theo đúng các method. Với 3 method ở trên, mình thử nghiệm chạy tốn khoảng 105MB memory.

Trong source code, mình có sử dụng package mongosee nên cần phải chạy npm install [package-name] trên máy local rồi sau đó zip luôn cả folder node_modules để upload lên Lambda. Không rõ ngay đây có cách nào thao tác hay hơn không.

Thật ra thì nếu chỉ cần làm MVP hay demo cho sếp coi thì tới đây cũng là đủ rồi vì Lambda cho phép expose một HTTPS URL (Enable function URL) với đầy đủ các tính năng cơ bản vốn có của một API như:

  • Auth type: sử dụng AWS_IAM hoặc public
  • Invoke mode:
  • Configure cross-origin resource sharing (CORS): có thể tự cấu hình lại các origin, expose headers, allow headers, allow methods, max age.

Tuy nhiên vì hạn chế lớn nhất của Function URL là mỗi URL chỉ trỏ được đến đúng 1 version hoặc alias thôi, không thể thay đổi được giá trị trỏ đến nên sẽ rất khó để quản lý và sử dụng thực tế, ở môi trường cần sự ổn định ít thay đổi các giá trị cấu hình.

API Gateway (API GTW)

API GTW sẽ giải quyết câu chuyện Function URL ở trên, cũng tại màn hình Function overview của Lambda, ta bấm Add trigger để tiến hành chọn API GTW từ trong source của Trigger configuration.

Làm vầy thì tiện nhưng cái API url tạo ra đều bị đính kèm thêm một đoạn tên của Lambda Function, khá bất tiện thế nên chúng ta sẽ chọn giải pháp tự tạo API GTW riêng.

Từ màn hình API GTW Console bấm nút Create API > Choose an API type > REST API > Build. Ở màn hình tiếp theo ta chỉ cần điền API name, còn lại mọi thứ để như mặc định.

Chọn Actions > Create Resource để tạo một nhóm resource, nhóm này sẽ chứa các endpoint. Chỗ này thì nhớ chọn Enable API Gateway CORS, với tùy chọn này thì sau khi tạo xong sẽ mặc định có endpoint method OPTIONS phục vụ cho việc preflight (một phương pháp để kiểm tra xem browser có quyền truy cập vào tài nguyên đích không).

Tiếp tục chọn Actions > Create Method, chọn method click nút check kế bên sau đó điền Lambda Function, nhớ chọn Use Lambda Proxy integration để request package gửi lên được nhét vào event theo đúng cấu trúc code ở Lambda ở trên.

Sau khi xong lại chọn Actions > Deploy API, hoàn tất bạn sẽ thấy màn hình production Stage Editor với Invoke URL.

Đến đây xem như cơ bản đã hoàn thành và có thể đưa vào sử dụng.

Anh Dũng
Sài Gòn những ngày nhiều mưa, tháng 09/ 2023.

Bình luận

Bài viết tương tự

- vừa được xem lúc

PDF Export, cẩn thận với những input có thể truyền vào

Giới thiệu. Dạo gần đây mình tình cờ gặp rất nhiều lỗi XSS, tuy nhiên trang đó lại có sử dụng dữ liệu người dùng input vào để export ra PDF.

0 0 49

- vừa được xem lúc

Tán gái theo kiểu Message Queue là thế nào?

. Bài toán. Vào những năm 1900, khi mà công nghệ chưa phát triển, con người chỉ nói chuyện với nhau trực tiếp hoặc qua thư... . Trai tài gái sắc, họ nói chuyện với nhau một cách thoải mái, tự nhiên. Mọi chuyện yên bình cho đến khi có anh chàng C đến, chiều cao chuẩn 1m8 chứ không cộng thêm sừng. C c

0 0 29

- vừa được xem lúc

Giới thiệu Lambda AWS

Giới thiệu. Nếu bạn là 1 developer, đúng rồi đó, người mà luôn được mọi người nhờ sửa tủ lạnh, ti vi, quạt máy, ống nước, đủ thứ loại trên đời, khi bạn xây dựng một ứng dụng, bạn sẽ muốn được nhiều người sử dụng, trải nghiệm và đánh giá tốt.

0 0 24

- vừa được xem lúc

Tạo tải khoản AWS 2021

Các bài viết trước:. . Ứng dụng AWS trong thực tế. Bạn có thể làm gì với AWS.

0 0 167

- vừa được xem lúc

Tương tác với AWS

Các bài viết trước:. . Ứng dụng AWS trong thực tế. Bạn có thể làm gì với AWS.

0 0 24

- vừa được xem lúc

Khám phá những dịch vụ của AWS

Các bài viết trước:. . Ứng dụng AWS trong thực tế. Bạn có thể làm gì với AWS.

0 0 27