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

Làm việc với AWS DSQL và Lambda – Thiết lập dự án

0 0 3

Người đăng: Gung Typical

Theo Viblo Asia

Gần đây, tôi đã khám phá Amazon Aurora DSQL — cơ sở dữ liệu SQL phân tán mới nhất của AWS được xây dựng dành riêng cho các khối lượng công việc serverless. Không giống như các cơ sở dữ liệu truyền thống cần bảo trì thường xuyên, Aurora DSQL tự động mở rộng và chỉ tính phí dựa trên mức sử dụng — khiến nó trở thành một lựa chọn hoàn hảo cho các hàm Lambda.

Khi nhắc đến cơ sở dữ liệu serverless, nhiều người nghĩ ngay đến DynamoDB — và điều đó hoàn toàn hợp lý. Nó đã là giải pháp NoSQL hàng đầu cho các ứng dụng serverless suốt nhiều năm. Nhưng giờ đây, chúng ta cuối cùng cũng có thể cân nhắc sử dụng cơ sở dữ liệu quan hệ trong bối cảnh serverless thực sự. Aurora DSQL mang lại sự quen thuộc của SQL và mô hình dữ liệu quan hệ vào thế giới serverless, mà không cần lo lắng về việc quản lý instance hoặc vấn đề mở rộng. image.png

Bài viết này sẽ đề cập đến những gì?

Thiết lập dự án:

Bạn sẽ học cách khởi tạo và tổ chức một dự án backend serverless, bao gồm thiết lập repository và chuẩn bị các file cũng như thư mục cần thiết để có workflow phát triển mượt mà.

AWS CDK cho hạ tầng:

Bài viết hướng dẫn cách sử dụng AWS CDK để định nghĩa hạ tầng cloud bằng mã. Bạn sẽ biết cách dùng các construct của CDK (đặc biệt là L1 với Aurora DSQL) để triển khai tài nguyên như Lambda và Aurora DSQL, cũng như cấu trúc stack cho dễ bảo trì và mở rộng.

Kết nối Lambda và DSQL:

Bạn sẽ biết cách thiết lập kết nối an toàn giữa Lambda và Aurora DSQL. Bao gồm việc cấu hình IAM role, policy cho Lambda để tương tác với DSQL Data API, thiết lập biến môi trường hoặc secrets để truy cập CSDL một cách bảo mật.

Đoạn mã từng bước:

Cung cấp ví dụ mã cụ thể ở mỗi bước. Bạn sẽ thấy cách viết CDK stack, định nghĩa Lambda function và kết nối với DSQL, dễ dàng làm theo và áp dụng cho dự án của mình.

Repository mã nguồn mở:

Bài viết có liên kết đến một repo open-source, giúp bạn dễ dàng xem cấu trúc dự án đầy đủ, clone mã về và tự thử nghiệm. Rất minh bạch và tiện mở rộng.

Bước 1: Tổ chức dự án

Cấu trúc thư mục

image.png

Với:

  • infra/ - Mã CDK định nghĩa hạ tầng
  • service/ - Mã nguồn của Lambda
  • .github/ - Workflow của GitHub Actions

Lưu ý:

  • Cách tổ chức này giúp tôi tách biệt rõ ràng hạ tầng, logic nghiệp vụ và các hành động liên quan đến CI/CD pipeline.
  • Ngoài ra, tôi thích chia hạ tầng thành các stack theo từng domain vì điều đó rất hữu ích khi dự án phát triển lớn hơn.

Bước 2: Làm việc với AWS CDK và DSQL

Ghi chú: Aurora DSQL mới ra mắt nên chỉ có L1 Construct (được sinh tự động). Tôi sẽ cập nhật bài viết và repo khi AWS hỗ trợ tốt hơn.

Ví dụ khởi tạo DSQL Cluster:

export class StorageStack extends cdk.Stack { dsqlCluster: cdk.CfnResource; dsqlClusterArn: string; dsqlClusterEndpoint: string; constructor(scope: constructs.Construct, id: string, props: cdk.StackProps) { super(scope, id, props); // Create DSQL cluster using native CloudFormation resource this.dsqlCluster = new cdk.CfnResource(this, 'DSQLCluster', { type: 'AWS::DSQL::Cluster', properties: { DeletionProtectionEnabled: true, Tags: [ { Key: 'Project', Value: 'aws-dsql-demo' } ] } }); this.dsqlClusterArn = this.dsqlCluster.getAtt('ResourceArn').toString(); this.dsqlClusterEndpoint = `${this.dsqlCluster.getAtt('Identifier').toString()}.dsql.${this.region}.on.aws`; }
}

Bước 3: Tạo Lambda và phân quyền

export interface FunctionsStackProps extends cdk.StackProps { label: { id: string; }, domainName: string; dsqlClusterEndpoint: string; dsqlClusterArn: string;
} export class FunctionsStack extends cdk.Stack { generateGameLambda: lambda.Function; constructor(scope: constructs.Construct, id: string, props: FunctionsStackProps) { super(scope, `${id}-functions-stack`, props); // Create Lambda role with DSQL permissions const lambdaRole = new iam.Role(this, 'DSQLLambdaRole', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'), ] }); // Add DSQL permissions lambdaRole.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ 'dsql:DbConnect', 'dsql:ExecuteStatement', 'dsql:DbConnectAdmin', ], resources: [props.dsqlClusterArn] })); this.generateGameLambda = new nodeLambda.NodejsFunction(this, 'GenerateGameLambda', { entry: './service/generate-game/Handler.ts', runtime: lambda.Runtime.NODEJS_20_X, role: lambdaRole, environment: { DSQL_ENDPOINT: props.dsqlClusterEndpoint } }); }
}

Bước 4: Tối ưu kết nối database trong Lambda

Tạo lớp DatabaseService để:

  • Cache kết nối TypeORM DataSource trong lifecycle của Lambda.
  • Sử dụng DsqlSigner để tạo token tạm thời.
  • Dùng TypeORM để quản lý entity.
import "reflect-metadata";
import { DataSource } from "typeorm";
import { DsqlSigner } from "@aws-sdk/dsql-signer";
import { Game } from "../models/Game"; export class DatabaseService { private static dataSource: DataSource; private static async getAuthToken(host: string): Promise<string> { const signer = new DsqlSigner({ hostname: host, region: process.env.AWS_REGION || 'eu-west-2' }); return await signer.getDbConnectAdminAuthToken(); } static async initialize(): Promise<DataSource> { if (!DatabaseService.dataSource) { const host = process.env.DSQL_ENDPOINT || ''; DatabaseService.dataSource = new DataSource({ type: "postgres", host: host, port: 5432, username: 'admin', password: await DatabaseService.getAuthToken(host), database: "postgres", ssl: { rejectUnauthorized: true }, synchronize: true, logging: true, entities: [Game] }); // Initialize connection to postgres database await DatabaseService.dataSource.initialize(); } return DatabaseService.dataSource; } static async saveGame(game: Partial<Game>): Promise<Game> { const dataSource = await DatabaseService.initialize(); const gameRepository = dataSource.getRepository(Game); const newGame = gameRepository.create(game); return await gameRepository.save(newGame); }
} 

Bước 5: Tạo handler cho Lambda

export async function handler(event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> { console.log(event, context); await DatabaseService.initialize(); try { // Generate a random game const gameData = generateRandomGame(); // Save it to the database const savedGame = await DatabaseService.saveGame(gameData); return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Game generated and saved successfully', game: savedGame }) }; } catch (error) { console.error('Error generating game:', error); return { statusCode: 500, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Failed to generate and save game', error: error instanceof Error ? error.message : String(error) }) }; }
}

Debug thủ công

Bạn có thể kết nối trực tiếp với CSDL thông qua AWS Console:

  • Tìm kiếm “AWS DSQL”
  • Chọn Cluster
  • Nhấn Connect > Open in CloudShell
  • Chọn kết nối với quyền admin và chạy truy vấn SQL

Bạn sẽ làm được những gì qua bài viết này:

  • Thiết lập cấu trúc dự án rõ ràng, tách biệt giữa hạ tầng, code dịch vụ và CI/CD
  • Khởi tạo Aurora DSQL Cluster và Lambda bằng AWS CDK (sử dụng L1 construct)
  • Cấu hình quyền IAM cho Lambda kết nối và thực thi truy vấn trên Aurora DSQL
  • Tối ưu kết nối DB với TypeORM + DsqlSigner để bảo mật token
  • Tạo Lambda handler lưu dữ liệu vào Aurora DSQL và cung cấp qua API Gateway

Bình luận

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

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

The Twelve-Factor App, cẩm nang gối đầu giường trong xây dựng application (Phần 1)

Giới thiệu. Ngày nay các phần mềm được triển khai dưới dạng các dịch vụ, chúng được gọi là các web apps hay software-as-a-service (SaaS).

0 0 45

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

8 Sai lầm phổ biến khi lập trình Android

1. Hard code.

0 0 207

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

Popular interview question: What is the difference between Process and Thread? 10 seconds a day

Video được đăng tại channel Tips Javascript

0 0 44

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

Thuật toán và ứng dụng - P1

Mục đích series. . Những bài toán gắn liền với thực tế. Từ đó thấy được tầm quan trọng của thuật toán trong lập trình.

0 0 46

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

Tác dụng của Docker trong quá trình học tập

Docker bây giờ gần như là kiến thức bắt buộc đối với các anh em Dev và Devops, nhưng mà đối với sinh viên IT nói chung vẫn còn khá mơ hồ và không biết tác dụng thực tế của nó. Hôm nay mình sẽ chia sẻ

0 0 52

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

Làm giàu trong ngành IT

Hầu như mọi người đều đi làm để kiếm tiền, ít người đi làm vì thấy cái nghề đó thú vị lắm. Bây giờ vất cho mình 100 tỷ bảo mình bỏ nghề thì mình cũng bỏ thôi.

0 0 55