Trong loạt bài đăng trên blog này, tôi muốn thảo luận về các phương pháp hay nhất để xây dựng dịch vụ nhiều người thuê trong AWS . Tài liệu hiện có về cách xây dựng dịch vụ nhiều người thuê thường nhắm đến các ứng dụng SaaS với hàng trăm khách hàng (ví dụ: ).
Tôi sẽ chia loạt bài đăng trên blog thành ba phần cho từng loại tích hợp dịch vụ với dịch vụ: tích hợp đồng bộ, không đồng bộ và hàng loạt.
Nhiều người thuê dịch vụ nội bộ
1.1. Cách ly người thuê nhà 1.2. Giám sát nhiều người thuê 1.3. Chia tỷ lệNhiều người thuê dịch vụ nội bộ
2.1. Cách ly người thuê - kiểm soát truy cập 2.2 Cách ly người thuê nhà - vấn đề hàng xóm ồn ào 2.3 Giám sát nhiều người thuê 2.4 Số liệu, Cảnh báo, Trang tổng quan 2.5 Tích hợp và loại bỏ ứng dụng khách APINhiều bên thuê với AWS AppSync
Phần kết luận
Multi-tenancy là khả năng phần mềm phục vụ nhiều khách hàng hoặc người thuê với một phiên bản phần mềm duy nhất.
Khi bạn cho phép nhiều nhóm gọi API dịch vụ của mình, dịch vụ của bạn sẽ trở thành nhiều đối tượng thuê. Kiến trúc nhiều đối tượng thuê tạo thêm độ phức tạp cho các dịch vụ của bạn, chẳng hạn như cách ly đối tượng thuê, giám sát cấp độ đối tượng thuê và mở rộng quy mô.
Nếu bạn đang xây dựng dịch vụ web AWS của mình bằng API REST , HTTP hoặc WebSocket trong AWS thì rất có thể bạn đang sử dụng API Gateway.
Đưa lên máy khách với ủy quyền dựa trên tài nguyên . Để truy cập dựa trên tài nguyên, bạn cần cập nhật Chính sách tài nguyên cổng API và thêm Tài khoản AWS của khách hàng. Nhược điểm chính của phương pháp này là sau khi bạn cập nhật chính sách tài nguyên, giai đoạn API Gateway cần được triển khai lại để các thay đổi có hiệu lực (xem tài liệu AWS và ). Tuy nhiên, nếu sử dụng CDK, bạn có thể tự động hóa việc triển khai các giai đoạn mới (xem ). Một nhược điểm khác là giới hạn về độ dài tối đa của chính sách tài nguyên.
Tiếp nhận khách hàng bằng ủy quyền dựa trên danh tính . Để kiểm soát quyền truy cập dựa trên danh tính, bạn cần tạo vai trò IAM cho máy khách và cho phép máy khách đảm nhận vai trò đó bằng cách cập nhật chính sách tài nguyên của vai trò (mối quan hệ đáng tin cậy). Bạn có thể sử dụng người dùng IAM, nhưng vai trò IAM sẽ tốt hơn từ quan điểm bảo mật. Các vai trò cho phép xác thực bằng thông tin xác thực tạm thời và không yêu cầu lưu trữ thông tin xác thực người dùng IAM. Có giới hạn 1.000 vai trò cho mỗi tài khoản, nhưng giới hạn này có thể điều chỉnh được. Ngoài ra, một nhược điểm khác của phương pháp dựa trên vai trò để có được quyền truy cập nhiều tài khoản vào API của bạn là bạn cần tạo vai trò IAM cho mọi ứng dụng khách API mới. Tuy nhiên, quản lý vai trò có thể được tự động hóa bằng CDK (xem ).
Ủy quyền AWS IAM chỉ cho phép bạn kiểm soát quyền truy cập vào API Gateway (sử dụng chính sách IAM, bạn có thể chỉ định tài khoản AWS nào có thể gọi điểm cuối API Gateway nào). Bạn có trách nhiệm triển khai quyền truy cập kiểm soát vào dữ liệu và các tài nguyên cơ bản khác trong dịch vụ của mình. Trong dịch vụ của mình, bạn có thể sử dụng AWS IAM ARN của người gọi được chuyển bằng Yêu cầu cổng API để kiểm soát quyền truy cập sâu hơn:
export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => { // IAM Principal ARN of the api caller const callerArn = event.requestContext.identity.userArn!; // .. business logic based on caller return { statusCode: 200, body: JSON.stringify({ message: `Received API Call from ${callerArn}`, }) }; };
API Gateway có hai loại nhật ký:
Để theo dõi yêu cầu của ứng dụng khách API, tôi khuyên bạn nên bật tính năng ghi nhật ký truy cập. Bạn có thể đăng nhập ít nhất AWS IAM ARN của người gọi ( $context.identity.userArn
), đường dẫn yêu cầu ( $context.path
), mã trạng thái phản hồi dịch vụ của bạn $context.status
và độ trễ cuộc gọi API ( $context.responseLatency
) .
const formatObject = { requestId: '$context.requestId', extendedRequestId: '$context.extendedRequestId', apiId: '$context.apiId', resourceId: '$context.resourceId', domainName: '$context.domainName', stage: '$context.stage', path: '$context.path', resourcePath: '$context.resourcePath', httpMethod: '$context.httpMethod', protocol: '$context.protocol', accountId: '$context.identity.accountId', sourceIp: '$context.identity.sourceIp', user: '$context.identity.user', userAgent: '$context.identity.userAgent', userArn: '$context.identity.userArn', caller: '$context.identity.caller', cognitoIdentityId: '$context.identity.cognitoIdentityId', status: '$context.status', integration: { // The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns. status: '$context.integration.status', // For Lambda proxy integration, the status code returned from AWS Lambda, not from the backend Lambda function code. integrationStatus: '$context.integration.integrationStatus', // The error message returned from an integration // A string that contains an integration error message. error: '$context.integration.error', latency: '$context.integration.latency', }, error: { responseType: '$context.error.responseType', message: '$context.error.message', }, requestTime: '$context.requestTime', responseLength: '$context.responseLength', responseLatency: '$context.responseLatency', }; const accessLogFormatString = JSON.stringify(formatObject); const accessLogFormat = apigw.AccessLogFormat.custom(accessLogFormatString);
fields @timestamp, path, status, responseLatency, userArn | sort @timestamp desc | filter userArn like 'payment-service' | limit 20
Theo mặc định, số liệu CloudWatch được API Gateway hỗ trợ sẽ được tổng hợp cho tất cả các yêu cầu. Tuy nhiên, bạn có thể phân tích cú pháp nhật ký truy cập API Gateway để xuất bản số liệu CloudWatch tùy chỉnh cùng với thứ nguyên bổ sung là tên khách hàng của bạn để có thể giám sát việc sử dụng API của khách hàng (đối tượng thuê). Ở mức tối thiểu, tôi khuyên bạn nên xuất bản số liệu CloudWatch cho mỗi khách hàng. Đếm, 4xx, 5xx, Độ trễ được phân chia theo Dimension=${Client}
. Bạn cũng có thể thêm các thứ nguyên như mã trạng thái và đường dẫn API.
2.4.1. Sử dụng bộ lọc nhật ký số liệu để xuất bản số liệu cho mỗi khách hàng
Ví dụ về Bộ lọc nhật ký số liệu CloudWatch để Count
lượng xuất bản với thứ nguyên Client
và Path
new logs.MetricFilter(this, 'MultiTenantApiCountMetricFilter', { logGroup: accessLogsGroup, filterPattern: logs.FilterPattern.exists('$.userArn'), metricNamespace: metricNamespace, metricName: 'Count', metricValue: '1', unit: cloudwatch.Unit.COUNT, dimensions: { client: '$.userArn', method: '$.httpMethod', path: '$.path',},}); });
2.4.2. Sử dụng hàm Lambda để xuất bản số liệu cho mỗi khách hàng
Tùy chọn thay thế là tạo hàm Lambda để phân tích nhật ký, trích xuất số liệu và xuất bản chúng. Điều này cho phép bạn thực hiện nhiều công việc tùy chỉnh hơn như lọc các ứng dụng khách không xác định hoặc trích xuất tên ứng dụng khách từ userArn.
const logProcessingFunction = new lambda.NodejsFunction( this, 'log-processor-function', { functionName: 'multi-tenant-api-log-processor-function', } ); new logs.SubscriptionFilter(this, 'MultiTenantApiLogSubscriptionFilter', { logGroup: accessLogsGroup, destination: new logsd.LambdaDestination(logProcessingFunction), filterPattern: logs.FilterPattern.allEvents(), });
interface ApiClientConfig { name: string; awsAccounts: string[]; rateLimit: number; burstLimit: number; } const apiClients: ApiClientConfig[] = [ { name: 'payment-service', awsAccounts: ['3','444455556666'], rateLimit: 10, burstLimit: 2, }, { name: 'order-service', awsAccounts: ['777788889999'], rateLimit: 1, burstLimit: 1, }, ];
Nếu dịch vụ của bạn có API GraphQL thì bạn có thể sử dụng AppSync. Tương tự như API Gateway, bạn có thể sử dụng IAM Auth để ủy quyền các yêu cầu AppSync. AppSync không có chính sách tài nguyên (xem ), vì vậy bạn chỉ có thể sử dụng ủy quyền dựa trên vai trò để thiết lập kiểm soát truy cập vào API AppSync. Tương tự như API Gateway, bạn sẽ tạo vai trò IAM riêng cho từng đối tượng thuê dịch vụ mới của mình.