Ngân hàng đề — AWS Certified Solutions Architect Professional

Tìm thấy 1221 câu.

Câu 481 Chọn nhiều đáp án Continuous Improvement for Existing Solutions

A social learning platform allows students to connect with other students as well as experts and professionals from academic, research institutes and industry. The engineering team at the company manages 5 Amazon EC2 instances that make read-heavy database requests to the Amazon RDS for PostgreSQL DB cluster. As an AWS Certified Solutions Architect Professional, you have been asked to make the database cluster resilient from a disaster recovery perspective.

Which of the following features will help you prepare for database disaster recovery? (Select two)

  1. A

    Enable the automated backup feature of Amazon RDS in a multi-AZ deployment that creates backups in a single or multiple AWS Region(s)

  2. B

    Use RAID 1 configuration for the RDS DB cluster

  3. C

    Use cross-Region Read Replicas

  4. D

    Use database cloning feature of the RDS DB cluster

  5. E

    Use RDS Provisioned IOPS (SSD) Storage in place of General Purpose (SSD) Storage

Xem giải thích

Đáp án

**A và C — Bật sao lưu tự động của RDS trong triển khai Multi-AZ, tạo bản sao lưu ở một hoặc nhiều Region; và dùng cross-Region read replica.

Vì sao đúng

Đề hỏi về khôi phục thảm hoạ, và hai tính năng này bao phủ hai kịch bản khác nhau: | Kịch bản | Cơ chế | |---|---| | Mất dữ liệu do lỗi logic (xoá nhầm) | sao lưu tự động + point-in-time recovery | | Mất cả một Region | cross-Region read replica |

⚠ Điểm mấu chốt: sao lưu tự động cho phép khôi phục về một THỜI ĐIỂM bất kỳ:

RDS chụp snapshot hằng ngày
        ↓
    Và ghi transaction log liên tục
        ↓
    → khôi phục về bất kỳ giây nào
      trong thời gian giữ backup
        ↓
    Thời gian giữ tối đa 35 ngày
aws rds restore-db-instance-to-point-in-time \
  --source-db-instance-identifier csdl-chinh \
  --target-db-instance-identifier csdl-khoi-phuc \
  --restore-time 2026-09-01T10:30:00Z

⚠ Và sao chép backup sang Region khác là tính năng riêng:

aws rds modify-db-instance \
  --db-instance-identifier csdl-chinh \
  --backup-retention-period 14 \
  --apply-immediately

aws rds start-db-instance-automated-backups-replication \
  --source-db-instance-arn <arn-csdl> \
  --backup-retention-period 14 \
  --region us-west-2
Backup nằm ở Region khác
        ↓
    Region chính mất hoàn toàn
        ↓
    Vẫn khôi phục được từ Region kia
    → đây là phần "single or multiple
      Regions" của mệnh đề A

⚠ Và Multi-AZ KHÔNG phải khôi phục thảm hoạ:

Multi-AZ bảo vệ khỏi mất một AZ
        ↓
    Cả hai AZ nằm trong CÙNG Region
        ↓
    Region mất → cả hai mất
    → Multi-AZ là sẵn sàng cao, không
      phải DR

Bảng phân biệt bốn khái niệm: | Cơ chế | Bảo vệ khỏi | |---|---| | Multi-AZ | mất một AZ | | Read replica cùng Region | quá tải đọc | | Cross-Region read replica | mất cả Region | | Backup + PITR | lỗi logic, xoá nhầm |

⚠ Và cross-Region read replica là cách duy nhất trong bốn phương án chống mất Region:

aws rds create-db-instance-read-replica \
  --db-instance-identifier ban-sao-us-west \
  --source-db-instance-identifier \
    arn:aws:rds:ap-southeast-1:111122223333:db:csdl-chinh \
  --region us-west-2 \
  --db-instance-class db.r6g.large

Thăng cấp khi Region chính mất:

aws rds promote-read-replica \
  --db-instance-identifier ban-sao-us-west \
  --region us-west-2

⚠ Và thăng cấp là thao tác MỘT CHIỀU:

Thăng cấp xong
        ↓
    Nó thành CSDL độc lập
        ↓
    Không quay lại làm replica được
        ↓
    → muốn quay về Region cũ phải dựng
      replica ngược lại

⚠ Và cross-Region replica có độ trễ, nên RPO không bằng không:

Sao chép BẤT ĐỒNG BỘ
        ↓
    Độ trễ thường vài giây tới vài
      chục giây
        ↓
    Region chính chết đột ngột
        ↓
    → mất các giao dịch chưa kịp sao
      chép
aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS --metric-name ReplicaLag \
  --dimensions Name=DBInstanceIdentifier,Value=ban-sao-us-west \
  --statistics Average --period 300 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-01T12:00:00Z

⚠ Và với PostgreSQL, replica dùng streaming replication gốc:

RDS for PostgreSQL cross-Region
  replica
        ↓
    Dùng physical replication
        ↓
    Giữ được toàn bộ CSDL, không chọn
      lọc bảng
        ↓
    Và replica ở chế độ chỉ đọc thật
      sự

⚠ Và replica cũng giúp việc đọc — đúng nhu cầu của đề:

Đề nói 5 instance EC2 đọc nhiều
        ↓
    Trỏ chúng vào replica
        ↓
    Giảm tải cho instance chính
    → vừa DR vừa chia tải

⚠ Và vì sao mệnh đề B sai hoàn toàn:

B nói dùng cấu hình RAID 1 cho cụm
  RDS
        ↓
    RDS là dịch vụ được quản lý
        ↓
    Bạn không truy cập được lớp lưu
      trữ
        ↓
    Không có tuỳ chọn RAID nào
    → khái niệm này chỉ áp cho EC2 tự
      quản

⚠ Và vì sao mệnh đề D sai:

D nói dùng tính năng database cloning
        ↓
    Cloning là tính năng của AURORA,
      không phải RDS PostgreSQL
        ↓
    Và clone dùng copy-on-write TRONG
      CÙNG Region
        ↓
    Nó để tạo môi trường thử nghiệm
      nhanh
    → không phải cơ chế DR

⚠ Và Aurora clone có đặc điểm đáng biết:

Clone chia sẻ lớp lưu trữ với bản gốc
        ↓
    Chỉ ghi khác biệt
        ↓
    Tạo trong vài phút dù CSDL nhiều
      TB
        ↓
    Nhưng nếu lưu trữ hỏng
    → cả bản gốc lẫn clone cùng mất

⚠ Và vì sao mệnh đề E sai:

E nói đổi từ gp2/gp3 sang Provisioned
  IOPS
        ↓
    Đó là cải thiện HIỆU NĂNG
        ↓
    Không liên quan gì tới khôi phục
      thảm hoạ
    → đọc kỹ câu hỏi hỏi về cái gì

Chiến lược DR đầy đủ cho RDS:

Trong Region:
    Multi-AZ (chuyển đổi tự động)
        ↓
    Backup tự động 14-35 ngày
        ↓
Liên Region:
    Cross-Region read replica
        ↓
    Sao chép backup sang Region khác
        ↓
    Snapshot thủ công trước thay đổi
      lớn

⚠ Và snapshot thủ công không tự hết hạn:

Snapshot tự động: xoá theo thời gian
  giữ
        ↓
    Snapshot thủ công: giữ tới khi bạn
      xoá
        ↓
    Trước khi nâng cấp phiên bản lớn
    → luôn tạo snapshot thủ công
aws rds create-db-snapshot \
  --db-instance-identifier csdl-chinh \
  --db-snapshot-identifier truoc-nang-cap-v16

⚠ Và xoá CSDL thì snapshot tự động cũng mất:

`delete-db-instance` không có
  `--final-db-snapshot-identifier`
        ↓
    Mọi snapshot TỰ ĐỘNG bị xoá theo
        ↓
    Snapshot THỦ CÔNG vẫn còn
    → luôn tạo final snapshot
aws rds delete-db-instance \
  --db-instance-identifier csdl-cu \
  --final-db-snapshot-identifier ban-cuoi-csdl-cu

⚠ Và nên bật deletion protection:

aws rds modify-db-instance \
  --db-instance-identifier csdl-chinh \
  --deletion-protection --apply-immediately

⚠ Và AWS Backup quản tập trung tốt hơn:

aws backup put-backup-plan --backup-plan '{
  "BackupPlanName": "ke-hoach-csdl",
  "Rules": [{
    "RuleName": "hang-ngay-giu-35",
    "TargetBackupVaultName": "kho-chinh",
    "ScheduleExpression": "cron(0 17 * * ? *)",
    "Lifecycle": {"DeleteAfterDays": 35},
    "CopyActions": [{
      "DestinationBackupVaultArn":
        "arn:aws:backup:us-west-2:111122223333:backup-vault:kho-dr",
      "Lifecycle": {"DeleteAfterDays": 90}}]}]}'

Ba lợi ích của tổ hợp: | Lợi ích | Chi tiết | |---|---| | Khôi phục về bất kỳ thời điểm nào | | | Sống sót qua mất cả Region | | | Replica còn chia tải đọc | |

⚠ Và phải diễn tập DR định kỳ:

Có replica không có nghĩa là khôi phục
  được
        ↓
    Ứng dụng có đổi endpoint được
      không?
        ↓
    DNS mất bao lâu để lan?
        ↓
    → chỉ diễn tập mới trả lời được

Vì sao các phương án khác sai

  • **D. Dùng tính năng database cloning của cụm — đây là phương án gần nhất và clone thật sự tạo ra một bản CSDL nhanh chóng, nhưng đó là tính năng của Aurora, hoạt động trong cùng Region và chia sẻ chung lớp lưu trữ nên không bảo vệ được khi lưu trữ hỏng.
  • **B. Dùng cấu hình RAID 1 cho cụm RDS — RDS là dịch vụ được quản lý, không truy cập được lớp lưu trữ; không có tuỳ chọn RAID.
  • **E. Dùng Provisioned IOPS thay General Purpose — đó là cải thiện hiệu năng, không liên quan tới khôi phục thảm hoạ.

Ghi nhớ

⚠ Bốn cơ chế bảo vệ dữ liệu RDS — bảng phải thuộc: | Cơ chế | Bảo vệ khỏi | RPO | |---|---|---| | Multi-AZ | mất một AZ | 0 (đồng bộ) | | Cross-Region replica | mất Region | giây tới phút | | Backup + PITR | lỗi logic | 5 phút | | Snapshot thủ công | thay đổi lớn | thời điểm chụp |

Từ khoá nhận diện:

"disaster recovery, cross-Region" → cross-Region read replica "restore to any point in time" → automated backup "Multi-AZ is DR" → SAI, đó là sẵn sàng cao "RAID for RDS" → LUÔN SAI

Ba lưu ý về automated backup: | Lưu ý | Chi tiết | |---|---| | Giữ tối đa 35 ngày | | | Sao chép được sang Region khác | | | Xoá CSDL thì mất theo | |

Ba lưu ý về cross-Region replica: | Lưu ý | Chi tiết | |---|---| | Sao chép bất đồng bộ, có độ trễ | | | Thăng cấp là một chiều | | | Theo dõi ReplicaLag | |

Ba lưu ý về snapshot: | Lưu ý | Chi tiết | |---|---| | Thủ công không tự hết hạn | | | Sao chép sang Region khác được | | | Chia sẻ sang tài khoản khác được | |

Ba lưu ý về Aurora: | Lưu ý | Chi tiết | |---|---| | Global Database cho DR liên Region | | | Clone dùng copy-on-write, cùng Region | | | Backtrack quay ngược thời gian (chỉ MySQL) | |

Ba lưu ý về bảo vệ khỏi xoá nhầm: | Lưu ý | Chi tiết | |---|---| | Bật deletion protection | | | Luôn tạo final snapshot | | | Chặn DeleteDBInstance bằng SCP | |

Ba lưu ý về AWS Backup: | Lưu ý | Chi tiết | |---|---| | Quản backup nhiều dịch vụ ở một chỗ | | | CopyActions sao sang Region khác | | | Vault Lock chống xoá backup | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Khôi phục thử vào một CSDL tạm | | | Thăng cấp replica ở môi trường thử | | | Đo ReplicaLag trong giờ cao điểm | |

Và một lời khuyên: hãy thực hiện khôi phục thử ít nhất mỗi quý một lần. Một backup chưa từng được khôi phục chỉ là một giả định — và những thứ hỏng trong lúc khôi phục thật (thiếu parameter group, thiếu subnet group, ứng dụng hardcode endpoint) đều là thứ chỉ lộ ra khi bạn thật sự làm.

Câu 482 Continuous Improvement for Existing Solutions

A leading pharmaceutical company has significant investments in running Oracle and PostgreSQL services on Amazon RDS which provide their scientists with near real-time analysis of millions of rows of manufacturing data generated by continuous manufacturing equipment with 1,600 data points per row. The business analytics team has been running ad-hoc queries on these databases to prepare daily reports for senior management. The engineering team has observed that the database performance takes a hit whenever these reports are run by the analytics team. To facilitate the business analytics reporting, the engineering team now wants to replicate this data with high availability and consolidate these databases into a petabyte-scale data warehouse by streaming data to Amazon Redshift.

As a Solutions Architect Professional, which of the following would you recommend as the MOST resource-efficient solution that requires the LEAST amount of development time without the need to manage the underlying infrastructure?

  1. A

    Use AWS Database Migration Service to replicate the data from the databases into Amazon Redshift

  2. B

    Use AWS Glue to replicate the data from the databases into Amazon Redshift

  3. C

    Use Amazon EMR to replicate the data from the databases into Amazon Redshift

  4. D

    Use Amazon Kinesis Data Streams to replicate the data from the databases into Amazon Redshift

Xem giải thích

Đáp án

**A — Dùng AWS Database Migration Service sao chép dữ liệu từ các cơ sở dữ liệu vào Amazon Redshift.

Vì sao đúng

Đề đòi ba thứ, và DMS đáp ứng cả ba tốt nhất: | Yêu cầu | DMS | |---|---| | Ít thời gian phát triển nhất | cấu hình, không viết mã | | Không quản hạ tầng | replication instance hoặc Serverless | | Sao chép liên tục | CDC |

⚠ Điểm mấu chốt: DMS làm được cả tải ban đầu lẫn sao chép liên tục:

Full load: chép toàn bộ dữ liệu hiện

      có
        ↓
    CDC: đọc log thay đổi của CSDL
        ↓
    Áp thay đổi vào đích liên tục
        ↓
    → một công cụ lo cả hai giai đoạn

Tạo tác vụ:

aws dms create-replication-task \
  --replication-task-identifier sao-chep-sang-redshift \
  --source-endpoint-arn <arn-oracle> \
  --target-endpoint-arn <arn-redshift> \
  --replication-instance-arn <arn-instance> \
  --migration-type full-load-and-cdc \
  --table-mappings file://anh-xa.json

⚠ Và DMS Serverless bỏ hẳn việc chọn kích thước:

aws dms create-replication-config \
  --replication-config-identifier sao-chep-lien-tuc \
  --source-endpoint-arn <arn-nguon> \
  --target-endpoint-arn <arn-redshift> \
  --replication-type full-load-and-cdc \
  --compute-config MinCapacityUnits=1,MaxCapacityUnits=32
Đề nói "không cần quản lý hạ tầng nền"
        ↓
    → DMS Serverless khớp chính xác

⚠ Và DMS ghi vào Redshift qua bucket S3 trung gian:

DMS ghi tệp CSV vào bucket
        ↓
    Rồi phát lệnh `COPY`
        ↓
    `COPY` nạp song song trên mọi
      slice
    → nhanh hơn `INSERT` rất nhiều lần

⚠ Và có ràng buộc cứng: cùng tài khoản, cùng Region:

Redshift đích phải cùng tài khoản với
  replication instance
        ↓
    Và cùng Region
        ↓
    Khác đích của DMS (RDS, S3 thì
      liên Region được)

Ánh xạ bảng chọn lọc:

{"rules": [{
   "rule-type": "selection",
   "rule-id": "1", "rule-name": "chon-bang-san-xuat",
   "object-locator": {"schema-name": "SANXUAT",
                      "table-name": "%"},
   "rule-action": "include"},
  {"rule-type": "transformation",
   "rule-id": "2", "rule-name": "chuyen-chu-thuong",
   "rule-target": "table", "rule-action": "convert-lowercase",
   "object-locator": {"schema-name": "%", "table-name": "%"}}]}

⚠ Và vì sao phương án B kém hơn:

B dùng AWS Glue
        ↓
    Glue là ETL theo LÔ
        ↓
    Chạy job theo lịch
        ↓
    Đề nói "streaming data to Redshift"
    → Glue không phải công cụ sao chép
      liên tục
Và Glue đòi viết script:
        ↓
    PySpark hoặc Scala
        ↓
    Xử lý ánh xạ kiểu, xử lý bản ghi
      cập nhật
    → nhiều thời gian phát triển hơn
      DMS

⚠ Và Glue có chỗ đứng riêng, chỉ là không hợp ở đây:

Glue mạnh khi cần BIẾN ĐỔI phức tạp
        ↓
    Gộp nhiều nguồn, làm sạch, tính
      toán
        ↓
    DMS mạnh khi cần SAO CHÉP nguyên
      trạng
    → đề chỉ cần sao chép

⚠ Và vì sao phương án C nặng nhất:

C dùng Amazon EMR
        ↓
    Phải chọn loại node, số node
        ↓
    Phải viết job Spark đọc CSDL
        ↓
    Phải tự xử lý CDC
        ↓
    Đề nói "không quản lý hạ tầng nền"
    → EMR là cụm phải vận hành

⚠ Và vì sao phương án D không phù hợp:

D dùng Kinesis Data Streams
        ↓
    Kinesis nhận dữ liệu do ứng dụng
      ĐẨY vào
        ↓
    Nó không tự đọc từ CSDL
        ↓
    → phải viết một tiến trình đọc CSDL
      rồi đẩy vào Kinesis
    → và viết một tiến trình đọc Kinesis
      ghi vào Redshift

Bảng bốn công cụ: | Công cụ | Mô hình | Viết mã | |---|---|---| | DMS | sao chép CSDL | không | | Glue | ETL theo lô | có | | EMR | cụm xử lý phân tán | có | | Kinesis | luồng do ứng dụng đẩy | có |

⚠ Và yêu cầu bật log thay đổi ở nguồn: | Engine | Cấu hình | |---|---| | Oracle | ARCHIVELOG + supplemental logging | | PostgreSQL | wal_level = logical |

-- Oracle
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER TABLE SANXUAT.DU_LIEU
  ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
-- PostgreSQL (trong parameter group)
rds.logical_replication = 1

⚠ Và với PostgreSQL trên RDS thì phải khởi động lại:

Đổi `rds.logical_replication`
        ↓
    Đó là tham số static
        ↓
    → phải reboot instance
    → lên kế hoạch cửa sổ bảo trì

⚠ Và bảng không có khoá chính gây vấn đề với CDC:

CDC cần xác định dòng nào bị sửa
        ↓
    Không có khoá chính → không xác
      định được
        ↓
    Với PostgreSQL: đặt `REPLICA IDENTITY FULL`
        ↓
    Nhưng nó làm WAL phình rất to
ALTER TABLE bang_khong_khoa REPLICA IDENTITY FULL;

⚠ Và nên tạo bảng đích trước với DISTKEY và SORTKEY:

CREATE TABLE san_xuat.du_lieu (
    ma_thiet_bi   VARCHAR(32) DISTKEY,
    thoi_gian     TIMESTAMP   SORTKEY,
    diem_do_1     DECIMAL(12,4),
    diem_do_2     DECIMAL(12,4)
);
DMS tự tạo bảng nếu chưa có
        ↓
    Bảng đó không có khoá phân bố hay
      sắp xếp
        ↓
    1.600 cột mỗi dòng, hàng triệu
      dòng
    → thiết kế khoá quyết định hiệu
      năng truy vấn

⚠ Và Redshift có giới hạn 1.600 cột mỗi bảng:

Đề nói 1.600 điểm dữ liệu mỗi dòng
        ↓
    Đúng bằng giới hạn của Redshift
        ↓
    → có thể phải tách bảng
    → hoặc dùng SUPER lưu dạng bán cấu
      trúc
CREATE TABLE do_dac (
    ma_thiet_bi VARCHAR(32) DISTKEY,
    thoi_gian   TIMESTAMP   SORTKEY,
    diem_do     SUPER);

⚠ Và bật data validation để kiểm chứng:

{"ValidationSettings": {
  "EnableValidation": true,
  "ValidationMode": "ROW_LEVEL",
  "ThreadCount": 5,
  "FailureMaxCount": 10000}}

⚠ Và theo dõi độ trễ CDC:

aws cloudwatch get-metric-statistics \
  --namespace AWS/DMS --metric-name CDCLatencyTarget \
  --dimensions Name=ReplicationTaskArn,Value=<arn-task> \
  --statistics Average --period 300 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-01T12:00:00Z
Độ trễ tăng dần không về 0
        ↓
    Replication instance quá nhỏ
        ↓
    Hoặc Redshift đang bận
    → hai chỉ số: `CDCLatencySource` và
      `CDCLatencyTarget` chỉ ra bên nào

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Không viết dòng mã nào | | | Có full load và CDC trong một tác vụ | | | Có xác minh dữ liệu sẵn | |

⚠ Và giải quyết đúng vấn đề gốc của đề:

Phân tích chạy trên CSDL sản xuất
        ↓
    Làm chậm hệ thống
        ↓
    Chuyển dữ liệu sang Redshift
        ↓
    → phân tích chạy trên kho riêng
    → CSDL sản xuất không bị ảnh hưởng

Vì sao các phương án khác sai

  • **B. Dùng AWS Glue — đây là phương án gần nhất và Glue thật sự đọc được từ RDS và ghi vào Redshift, nhưng nó là ETL theo lô chạy theo lịch, không phải cơ chế sao chép liên tục, và đòi viết script biến đổi.
  • **C. Dùng Amazon EMR — cụm phải chọn kích thước và vận hành, trái với "không quản lý hạ tầng nền".
  • **D. Dùng Kinesis Data Streams — Kinesis nhận dữ liệu do ứng dụng đẩy vào, không tự đọc từ cơ sở dữ liệu.

Ghi nhớ

⚠ Bốn công cụ đưa dữ liệu vào Redshift — bảng phải thuộc: | Công cụ | Dùng khi | |---|---| | DMS | sao chép từ CSDL, có CDC | | Glue | ETL có biến đổi phức tạp | | Data Firehose | luồng sự kiện | | COPY từ S3 | nạp theo lô, nhanh nhất |

Từ khoá nhận diện:

"replicate database to Redshift, least development" → DMS "transform and clean data" → Glue "no infrastructure to manage" → DMS Serverless "streaming into Redshift" → DMS CDC hoặc Streaming Ingestion

Ba lưu ý về DMS: | Lưu ý | Chi tiết | |---|---| | Redshift đích phải cùng tài khoản, cùng Region | | | Dùng bucket S3 trung gian | | | Serverless bỏ được việc chọn kích thước | |

Ba lưu ý về CDC: | Lưu ý | Chi tiết | |---|---| | Nguồn phải bật log thay đổi | | | Bảng không khoá chính gây vấn đề | | | Theo dõi CDCLatencyTarget | |

Ba lưu ý về Redshift đích: | Lưu ý | Chi tiết | |---|---| | Tạo bảng trước với DISTKEY, SORTKEY | | | Giới hạn 1.600 cột mỗi bảng | | | Kiểm stl_load_errors khi có vấn đề | |

Ba lưu ý về validation: | Lưu ý | Chi tiết | |---|---| | Cần khoá chính hoặc chỉ mục duy nhất | | | Kết quả trong awsdms_validation_failures_v1 | | | Bảng thiếu khoá bị bỏ qua âm thầm | |

Ba lưu ý về ánh xạ kiểu: | Nguồn | Rủi ro | |---|---| | NUMBER không khai độ chính xác | mất độ chính xác | | CLOB, BLOB | bị cắt | | TIMESTAMP WITH TIME ZONE | mất múi giờ |

Ba lưu ý về hiệu năng: | Lưu ý | Chi tiết | |---|---| | Full load nặng cho nguồn — chạy ngoài giờ | | | MaxFullLoadSubTasks điều khiển song song | | | Chạy VACUUM và ANALYZE sau full load | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Đếm số dòng hai bên | | | Bật data validation | | | Đo hiệu năng CSDL nguồn trước và sau | |

Và một lời khuyên: hãy tạo bảng trong Redshift với DISTKEY và SORTKEY trước khi khởi động tác vụ DMS. Với 1.600 cột mỗi dòng và hàng triệu dòng, khác biệt giữa một bảng có khoá phân bố hợp lý và một bảng do DMS tự tạo không phải vài phần trăm — nó là khác biệt giữa báo cáo chạy trong giây và báo cáo chạy trong giờ.

Câu 483 Design for New Solutions

A company provides a web-based business-management platform for IT service companies across the globe to manage help desk, customer service, sales and marketing, and other critical business functions. More than 50,000 people use the company's platform, so the company must respond quickly to any reported problems. However, the company has issues with not having enough visibility into its systems to discover any issues. Multiple logs and monitoring systems are needed to understand the root cause of problems thereby taking hours to resolve. Even as the company is slowly moving towards serverless architecture using AWS Lambda/Amazon API Gateway/Amazon Elastic Container Service (Amazon ECS), the company wants to monitor the microservices and gain deeper insights into its serverless resources.

Which of the following will you recommend to address the given requirements?

  1. A

    Configure Amazon CloudWatch to monitor and analyze all microservices through request tracing. Enable CloudTrail to log all user activity

  2. B

    Use AWS X-Ray to analyze the microservices applications through request tracing. Configure Amazon CloudWatch for monitoring containers, latency, web server requests, and incoming load-balancer requests and create CloudWatch alarms to send out notifications if system latency is increasing

  3. C

    Use AWS X-Ray to analyze the microservices applications through request tracing. Configure Amazon EventBridge for monitoring containers, latency, web server requests, and incoming load-balancer requests and create alarms to send out notifications if system latency is increasing

  4. D

    Configure Amazon EventBridge for monitoring containers, latency, web server requests, and incoming load-balancer requests and create alarms to send out notifications if system latency is increasing. Use AWS Config to continually assesses, audit, and evaluate the configurations and relationships of your resources and trigger alarms when needed

Xem giải thích

Đáp án

**B — Dùng AWS X-Ray phân tích các ứng dụng microservice bằng request tracing; cấu hình Amazon CloudWatch giám sát container, độ trễ, yêu cầu web server và yêu cầu tới bộ cân bằng tải; tạo CloudWatch alarm gửi thông báo khi độ trễ hệ thống tăng.

Vì sao đúng

Đề mô tả đúng bài toán mà X-Ray sinh ra để giải: không thấy được đường đi của một yêu cầu qua nhiều dịch vụ.

⚠ Điểm mấu chốt: log cho biết chuyện gì xảy ra ở MỘT nơi, trace cho biết đường đi QUA MỌI nơi:

Yêu cầu chậm 8 giây
        ↓
    Log API Gateway: nhận lúc 10:00:00
        ↓
    Log Lambda A: chạy 200 ms
        ↓
    Log Lambda B: chạy 150 ms
        ↓
    → 7,65 giây còn lại ở đâu?
    → log không trả lời được
X-Ray trace:
        ↓
    API Gateway 8.000 ms
      └─ Lambda A 200 ms
      └─ DynamoDB 50 ms
      └─ Gọi API bên thứ ba 7.600 ms ←
    → thấy ngay điểm nghẽn

⚠ Và đây chính là "mất hàng giờ để tìm nguyên nhân gốc" trong đề:

Nhiều hệ thống log và giám sát
        ↓
    Phải ghép tay từng mảnh
        ↓
    X-Ray ghép sẵn theo trace ID
    → từ hàng giờ xuống vài phút

Bật X-Ray cho Lambda:

aws lambda update-function-configuration \
  --function-name xu-ly-don \
  --tracing-config Mode=Active

Bật cho API Gateway:

aws apigateway update-stage \
  --rest-api-id abc123 --stage-name prod \
  --patch-operations op=replace,path=/tracingEnabled,value=true

Bật cho ECS:

{"containerDefinitions": [
  {"name": "ung-dung", "image": "...",
   "environment": [{"name": "AWS_XRAY_DAEMON_ADDRESS",
                    "value": "xray-daemon:2000"}]},
  {"name": "xray-daemon",
   "image": "public.ecr.aws/xray/aws-xray-daemon:latest",
   "cpu": 32, "memoryReservation": 256,
   "portMappings": [{"containerPort": 2000, "protocol": "udp"}]}]}

⚠ Và trace lan truyền qua header X-Amzn-Trace-Id:

Root=1-63f1a2b3-abcdef0123456789;Parent=53995c3f42cd8ad8;Sampled=1
Dịch vụ đầu tiên tạo `Root`
        ↓
    Mỗi dịch vụ sau tạo segment con,
      giữ nguyên `Root`
        ↓
    → X-Ray ghép lại thành một trace
    → mất header này là mất liên kết

⚠ Và đây là lỗi hay gặp nhất khi dùng X-Ray:

Dịch vụ A gọi dịch vụ B bằng HTTP
  client thường
        ↓
    Không chuyển tiếp header trace
        ↓
    B tạo trace MỚI
        ↓
    → trace đứt đoạn, mỗi dịch vụ một
      trace riêng
    → dùng SDK của X-Ray để tự lo việc
      này

Trong Node.js:

const AWSXRay = require('aws-xray-sdk-core');
const https = AWSXRay.captureHTTPs(require('https'));
const AWS = AWSXRay.captureAWS(require('aws-sdk'));

Trong Python:

from aws_xray_sdk.core import xray_recorder, patch_all
patch_all()

@xray_recorder.capture('tinh_gia')
def tinh_gia(don_hang):
    xray_recorder.put_annotation('maKhach', don_hang['maKhach'])
    xray_recorder.put_metadata('chiTiet', don_hang)
    return ...

⚠ Và phân biệt annotation với metadata rất quan trọng: | | Annotation | Metadata | |---|---|---| | Đánh chỉ mục | có | không | | Lọc được | có | không | | Giới hạn | 50 mỗi trace | lớn hơn nhiều |

Muốn tìm "mọi trace của khách hàng
  X"
        ↓
    Phải là annotation
        ↓
    Để metadata → không lọc được

Lọc trace:

aws xray get-trace-summaries \
  --start-time 2026-09-01T10:00:00Z \
  --end-time 2026-09-01T11:00:00Z \
  --filter-expression 'annotation.maKhach = "KH-123" AND responsetime > 5'

⚠ Và lấy mẫu quyết định chi phí:

{"version": 2,
 "default": {"fixed_target": 1, "rate": 0.05},
 "rules": [{
   "description": "Ghi day du duong dan thanh toan",
   "service_name": "*", "http_method": "POST",
   "url_path": "/thanh-toan/*",
   "fixed_target": 10, "rate": 1.0}]}
`fixed_target`: số yêu cầu ghi đủ mỗi
  giây
        ↓
    `rate`: tỷ lệ ghi cho phần còn lại
        ↓
    Đường dẫn quan trọng → ghi 100%
    → đường dẫn thường → 5%

⚠ Và vì sao phương án A sai — CloudWatch không làm request tracing:

A nói dùng CloudWatch phân tích
  microservice qua request tracing
        ↓
    CloudWatch chứa metric và log
        ↓
    Nó không ghép các đoạn của một yêu
      cầu qua nhiều dịch vụ
    → đó là việc của X-Ray

⚠ Và CloudTrail cũng không phải công cụ này:

A nói CloudTrail ghi mọi hoạt động
  người dùng
        ↓
    CloudTrail ghi lời gọi API AWS
        ↓
    Không ghi yêu cầu HTTP của người
      dùng cuối tới ứng dụng

⚠ Và vì sao phương án C sai — EventBridge không giám sát:

C nói dùng EventBridge giám sát
  container, độ trễ, yêu cầu
        ↓
    EventBridge là bus sự kiện
        ↓
    Nó ĐỊNH TUYẾN sự kiện
        ↓
    Không thu thập metric, không tạo
      alarm
    → sai vai trò hoàn toàn

Bảng bốn dịch vụ quan sát: | Dịch vụ | Việc | |---|---| | CloudWatch | metric, log, alarm, dashboard | | X-Ray | trace một yêu cầu qua nhiều dịch vụ | | CloudTrail | ai gọi API AWS nào | | EventBridge | định tuyến sự kiện, không giám sát |

⚠ Và vì sao phương án D sai:

D dùng EventBridge giám sát + Config
  đánh giá cấu hình
        ↓
    Config kiểm CẤU HÌNH tài nguyên
        ↓
    Không liên quan tới hiệu năng ứng
      dụng
    → và vẫn thiếu tracing

Ba trụ cột của observability:

Metric  → cái gì đang xảy ra
          (CloudWatch)
        ↓
Log     → chi tiết tại một điểm
          (CloudWatch Logs)
        ↓
Trace   → đường đi qua toàn hệ thống
          (X-Ray)

⚠ Và Container Insights cho ECS là phần "giám sát container":

aws ecs update-cluster-settings \
  --cluster cum-ung-dung \
  --settings name=containerInsights,value=enabled
Metric ở cấp cụm, dịch vụ, tác vụ
        ↓
    CPU, bộ nhớ, mạng, số tác vụ
    → không tự thu thập được từ metric
      EC2 thường

Tạo alarm cho độ trễ:

aws cloudwatch put-metric-alarm \
  --alarm-name do-tre-tang \
  --namespace AWS/ApplicationELB \
  --metric-name TargetResponseTime \
  --dimensions Name=LoadBalancer,Value=app/alb-ung-dung/abc \
  --extended-statistic p99 --period 300 \
  --threshold 2 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 --alarm-actions <arn-sns>

⚠ Và dùng p99 chứ đừng dùng Average:

Average 200 ms trông rất khoẻ
        ↓
    Nhưng 1% người dùng chờ 10 giây
        ↓
    Đó là hàng nghìn người mỗi ngày
    → p99 mới phản ánh trải nghiệm tệ
      nhất

⚠ Và X-Ray có Service Map vẽ sẵn kiến trúc:

Mỗi node là một dịch vụ
        ↓
    Kích thước theo lưu lượng
        ↓
    Màu theo tỷ lệ lỗi
        ↓
    → nhìn một cái là thấy dịch vụ nào
      đang có vấn đề

⚠ Và CloudWatch ServiceLens gộp cả ba trụ cột:

Service Map của X-Ray
        ↓
    + metric của CloudWatch
        ↓
    + log liên quan
        ↓
    → một màn hình duy nhất

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Thấy điểm nghẽn trong vài phút | | | Bản đồ dịch vụ tự sinh | | | Cảnh báo trước khi người dùng phàn nàn | |

⚠ Và nên dùng ADOT nếu muốn không khoá vào một nhà cung cấp:

AWS Distro for OpenTelemetry
        ↓
    Chuẩn mở, gửi được tới X-Ray hoặc
      hệ thống khác
        ↓
    Đổi backend không phải sửa mã ứng
      dụng

Vì sao các phương án khác sai

  • **C. Dùng X-Ray cho tracing nhưng EventBridge để giám sát container và độ trễ — đây là phương án gần nhất và vế X-Ray hoàn toàn đúng, nhưng EventBridge là bus định tuyến sự kiện, nó không thu thập metric và không tạo alarm được.
  • **A. Dùng CloudWatch cho request tracing + CloudTrail ghi hoạt động người dùng — CloudWatch không ghép các đoạn của một yêu cầu qua nhiều dịch vụ; CloudTrail ghi lời gọi API AWS chứ không ghi yêu cầu người dùng cuối.
  • **D. EventBridge giám sát + AWS Config đánh giá cấu hình — Config kiểm cấu hình tài nguyên, không liên quan tới hiệu năng ứng dụng, và phương án này hoàn toàn thiếu tracing.

Ghi nhớ

⚠ Ba trụ cột observability — bảng phải thuộc: | Trụ cột | Dịch vụ | Trả lời | |---|---|---| | Metric | CloudWatch | có bất thường không | | Log | CloudWatch Logs | chuyện gì xảy ra ở đây | | Trace | X-Ray | thời gian đi đâu mất |

Từ khoá nhận diện:

"deeper insight into microservices" → X-Ray "request tracing" → X-Ray, KHÔNG phải CloudWatch "monitor containers" → Container Insights "route events between services" → EventBridge

Ba lưu ý về X-Ray: | Lưu ý | Chi tiết | |---|---| | Header X-Amzn-Trace-Id phải được chuyển tiếp | | | Annotation lọc được, metadata thì không | | | Lấy mẫu quyết định chi phí | |

Ba lưu ý về bật X-Ray: | Dịch vụ | Cách | |---|---| | Lambda | --tracing-config Mode=Active | | API Gateway | tracingEnabled=true | | ECS/EC2 | chạy X-Ray daemon |

Ba lưu ý về CloudWatch alarm: | Lưu ý | Chi tiết | |---|---| | Dùng p99 thay Average cho độ trễ | | | Đặt evaluation-periods tránh báo giả | | | Composite alarm gộp nhiều điều kiện | |

Ba lưu ý về Container Insights: | Lưu ý | Chi tiết | |---|---| | Bật ở cấp cụm ECS hoặc EKS | | | Metric theo cụm, dịch vụ, tác vụ | | | Tính phí theo metric thu thập | |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | X-Ray tính theo trace ghi và quét | | | Lấy mẫu giảm chi phí đáng kể | | | Đặt retention cho log group | |

Ba lưu ý về ADOT: | Lưu ý | Chi tiết | |---|---| | Chuẩn OpenTelemetry, không khoá nhà cung cấp | | | Gửi được tới X-Ray và hệ thống khác | | | Có collector chạy như sidecar | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Xem Service Map có đủ mọi dịch vụ không | | | Kiểm trace có bị đứt đoạn không | | | Thử alarm bằng cách tạo tải giả | |

Và một lời khuyên: hãy kiểm tra Service Map có nối liền các dịch vụ hay bị đứt thành nhiều mảnh rời. Trace đứt đoạn là dấu hiệu header X-Amzn-Trace-Id không được chuyển tiếp ở đâu đó — và khi đó X-Ray vẫn chạy, vẫn tốn tiền, nhưng lại không trả lời được đúng câu hỏi mà bạn dựng nó lên để hỏi.

Câu 484 Chọn nhiều đáp án Continuous Improvement for Existing Solutions

An e-commerce company is investigating user reports of its Java-based web application errors on the day of the Thanksgiving sale. The development team recovered the logs created by the EC2 instance-hosted web servers and reviewed Aurora DB cluster performance metrics. Some of the web servers were terminated before logs could be collected and the Aurora metrics were inadequate for query performance analysis.

Which of the following steps would you recommend to make the monitoring process more reliable to troubleshoot any future events due to traffic spikes? (Select three)

  1. A

    Set up the AWS X-Ray SDK to trace incoming HTTP requests on the EC2 instances as well as set up tracing of SQL queries with the X-Ray SDK for Java

  2. B

    Enable detailed monitoring for Amazon EC2 instances to send data points to CloudWatch every minute. Track the metric 'CPUUtilization' to know when the auto-scaling process can kick in

  3. C

    Install and configure an Amazon CloudWatch Logs agent on the EC2 instances to send the application logs to CloudWatch Logs

  4. D

    Enable Aurora lab mode which will then publish all logs and activity on Aurora DB to CloudWatch logs

  5. E

    Use CloudTrail and configure a trail to deliver Amazon Aurora query activity to an Amazon S3 bucket. Process and analyze these real-time log streams using Amazon Kinesis Data Streams

  6. F

    Configure the Aurora MySQL DB cluster to publish slow query and error logs to Amazon CloudWatch Logs

Xem giải thích

Đáp án

**A, C và F — Dùng X-Ray SDK theo dõi yêu cầu HTTP trên EC2 và theo dõi truy vấn SQL bằng X-Ray SDK for Java; cài CloudWatch Logs agent trên EC2 để đẩy log ứng dụng lên CloudWatch Logs; và cấu hình cụm Aurora MySQL đẩy slow query log và error log lên CloudWatch Logs.

Vì sao đúng

Đề nêu đúng hai thất bại, và ba mệnh đề đúng chữa cả hai: | Thất bại | Cách chữa | |---|---| | Máy chủ bị kết thúc trước khi lấy được log | C — đẩy log ra ngoài liên tục | | Metric Aurora không đủ để phân tích truy vấn | F — bật slow query log | | Không thấy đường đi của yêu cầu | A — X-Ray tracing |

⚠ Điểm mấu chốt thứ nhất: log phải rời khỏi máy TRƯỚC khi máy chết:

Auto Scaling kết thúc instance
        ↓
    Đĩa gốc bị xoá theo
        ↓
    Log nằm trên đĩa đó → mất
        ↓
    → CloudWatch Logs agent đẩy liên
      tục
    → log tồn tại độc lập với máy

Cấu hình agent:

{"agent": {"metrics_collection_interval": 60},
 "logs": {"logs_collected": {"files": {"collect_list": [
   {"file_path": "/var/log/ung-dung/ung-dung.log",
    "log_group_name": "/ec2/ung-dung",
    "log_stream_name": "{instance_id}",
    "retention_in_days": 30},
   {"file_path": "/var/log/cloud-init-output.log",
    "log_group_name": "/ec2/khoi-dong",
    "log_stream_name": "{instance_id}"}]}}},
 "metrics": {"namespace": "UngDung",
   "metrics_collected": {
     "mem": {"measurement": ["mem_used_percent"]},
     "disk": {"measurement": ["used_percent"],
              "resources": ["/"]}}}}
aws ssm put-parameter --name /cau-hinh/cloudwatch-agent \
  --type String --value file://cau-hinh.json

aws ssm send-command \
  --document-name AmazonCloudWatch-ManageAgent \
  --targets Key=tag:Nhom,Values=ung-dung \
  --parameters action=configure,mode=ec2,\
optionalConfigurationSource=ssm,\
optionalConfigurationLocation=/cau-hinh/cloudwatch-agent,\
optionalRestart=yes

⚠ Và agent còn thu thập metric bộ nhớ và đĩa:

CloudWatch mặc định KHÔNG có metric
  bộ nhớ của EC2
        ↓
    Vì đó là thông tin bên trong hệ
      điều hành
        ↓
    → phải cài agent mới có
    → rất nhiều sự cố "hết bộ nhớ"
      không có metric nào ghi lại

⚠ Điểm mấu chốt thứ hai: Aurora phải được bảo bật log:

aws rds modify-db-cluster \
  --db-cluster-identifier cum-aurora \
  --cloudwatch-logs-export-configuration \
    'EnableLogTypes=["slowquery","error","audit"]' \
  --apply-immediately

Và bật slow query log trong parameter group:

aws rds modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name nhom-tham-so-aurora \
  --parameters \
    ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate \
    ParameterName=long_query_time,ParameterValue=1,ApplyMethod=immediate \
    ParameterName=log_output,ParameterValue=FILE,ApplyMethod=immediate

⚠ Và log_output=FILE là bắt buộc để xuất sang CloudWatch:

`log_output=TABLE` ghi vào bảng
  `mysql.slow_log`
        ↓
    Không xuất sang CloudWatch được
        ↓
    → phải là `FILE`

⚠ Và long_query_time mặc định 10 giây là quá cao:

Truy vấn 3 giây không bị ghi
        ↓
    Nhưng 3 giây × hàng nghìn lượt
        ↓
    Đó chính là thứ làm sập hệ thống
      trong ngày sale
    → đặt 1 giây hoặc thấp hơn

⚠ Và Performance Insights là công cụ mạnh hơn cho việc này:

aws rds modify-db-instance \
  --db-instance-identifier aurora-1 \
  --enable-performance-insights \
  --performance-insights-retention-period 731 \
  --apply-immediately
Thấy truy vấn nào chiếm nhiều thời
  gian nhất
        ↓
    Phân tích theo wait event
        ↓
    Giữ được tới 2 năm
    → đề không nhắc nhưng nên bật

⚠ Điểm mấu chốt thứ ba: X-Ray SDK for Java theo dõi được cả SQL:

import com.amazonaws.xray.sql.TracingDataSource;

DataSource nguon = TracingDataSource.decorate(nguonGoc);
Mỗi truy vấn SQL thành một subsegment
        ↓
    Thấy truy vấn nào chậm, chạy bao
      nhiêu lần
        ↓
    Và nó gắn với đúng yêu cầu HTTP
      nào
    → chính là thứ "metric Aurora
      không cung cấp được"

⚠ Và vì sao mệnh đề B không giải quyết vấn đề của đề:

B bật detailed monitoring, theo dõi
  `CPUUtilization`
        ↓
    Đó là giám sát cơ bản
        ↓
    Đề nói vấn đề là KHÔNG THU THẬP
      ĐƯỢC LOG và KHÔNG PHÂN TÍCH ĐƯỢC
      TRUY VẤN
        ↓
    CPU không trả lời hai câu hỏi đó
Và detailed monitoring chỉ đổi tần
  suất từ 5 phút xuống 1 phút
        ↓
    Hữu ích, nhưng không phải cái
      thiếu ở đây

⚠ Và vì sao mệnh đề D sai — lab mode không phải để ghi log:

D nói bật "Aurora lab mode" để đẩy
  mọi log lên CloudWatch
        ↓
    Lab mode bật các tính năng ĐANG
      THỬ NGHIỆM của Aurora
        ↓
    Không liên quan gì tới ghi log
        ↓
    Và không nên bật trên hệ thống sản
      xuất

⚠ Và vì sao mệnh đề E sai — CloudTrail không ghi truy vấn:

E nói dùng CloudTrail đưa hoạt động
  truy vấn Aurora vào S3
        ↓
    CloudTrail ghi lời gọi API QUẢN TRỊ
        ↓
    `CreateDBCluster`, `ModifyDBInstance`
        ↓
    Nó KHÔNG thấy câu `SELECT` nào
    → đó là việc của audit log và slow
      query log

Bảng phân biệt log của Aurora: | Log | Ghi gì | |---|---| | Error log | lỗi khởi động, lỗi engine | | Slow query log | truy vấn vượt long_query_time | | General log | MỌI truy vấn (rất nặng) | | Audit log | truy cập, thay đổi lược đồ | | CloudTrail | thao tác quản trị RDS |

⚠ Và general log rất nguy hiểm trên hệ thống bận:

Ghi MỌI truy vấn
        ↓
    Hàng GB log mỗi giờ
        ↓
    Chậm CSDL và tốn tiền CloudWatch
      Logs
    → chỉ bật khi chẩn đoán, và tắt
      ngay sau đó

⚠ Và nên thêm lifecycle hook để lấy log lần cuối:

aws autoscaling put-lifecycle-hook \
  --auto-scaling-group-name asg-web \
  --lifecycle-hook-name thu-thap-log \
  --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \
  --heartbeat-timeout 300 --default-result CONTINUE \
  --notification-target-arn <arn-sns> \
  --role-arn <arn-role>
Instance chuyển sang `Terminating:Wait`
        ↓
    Lambda chạy `flush` cho agent
        ↓
    Rồi cho phép kết thúc
    → bắt được cả những dòng log cuối
      cùng

⚠ Và nên đặt truy vấn Logs Insights sẵn cho lần sau:

fields @timestamp, @message
| filter @message like /Exception/
| stats count() as soLoi by bin(5m)
| sort @timestamp desc

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Log tồn tại độc lập với máy | | | Biết truy vấn nào chậm và chậm bao nhiêu | | | Trace nối yêu cầu HTTP với truy vấn SQL | |

⚠ Và đây là điểm khiến ba mệnh đề bổ trợ nhau:

Log cho biết ngoại lệ nào xảy ra
        ↓
    Slow query log cho biết truy vấn
      nào chậm
        ↓
    Trace nối chúng lại: yêu cầu nào
      gọi truy vấn nào và mất bao lâu
    → ba mảnh của cùng một bức tranh

Vì sao các phương án khác sai

  • **B. Bật detailed monitoring và theo dõi CPUUtilization — đây là phương án gần nhất và giám sát chi tiết mỗi phút thật sự hữu ích, nhưng đề nói vấn đề là không thu thập được log và không phân tích được truy vấn; CPU không trả lời hai câu hỏi đó.
  • **D. Bật Aurora lab mode để đẩy mọi log lên CloudWatch — lab mode bật các tính năng đang thử nghiệm, không liên quan tới ghi log.
  • **E. Dùng CloudTrail đưa hoạt động truy vấn Aurora vào S3 — CloudTrail ghi lời gọi API quản trị, không thấy được câu truy vấn nào.

Ghi nhớ

⚠ Bốn nguồn dữ liệu chẩn đoán — bảng phải thuộc: | Nguồn | Trả lời | |---|---| | CloudWatch Logs agent | ứng dụng ghi gì | | Slow query log | truy vấn nào chậm | | X-Ray | thời gian đi đâu | | Performance Insights | CSDL chờ cái gì |

Từ khoá nhận diện:

"logs lost when instance terminated" → CloudWatch Logs agent "metrics inadequate for query analysis" → slow query log hoặc Performance Insights "trace SQL queries" → X-Ray SDK for Java "CloudTrail for query activity" → LUÔN SAI

Ba lưu ý về CloudWatch Logs agent: | Lưu ý | Chi tiết | |---|---| | Cần instance profile có quyền ghi log | | | Thu thập cả metric bộ nhớ và đĩa | | | Cấu hình qua SSM Parameter Store | |

Ba lưu ý về slow query log: | Lưu ý | Chi tiết | |---|---| | log_output phải là FILE | | | long_query_time mặc định 10 giây, quá cao | | | Xuất sang CloudWatch bằng cloudwatch-logs-export-configuration | |

Ba lưu ý về X-Ray với Java: | Lưu ý | Chi tiết | |---|---| | TracingDataSource bọc DataSource | | | Servlet filter bắt yêu cầu HTTP | | | Cần X-Ray daemon chạy trên máy | |

Ba lưu ý về log của Aurora: | Log | Cảnh báo | |---|---| | Error log | nên luôn bật | | Slow query log | nên bật, đặt ngưỡng thấp | | General log | chỉ bật khi chẩn đoán |

Ba lưu ý về giữ log: | Lưu ý | Chi tiết | |---|---| | Log group mặc định giữ vĩnh viễn | | | Đặt retention để kiểm soát chi phí | | | Xuất sang S3 cho lưu trữ dài hạn | |

Ba lưu ý về Auto Scaling: | Lưu ý | Chi tiết | |---|---| | Lifecycle hook để lấy log lần cuối | | | Tạm dừng Terminate khi cần điều tra | | | Grace period đủ cho ứng dụng khởi động | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Kết thúc một instance thử, xem log còn không | | | Chạy truy vấn chậm, kiểm slow query log | | | Xem trace có chứa subsegment SQL không | |

Và một lời khuyên: hãy hạ long_query_time xuống 1 giây thay vì để mặc định 10 giây. Truy vấn mất 10 giây thì ai cũng thấy — thứ làm sập hệ thống trong ngày cao điểm thường là truy vấn 2 giây chạy hàng nghìn lần, và với ngưỡng mặc định thì không dòng nào trong số đó được ghi lại.

Câu 485 AWS Analytics

A company has deployed sensors in its factories to continuously monitor environmental factors such as temperature and lighting. The company seeks an AWS solution to stream this data for real-time analysis and to alert the factory management team immediately if any readings exceed predefined thresholds.

What AWS setup would best achieve this goal?

  1. A

    Stream the sensor data to Amazon Kinesis Data Firehose, process it with Amazon EC2 instances for real-time analysis, and employ Amazon SNS for urgent notifications to the management team.

  2. B

    Stream the sensor data into AWS IoT Core, process it using Amazon Kinesis Data Analytics, and integrate Amazon SES to email the management team about any critical deviations.

  3. C

    Stream the environmental data to Amazon Kinesis Data Streams, analyze it using an AWS Lambda function, and configure Amazon SNS to send immediate alerts to the management team if anomalies are detected.

  4. D

    Stream the sensor data to Amazon Managed Streaming for Apache Kafka (MSK), utilize AWS Lambda for data analysis, and set up Amazon SNS to alert the management team in case of threshold breaches.

Xem giải thích

Đáp án

**C — Đưa dữ liệu môi trường vào Amazon Kinesis Data Streams, phân tích bằng một hàm AWS Lambda, và cấu hình Amazon SNS gửi cảnh báo tức thì cho đội quản lý khi phát hiện bất thường.

Vì sao đúng

Đề đòi phân tích thời gian thực và cảnh báo NGAY LẬP TỨC. Chỉ một tổ hợp trong bốn phương án đáp ứng được cả hai.

⚠ Điểm mấu chốt: Data Streams có độ trễ dưới một giây, Firehose thì không: | | Data Streams | Data Firehose | |---|---|---| | Độ trễ tới người tiêu thụ | ~200 ms | tối thiểu 60 giây | | Mục đích | xử lý thời gian thực | nạp vào kho dữ liệu | | Người tiêu thụ | tự viết hoặc Lambda | có sẵn |

Cảm biến báo nhiệt độ vượt ngưỡng
        ↓
    Firehose gom lô 60 giây
        ↓
    → cảnh báo tới sau ít nhất một
      phút
    → không phải "ngay lập tức"

⚠ Và đó là lý do phương án A sai:

A dùng Firehose
        ↓
    Cộng thêm: xử lý bằng EC2
        ↓
    Firehose không đẩy được vào EC2
        ↓
    → hai lỗi trong một phương án

⚠ Và Firehose có chế độ không buffer, nhưng vẫn không phải thời gian thực:

Đặt `IntervalInSeconds` = 0
        ↓
    Chỉ áp cho một số đích
        ↓
    Và vẫn là mô hình NẠP, không phải
      mô hình XỬ LÝ
    → đích của Firehose là kho, không
      phải mã của bạn

Dựng luồng:

aws kinesis create-stream \
  --stream-name du-lieu-cam-bien \
  --stream-mode-details StreamMode=ON_DEMAND

⚠ Và chế độ on-demand bỏ được việc quản shard: | Chế độ | Đặc điểm | |---|---| | Provisioned | tự chọn số shard, rẻ hơn khi tải ổn định | | On-demand | tự co giãn, đắt hơn nhưng không phải quản |

Nối Lambda vào luồng:

aws lambda create-event-source-mapping \
  --function-name phan-tich-cam-bien \
  --event-source-arn <arn-stream> \
  --starting-position LATEST \
  --batch-size 100 \
  --maximum-batching-window-in-seconds 1 \
  --parallelization-factor 4 \
  --function-response-types ReportBatchItemFailures

⚠ Và maximum-batching-window quyết định độ trễ:

Đặt 0 hoặc 1 giây
        ↓
    Lambda được gọi gần như ngay
        ↓
    Đặt 30 giây
        ↓
    Gom được nhiều bản ghi hơn, rẻ hơn
    → nhưng chậm hơn

Hàm phân tích:

import base64, json, os, boto3

sns = boto3.client('sns')
NGUONG_NHIET = float(os.environ['NGUONG_NHIET'])
NGUONG_SANG = float(os.environ['NGUONG_SANG'])

def handler(su_kien, ngu_canh):
    hong = []
    for ban_ghi in su_kien['Records']:
        try:
            du_lieu = json.loads(
                base64.b64decode(ban_ghi['kinesis']['data']))
        except Exception:
            hong.append({'itemIdentifier':
                         ban_ghi['kinesis']['sequenceNumber']})
            continue
        canh_bao = []
        if du_lieu.get('nhietDo', 0) > NGUONG_NHIET:
            canh_bao.append(
                f"Nhiet do {du_lieu['nhietDo']}°C vuot nguong")
        if du_lieu.get('doSang', 0) > NGUONG_SANG:
            canh_bao.append(
                f"Do sang {du_lieu['doSang']} lux vuot nguong")
        if canh_bao:
            sns.publish(
                TopicArn=os.environ['ARN_TOPIC'],
                Subject=f"Canh bao nha may {du_lieu['maNhaMay']}",
                Message='\n'.join(canh_bao),
                MessageAttributes={
                    'maNhaMay': {'DataType': 'String',
                                 'StringValue': du_lieu['maNhaMay']}})
    return {'batchItemFailures': hong}

⚠ Và ReportBatchItemFailures là chi tiết quan trọng:

Không bật
        ↓
    Một bản ghi hỏng → cả lô thất bại
        ↓
    Lambda thử lại cả lô
        ↓
    Bản ghi hỏng vẫn hỏng
    → vòng lặp chặn shard vĩnh viễn
Bật lên
        ↓
    Chỉ báo bản ghi nào hỏng
        ↓
    Luồng đi tiếp
    → tránh được "poison pill"

⚠ Và nên có đích cho bản ghi thất bại:

aws lambda update-event-source-mapping \
  --uuid <uuid> \
  --maximum-retry-attempts 3 \
  --maximum-record-age-in-seconds 3600 \
  --destination-config '{"OnFailure": {
    "Destination": "<arn-sqs-that-bai>"}}'

⚠ Và vì sao phương án B không tốt bằng:

B dùng IoT Core → Kinesis Data
  Analytics → SES
        ↓
    IoT Core hợp lý cho cảm biến
        ↓
    Nhưng SES gửi EMAIL
        ↓
    Đề nói "cảnh báo tức thì cho đội
      quản lý"
    → SNS gửi được SMS, push, email,
      và gọi Lambda

⚠ Và SES là dịch vụ gửi thư hàng loạt, không phải hệ thống cảnh báo: | | SNS | SES | |---|---|---| | Mục đích | thông báo hệ thống | email marketing/giao dịch | | Kênh | email, SMS, push, HTTP, SQS, Lambda | chỉ email | | Fanout | có | không | | Lọc theo thuộc tính | có | không |

⚠ Và Kinesis Data Analytics (nay là Managed Flink) hợp cho phân tích cửa sổ:

Trung bình 5 phút, phát hiện xu hướng
        ↓
    Đó là thế mạnh của nó
        ↓
    Ở đây chỉ so ngưỡng đơn giản
    → Lambda đủ và rẻ hơn nhiều

⚠ Và vì sao phương án D quá nặng:

D dùng Amazon MSK
        ↓
    MSK là Kafka được quản lý
        ↓
    Vẫn phải chọn số broker, kích thước
      instance, dung lượng đĩa
        ↓
    Hợp khi đã có hệ sinh thái Kafka
    → dựng mới cho vài cảm biến là quá
      mức

Bảng bốn dịch vụ luồng: | Dịch vụ | Vận hành | Độ trễ | |---|---|---| | Data Streams | shard hoặc on-demand | ~200 ms | | Data Firehose | không có gì | ≥60 giây | | MSK | broker, đĩa | thấp | | IoT Core | không có gì | thấp |

⚠ Và IoT Core đáng cân nhắc nếu cảm biến nhiều:

aws iot create-topic-rule --rule-name canh-bao-nhiet \
  --topic-rule-payload '{
    "sql": "SELECT * FROM \"nha-may/+/cam-bien\" WHERE nhietDo > 80",
    "actions": [{"sns": {
      "targetArn": "<arn-topic>",
      "roleArn": "<arn-role>"}}]}'
IoT Core lọc ngay bằng SQL trong rule
        ↓
    Gọi thẳng SNS
        ↓
    Không cần Lambda
    → nhưng đề không đưa phương án nào
      như vậy

⚠ Và khoá phân vùng quyết định tính song song:

kinesis.put_record(
    StreamName='du-lieu-cam-bien',
    Data=json.dumps(du_lieu),
    PartitionKey=du_lieu['maNhaMay'])
Dùng mã nhà máy làm khoá
        ↓
    Dữ liệu cùng nhà máy vào cùng shard
        ↓
    Giữ được thứ tự theo nhà máy
        ↓
    Nhưng một nhà máy quá nhiều dữ liệu
    → shard nóng, các shard khác nhàn

⚠ Và shard nóng là vấn đề thực tế:

aws cloudwatch get-metric-statistics \
  --namespace AWS/Kinesis \
  --metric-name WriteProvisionedThroughputExceeded \
  --dimensions Name=StreamName,Value=du-lieu-cam-bien \
  --statistics Sum --period 300 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-01T12:00:00Z
Chỉ số này khác 0
        ↓
    Có shard bị quá tải
        ↓
    → đổi khoá phân vùng hoặc dùng
      on-demand

⚠ Và nên lọc ở SNS thay vì tạo nhiều topic:

aws sns set-subscription-attributes \
  --subscription-arn <arn-sub> \
  --attribute-name FilterPolicy \
  --attribute-value '{"maNhaMay": ["NM-01", "NM-02"]}'
Quản lý nhà máy 1 chỉ nhận cảnh báo
  của nhà máy 1
        ↓
    Một topic duy nhất
    → và mỗi người lọc phần của mình

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Cảnh báo trong vài trăm mili giây | | | Không có máy chủ nào để vận hành | | | Dữ liệu giữ lại được để phân tích sau | |

⚠ Và Data Streams giữ dữ liệu để xử lý lại:

aws kinesis increase-stream-retention-period \
  --stream-name du-lieu-cam-bien \
  --retention-period-hours 168
Sửa lỗi trong logic phân tích
        ↓
    Chạy lại từ dữ liệu đã lưu
        ↓
    Firehose không làm được việc này
    → dữ liệu đã ghi ra đích rồi

Vì sao các phương án khác sai

  • **D. Dùng Amazon MSK + Lambda + SNS — đây là phương án gần nhất và về mặt chức năng hoàn toàn hoạt động, nhưng MSK đòi chọn số broker, kích thước instance và dung lượng đĩa; đó là gánh nặng vận hành không cần thiết khi Kinesis Data Streams làm cùng việc mà không cần vận hành gì.
  • **A. Firehose + xử lý bằng EC2 + SNS — Firehose có độ trễ tối thiểu 60 giây và không đẩy được vào EC2.
  • **B. IoT Core + Kinesis Data Analytics + SES — SES là dịch vụ gửi email, không phải hệ thống cảnh báo đa kênh; và phân tích cửa sổ là quá mức cho việc so ngưỡng.

Ghi nhớ

⚠ Bốn dịch vụ luồng dữ liệu — bảng phải thuộc: | Dịch vụ | Chọn khi | |---|---| | Data Streams | thời gian thực, cần xử lý bằng mã | | Data Firehose | nạp vào S3/Redshift, không cần thời gian thực | | MSK | đã có hệ sinh thái Kafka | | IoT Core | hàng nghìn thiết bị, cần MQTT |

Từ khoá nhận diện:

"real-time analysis, immediate alerts" → Data Streams + Lambda + SNS "buffer then load to S3" → Firehose "send email to customers" → SES "notify operations team" → SNS

Ba lưu ý về Data Streams: | Lưu ý | Chi tiết | |---|---| | On-demand bỏ việc quản shard | | | Giữ dữ liệu tới 365 ngày | | | Khoá phân vùng quyết định phân bố | |

Ba lưu ý về Lambda + Kinesis: | Lưu ý | Chi tiết | |---|---| | ReportBatchItemFailures tránh poison pill | | | maximum-batching-window quyết định độ trễ | | | parallelization-factor tăng song song mỗi shard | |

Ba lưu ý về SNS: | Lưu ý | Chi tiết | |---|---| | Nhiều kênh: email, SMS, push, HTTP | | | Filter policy trên từng subscription | | | FIFO topic nếu cần thứ tự | |

Ba lưu ý về shard nóng: | Lưu ý | Chi tiết | |---|---| | Theo dõi WriteProvisionedThroughputExceeded | | | Khoá phân vùng lệch gây quá tải một shard | | | On-demand tự chia lại | |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | Provisioned rẻ hơn khi tải ổn định | | | On-demand đắt hơn nhưng không phải quản | | | Enhanced fan-out tính phí riêng | |

Ba lưu ý về IoT Core: | Lưu ý | Chi tiết | |---|---| | Topic rule lọc bằng SQL | | | Gọi thẳng SNS, Lambda, Kinesis | | | Quản danh tính từng thiết bị | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Gửi một bản ghi vượt ngưỡng, đo thời gian tới cảnh báo | | | Kiểm IteratorAge của Lambda | | | Thử một bản ghi hỏng, xem luồng có tiếp tục không | |

Và một lời khuyên: hãy bật ReportBatchItemFailures ngay từ đầu khi nối Lambda vào Kinesis. Một bản ghi cảm biến sai định dạng là chuyện chắc chắn sẽ xảy ra — và không có cờ này, nó chặn toàn bộ shard cho tới khi hết thời gian giữ dữ liệu, nghĩa là mọi cảnh báo sau nó cũng không bao giờ tới.

Câu 486 Chọn nhiều đáp án AWS Management & Governance

A company has created several development accounts in an AWS Organizations organization. The company has defined a fixed budget for each development account and needs to ensure that developers cannot launch expensive services or exceed the fixed monthly budget.

Which combination of steps should a solutions architect take? (Select THREE.)

  1. A

    Create an IAM policy that denies access to expensive services. Apply the IAM policy to the development accounts.

  2. B

    Use the AWS Budgets service to define a fixed monthly budget for each development account.

  3. C

    Create an AWS Budgets alert action to send an Amazon SNS notification when the budgeted amount is reached. Invoke an AWS Lambda function to terminate all services.

  4. D

    Create an AWS Budgets alert action to terminate services when the budgeted amount is reached. Configure the action to terminate all services.

  5. E

    Create an SCP that denies access to expensive services. Apply the SCP to an OU containing the development accounts.

  6. F

    Create an SCP that defines a fixed monthly resource usage limit. Apply the SCP to an OU containing the development accounts.

Xem giải thích

Đáp án

**B, C và E — Dùng AWS Budgets đặt ngân sách cố định hằng tháng cho mỗi tài khoản phát triển; tạo hành động cảnh báo Budgets gửi thông báo SNS khi chạm ngưỡng và gọi một hàm Lambda kết thúc mọi dịch vụ; tạo một SCP từ chối các dịch vụ đắt tiền và gắn vào OU chứa các tài khoản phát triển.

Vì sao đúng

Đề đòi hai thứ, và ba mệnh đề chia nhau lo: | Yêu cầu | Mệnh đề | |---|---| | Không cho dùng dịch vụ đắt tiền | E — SCP deny | | Không vượt ngân sách hằng tháng | B — Budgets + C — hành động khi chạm ngưỡng |

⚠ Điểm mấu chốt thứ nhất: SCP chặn được cả root, chính sách IAM thì không:

Tài khoản phát triển có quản trị viên
  riêng
        ↓
    Chính sách IAM: họ xoá được
        ↓
    Root của tài khoản đó: bỏ qua IAM
      policy
        ↓
    SCP: không xoá được, áp cả root
    → đó là lý do mệnh đề A thua mệnh
      đề E

SCP chặn dịch vụ đắt tiền:

{"Version": "2012-10-17",
 "Statement": [
  {"Sid": "ChanInstanceLon",
   "Effect": "Deny",
   "Action": "ec2:RunInstances",
   "Resource": "arn:aws:ec2:*:*:instance/*",
   "Condition": {"ForAnyValue:StringNotLike": {
     "ec2:InstanceType": ["t3.*", "t4g.*", "m5.large", "m6i.large"]}}},
  {"Sid": "ChanDichVuDatTien",
   "Effect": "Deny",
   "Action": ["redshift:CreateCluster",
              "sagemaker:CreateTrainingJob",
              "emr:RunJobFlow",
              "outposts:*",
              "macie2:*"],
   "Resource": "*"}]}

⚠ Và điều kiện ForAnyValue:StringNotLike là cách chặn theo loại instance:

Cho phép một danh sách trắng loại
  instance
        ↓
    Mọi loại khác bị từ chối
        ↓
    Chặn được `p5.48xlarge` giá hàng
      chục USD mỗi giờ

⚠ Và nên chặn cả Region để giảm bề mặt:

{"Sid": "ChiChoPhepHaiRegion",
 "Effect": "Deny",
 "NotAction": ["iam:*", "sts:*", "organizations:*",
               "cloudfront:*", "route53:*", "support:*",
               "budgets:*", "ce:*"],
 "Resource": "*",
 "Condition": {"StringNotEquals": {
   "aws:RequestedRegion": ["ap-southeast-1", "us-east-1"]}}}

⚠ Điểm mấu chốt thứ hai: SCP KHÔNG hiểu khái niệm tiền:

SCP đánh giá theo hành động, tài
  nguyên, điều kiện
        ↓
    Không có điều kiện nào là "chi phí
      tháng này"
        ↓
    → mệnh đề F sai: không có SCP nào
      "định nghĩa giới hạn sử dụng tài
      nguyên hằng tháng"
Đây là ranh giới quan trọng:
        ↓
    SCP: chặn HÀNH ĐỘNG
        ↓
    Budgets: theo dõi TIỀN
    → hai công cụ, hai tầng

Tạo ngân sách:

aws budgets create-budget --account-id 111122223333 \
  --budget '{
    "BudgetName": "ngan-sach-dev",
    "BudgetLimit": {"Amount": "500", "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST",
    "CostFilters": {"LinkedAccount": ["333344445555"]}}' \
  --notifications-with-subscribers '[
   {"Notification": {"NotificationType": "ACTUAL",
     "ComparisonOperator": "GREATER_THAN",
     "Threshold": 80, "ThresholdType": "PERCENTAGE"},
    "Subscribers": [{"SubscriptionType": "SNS",
      "Address": "<arn-sns>"}]},
   {"Notification": {"NotificationType": "FORECASTED",
     "ComparisonOperator": "GREATER_THAN",
     "Threshold": 100, "ThresholdType": "PERCENTAGE"},
    "Subscribers": [{"SubscriptionType": "SNS",
      "Address": "<arn-sns>"}]}]'

⚠ Và nên có cả hai loại thông báo: | Loại | Ý nghĩa | |---|---| | ACTUAL 80% | cảnh báo sớm, còn thời gian phản ứng | | FORECASTED 100% | dự báo sẽ vượt cuối tháng | | ACTUAL 100% | đã vượt, kích hoạt hành động |

⚠ Điểm mấu chốt thứ ba: vì sao mệnh đề D sai:

D nói tạo "Budgets alert action để
  kết thúc dịch vụ"
        ↓
    Budgets Actions có ba loại:
      APPLY_IAM_POLICY
      APPLY_SCP_POLICY
      RUN_SSM_DOCUMENTS
        ↓
    Không có loại nào tên "terminate
      all services"
    → phải qua SSM document hoặc Lambda

⚠ Và đó là lý do mệnh đề C dùng Lambda:

SNS nhận thông báo từ Budgets
        ↓
    Gọi Lambda
        ↓
    Lambda tự viết logic dừng tài
      nguyên
    → linh hoạt hơn nhiều so với SSM
      document dựng sẵn

Hàm dừng tài nguyên:

import boto3, os

def handler(su_kien, ngu_canh):
    ec2 = boto3.client('ec2')
    rds = boto3.client('rds')

    may = [i['InstanceId']
           for r in ec2.describe_instances(
               Filters=[{'Name': 'instance-state-name',
                         'Values': ['running']}])['Reservations']
           for i in r['Instances']]
    if may:
        ec2.stop_instances(InstanceIds=may)

    for db in rds.describe_db_instances()['DBInstances']:
        if db['DBInstanceStatus'] == 'available':
            rds.stop_db_instance(
                DBInstanceIdentifier=db['DBInstanceIdentifier'])
    return {'soMayDaDung': len(may)}

⚠ Và nên DỪNG chứ đừng KẾT THÚC:

`terminate-instances` xoá vĩnh viễn
        ↓
    Mất cả dữ liệu trên đĩa gốc
        ↓
    `stop-instances` giữ nguyên mọi thứ
        ↓
    Chỉ ngừng tính tiền tính toán
    → khôi phục được khi ngân sách
      tháng sau về
Đề dùng từ "terminate"
        ↓
    Nhưng trong thực tế nên dừng
    → và đây là chi tiết đáng cân nhắc
      trước khi triển khai

⚠ Và Budgets Actions gắn SCP là cách gọn hơn:

aws budgets create-budget-action \
  --account-id 111122223333 \
  --budget-name ngan-sach-dev \
  --notification-type ACTUAL \
  --action-type APPLY_SCP_POLICY \
  --action-threshold ActionThresholdValue=100,ActionThresholdType=PERCENTAGE \
  --definition '{"ScpActionDefinition": {
    "PolicyId": "p-chi-doc",
    "TargetIds": ["ou-dev-11111111"]}}' \
  --execution-role-arn <arn-role> \
  --approval-model AUTOMATIC \
  --subscribers '[{"SubscriptionType":"SNS","Address":"<arn-sns>"}]'

⚠ Và chỉ nên để AUTOMATIC cho môi trường phát triển:

Tài khoản dev → tự động chặn được
        ↓
    Tài khoản sản xuất → `MANUAL`
        ↓
    Tự động chặn sản xuất
    → biến vấn đề tài chính thành sự
      cố ngừng dịch vụ

⚠ Và Budgets có độ trễ dữ liệu:

Dữ liệu chi phí cập nhật vài lần mỗi
  ngày
        ↓
    Không phải thời gian thực
        ↓
    Một instance đắt chạy vài giờ
    → có thể vượt ngân sách trước khi
      cảnh báo tới
        ↓
    → đó là lý do phải có CẢ SCP chặn
      trước

⚠ Và đây là lý do ba mệnh đề bổ trợ nhau:

SCP: chặn từ đầu, tức thì, không thể
  vượt qua
        ↓
    Budgets: bắt phần còn lại — dùng
      nhiều dịch vụ rẻ cũng thành đắt
        ↓
    Lambda: hành động khi ngưỡng bị
      chạm

⚠ Và nên bật Cost Anomaly Detection nữa:

aws ce create-anomaly-monitor \
  --anomaly-monitor '{
    "MonitorName": "giam-sat-dev",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE"}'
Chi phí tăng gấp năm nhưng vẫn dưới
  ngân sách
        ↓
    Budgets im lặng
        ↓
    Anomaly Detection báo ngay

⚠ Và nên gắn thẻ để biết ai tiêu tiền:

{"Sid": "BatBuocGanThe",
 "Effect": "Deny",
 "Action": ["ec2:RunInstances", "rds:CreateDBInstance"],
 "Resource": "*",
 "Condition": {"Null": {
   "aws:RequestTag/ChuSoHuu": "true"}}}

Ba lợi ích của tổ hợp: | Lợi ích | Chi tiết | |---|---| | Dịch vụ đắt bị chặn ngay từ đầu | | | Ngân sách có trần cứng | | | Tự động dừng khi vượt | |

Vì sao các phương án khác sai

  • **A. Tạo chính sách IAM từ chối dịch vụ đắt tiền và gắn vào các tài khoản phát triển — đây là phương án gần nhất và về nội dung chính sách là giống hệt SCP, nhưng quản trị viên của tài khoản đó xoá được nó và root user hoàn toàn bỏ qua chính sách IAM.
  • **F. Tạo SCP định nghĩa giới hạn sử dụng tài nguyên hằng tháng — SCP đánh giá theo hành động và điều kiện, không có khái niệm chi phí hay hạn mức tiền.
  • **D. Tạo Budgets alert action kết thúc dịch vụ trực tiếp — Budgets Actions chỉ có ba loại: gắn IAM policy, gắn SCP, hoặc chạy SSM document; không có hành động "kết thúc mọi dịch vụ".

Ghi nhớ

⚠ Ba loại Budgets Action — bảng phải thuộc: | Loại | Làm gì | |---|---| | APPLY_IAM_POLICY | gắn chính sách hạn chế cho user/role | | APPLY_SCP_POLICY | gắn SCP vào OU hoặc tài khoản | | RUN_SSM_DOCUMENTS | dừng EC2 hoặc RDS |

Từ khoá nhận diện:

"prevent expensive services" → SCP "fixed monthly budget" → AWS Budgets "SCP with usage limit" → LUÔN SAI "IAM policy on member accounts" → root bỏ qua được

Ba lưu ý về SCP: | Lưu ý | Chi tiết | |---|---| | Áp cả root của tài khoản con | | | Không sửa được từ trong tài khoản | | | Chặn theo loại instance bằng điều kiện | |

Ba lưu ý về Budgets: | Lưu ý | Chi tiết | |---|---| | Dữ liệu có độ trễ, không thời gian thực | | | Đặt cả ACTUAL và FORECASTED | | | AUTOMATIC chỉ cho môi trường dev | |

Ba lưu ý về hành động dừng tài nguyên: | Lưu ý | Chi tiết | |---|---| | Dừng an toàn hơn kết thúc | | | Loại trừ tài nguyên có thẻ bảo vệ | | | Ghi log những gì đã dừng | |

Ba lưu ý về nhiều tầng kiểm soát: | Tầng | Việc | |---|---| | SCP | chặn trước, tức thì | | Budgets | theo dõi tiền | | Anomaly Detection | bắt tăng đột ngột |

Ba lưu ý về gắn thẻ: | Lưu ý | Chi tiết | |---|---| | Bắt buộc thẻ chủ sở hữu bằng SCP | | | Bật cost allocation tag | | | Xem chi phí theo thẻ trong Cost Explorer | |

Ba lưu ý về ngoại lệ: | Lưu ý | Chi tiết | |---|---| | Chừa quyền support:* để mở ticket | | | Chừa budgets:* và ce:* để xem chi phí | | | Chừa iam:* và sts:* để không tự khoá | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Thử tạo instance loại lớn — phải bị từ chối | | | Vượt ngân sách ở tài khoản sandbox | | | Kiểm Lambda có dừng đúng tài nguyên không | |

Và một lời khuyên: hãy dùng stop thay vì terminate trong hàm phản ứng ngân sách. Đề bài viết "terminate", nhưng dừng máy đạt được cùng mục đích tiết kiệm mà không xoá mất công việc của lập trình viên — và một cơ chế kiểm soát chi phí phá hỏng dữ liệu sẽ bị đội phát triển tìm cách vô hiệu hoá ngay tuần sau.

Câu 487 AWS Database

A company has a mobile application that uses Amazon API Gateway, AWS Lambda, and Amazon DynamoDB. The application is write intensive and costs have recently increased significantly. The biggest increase in cost has been for the AWS Lambda functions. Application utilization is unpredictable but has been increasing steadily each month.

A Solutions Architect has noticed that the Lambda function execution time averages over 4 minutes. This is due to wait time for a high-latency network call to an on-premises MySQL database. A VPN is used to connect to the VPC.
How can the Solutions Architect reduce the cost of the current architecture?

  1. A

    - Replace the VPN with AWS Direct Connect to reduce the network latency to the on-premises MySQL database.

    - Cache the API Gateway results to Amazon CloudFront.

    - Use Amazon EC2 Reserved Instances instead of Lambda.

    - Enable Auto Scaling on EC2 and use Spot Instances during peak times.

    - Enable DynamoDB Auto Scaling to manage target utilization.

  2. B

    - Replace the VPN with AWS Direct Connect to reduce the network latency to the on-premises MySQL database.

    - Enable local caching in the mobile application to reduce the Lambda function invocation calls.

    - Offload the frequently accessed records from DynamoDB to Amazon ElastiCache.

  3. C

    - Migrate the MySQL database server into a Multi-AZ Amazon RDS for MySQL.

    - Enable caching of the Amazon API Gateway results in Amazon CloudFront to reduce the number of Lambda function invocations.

    - Enable DynamoDB Accelerator for frequently accessed records and enable the DynamoDB Auto Scaling feature.

  4. D

    - Migrate the MySQL database server into a Multi-AZ Amazon RDS for MySQL.

    - Enable API caching on API Gateway to reduce the number of Lambda function invocations.

    - Enable Auto Scaling in DynamoDB.

Xem giải thích

Đáp án

**D — Di trú máy chủ MySQL sang Amazon RDS for MySQL Multi-AZ; bật API caching trên API Gateway để giảm số lần gọi Lambda; và bật Auto Scaling cho DynamoDB.

Vì sao đúng

Chi phí Lambda tăng vì hàm chạy trung bình hơn 4 phút, phần lớn là chờ mạng. Lambda tính tiền theo thời gian chạy × bộ nhớ, kể cả thời gian ngồi chờ.

⚠ Điểm mấu chốt: Lambda tính tiền cả lúc KHÔNG làm gì:

Hàm gọi CSDL tại chỗ qua VPN
        ↓
    Chờ phản hồi 4 phút
        ↓
    CPU gần như rảnh hoàn toàn
        ↓
    Nhưng vẫn tính đủ 4 phút × bộ nhớ
    → trả tiền cho việc chờ

Tính cụ thể:

1 triệu lời gọi/tháng
        ↓
    240 giây mỗi lời gọi, 1.024 MB
        ↓
    240 × 1 × 1.024/1024 = 240.000.000
      GB-giây
        ↓
    × 0,0000166667 USD ≈ 4.000 USD
Rút xuống 2 giây:
        ↓
    2.000.000 GB-giây ≈ 33 USD
    → giảm hơn 99%

⚠ Và cách chữa gốc là bỏ độ trễ mạng, không phải giảm độ trễ:

Phương án A và B chọn Direct Connect
        ↓
    Giảm độ trễ từ VPN xuống DX
        ↓
    Nhưng vẫn là gọi qua mạng ra ngoài
        ↓
    Di trú CSDL vào AWS
    → độ trễ xuống mili giây

⚠ Và Direct Connect còn thêm chi phí cố định:

Phí cổng theo giờ + phí lắp đặt
        ↓
    Cho một vấn đề giải quyết được
      bằng cách di trú CSDL
    → đề hỏi cách GIẢM chi phí

Di trú bằng DMS:

aws dms create-replication-task \
  --replication-task-identifier di-tru-mysql \
  --source-endpoint-arn <arn-mysql-tai-cho> \
  --target-endpoint-arn <arn-rds> \
  --migration-type full-load-and-cdc \
  --table-mappings file://anh-xa.json

⚠ Và Multi-AZ là lựa chọn đúng vì ứng dụng ghi nhiều:

Đề nói "write intensive"
        ↓
    Read replica không giúp gì cho ghi
        ↓
    Multi-AZ cho sẵn sàng cao
    → và ghi vẫn đi vào một node

⚠ Điểm mấu chốt thứ hai: API caching giảm số lần GỌI Lambda:

aws apigateway update-stage \
  --rest-api-id abc123 --stage-name prod \
  --patch-operations \
    op=replace,path=/cacheClusterEnabled,value=true \
    op=replace,path=/cacheClusterSize,value=1.6 \
    op=replace,path=/*/*/caching/enabled,value=true \
    op=replace,path=/*/*/caching/ttlInSeconds,value=300
Yêu cầu trùng nhau
        ↓
    API Gateway trả từ cache
        ↓
    Lambda KHÔNG được gọi
    → không tính tiền lời gọi đó

⚠ Và đây là khác biệt với phương án C:

C dùng CloudFront cache kết quả API
  Gateway
        ↓
    Cũng giảm được lời gọi
        ↓
    Nhưng thêm một dịch vụ nữa
        ↓
    API caching là tính năng CÓ SẴN
      của API Gateway
    → đơn giản hơn cho cùng mục đích

⚠ Và C còn thêm DAX — không cần thiết ở đây:

C thêm DynamoDB Accelerator
        ↓
    DAX tăng tốc ĐỌC
        ↓
    Đề nói ứng dụng GHI NHIỀU
        ↓
    DAX là cụm phải trả tiền theo giờ
    → thêm chi phí cho vấn đề không
      tồn tại

⚠ Và cache API chỉ hợp với dữ liệu ĐỌC:

Yêu cầu `GET` giống nhau → cache tốt
        ↓
    Yêu cầu `POST` ghi dữ liệu → không
      cache
        ↓
    Ứng dụng ghi nhiều
    → chỉ phần đọc hưởng lợi
    → nhưng đó vẫn là phần đáng kể

⚠ Và cache key phải cấu hình đúng:

aws apigateway update-method \
  --rest-api-id abc123 --resource-id xyz \
  --http-method GET \
  --patch-operations \
    op=replace,path=/requestParameters/method.request.querystring.maNguoiDung/required,value=true
Không khai tham số vào cache key
        ↓
    Mọi người dùng nhận cùng một kết
      quả
    → lỗi rò rỉ dữ liệu giữa các tài
      khoản

⚠ Và phải cho phép người gọi bỏ qua cache khi cần:

{"Sid": "ChoPhepXoaCache",
 "Effect": "Allow",
 "Action": "execute-api:InvalidateCache",
 "Resource": "arn:aws:execute-api:*:*:abc123/prod/GET/*"}

⚠ Điểm mấu chốt thứ ba: DynamoDB Auto Scaling:

aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id table/bang-du-lieu \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --min-capacity 5 --max-capacity 500

aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id table/bang-du-lieu \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --policy-name chinh-sach-ghi \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"}}'
Đề nói mức dùng tăng đều mỗi tháng
        ↓
    Provisioned cố định → phải chỉnh
      tay
        ↓
    Auto Scaling tự tăng theo
    → và tự giảm khi rảnh

⚠ Và cân nhắc on-demand nếu tải khó đoán:

Đề nói "unpredictable but increasing"
        ↓
    Auto Scaling phản ứng sau vài phút
        ↓
    On-demand phản ứng tức thì
        ↓
    Nhưng đắt hơn ~6 lần mỗi đơn vị
    → tải tăng đều thì Auto Scaling
      rẻ hơn

⚠ Và nên xem lại bộ nhớ của Lambda sau khi di trú:

aws lambda update-function-configuration \
  --function-name xu-ly-don \
  --memory-size 512 --timeout 30
Timeout đang đặt cao vì chờ mạng
        ↓
    Sau khi CSDL vào AWS, chỉ cần vài
      giây
        ↓
    Hạ timeout → lỗi lộ ra sớm hơn
    → thay vì treo 5 phút mới báo

⚠ Và AWS Lambda Power Tuning tìm được cấu hình rẻ nhất:

Bộ nhớ nhiều hơn → CPU mạnh hơn →
  chạy nhanh hơn
        ↓
    Có điểm mà tăng bộ nhớ lại RẺ hơn
        ↓
    Vì thời gian giảm nhiều hơn mức
      giá tăng
    → chỉ đo mới biết

⚠ Và nên dùng RDS Proxy khi Lambda gọi CSDL:

aws rds create-db-proxy \
  --db-proxy-name proxy-mysql \
  --engine-family MYSQL \
  --auth '[{"SecretArn": "<arn-secret>",
            "IAMAuth": "DISABLED"}]' \
  --role-arn <arn-role> \
  --vpc-subnet-ids subnet-a subnet-b
Hàng nghìn Lambda đồng thời
        ↓
    Mỗi cái mở một kết nối CSDL
        ↓
    MySQL hết `max_connections`
        ↓
    RDS Proxy gom kết nối
    → và giữ kết nối qua các lần gọi

⚠ Và vì sao phương án B không giải quyết được:

B cache ở phía ỨNG DỤNG DI ĐỘNG
        ↓
    Giảm số lời gọi, đúng
        ↓
    Nhưng phải phát hành phiên bản mới
      của app
        ↓
    Người dùng cập nhật chậm
    → và vẫn giữ nguyên độ trễ CSDL

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Thời gian chạy Lambda giảm hơn 99% | | | Số lời gọi giảm nhờ cache | | | DynamoDB tự co giãn theo tải | |

⚠ Và nên đo lại sau khi di trú:

aws cloudwatch get-metric-statistics \
  --namespace AWS/Lambda --metric-name Duration \
  --dimensions Name=FunctionName,Value=xu-ly-don \
  --statistics Average,Maximum --period 3600 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-02T00:00:00Z

Vì sao các phương án khác sai

  • **C. Di trú sang RDS Multi-AZ + cache API Gateway trong CloudFront + DAX + DynamoDB Auto Scaling — đây là phương án gần nhất và phần di trú CSDL hoàn toàn đúng, nhưng API Gateway đã có tính năng caching sẵn nên thêm CloudFront là thừa, và DAX tăng tốc đọc trong khi đề nói ứng dụng ghi nhiều.
  • **B. Thay VPN bằng Direct Connect + cache ở ứng dụng di động + ElastiCache — vẫn giữ CSDL ở tại chỗ nên độ trễ vẫn cao, và cache phía client đòi phát hành phiên bản app mới.
  • **A. Direct Connect + CloudFront + chuyển sang EC2 Reserved Instance và Spot — thay Lambda bằng EC2 là đi ngược hướng serverless và không giải quyết nguyên nhân gốc là độ trễ mạng.

Ghi nhớ

⚠ Bốn cách giảm chi phí Lambda — bảng phải thuộc: | Cách | Tác động | |---|---| | Giảm thời gian chạy | lớn nhất — tính tiền theo GB-giây | | Giảm số lời gọi (cache) | lớn | | Tối ưu bộ nhớ | vừa, cần đo | | Dùng ARM (Graviton) | ~20% rẻ hơn |

Từ khoá nhận diện:

"Lambda cost high, 4 minute duration" → hàm đang chờ, bỏ độ trễ mạng "reduce Lambda invocations" → API Gateway caching "write intensive" → DAX không giúp gì "connection exhaustion" → RDS Proxy

Ba lưu ý về chi phí Lambda: | Lưu ý | Chi tiết | |---|---| | Tính theo GB-giây, kể cả lúc chờ | | | Bộ nhớ nhiều hơn có thể RẺ hơn | | | Graviton rẻ hơn khoảng 20% | |

Ba lưu ý về API Gateway caching: | Lưu ý | Chi tiết | |---|---| | Tính phí theo giờ theo kích thước cache | | | Cache key phải bao gồm tham số phân biệt người dùng | | | Chỉ hợp với phương thức đọc | |

Ba lưu ý về DynamoDB: | Lưu ý | Chi tiết | |---|---| | Auto Scaling rẻ hơn on-demand khi tải tăng đều | | | On-demand phản ứng tức thì hơn | | | DAX chỉ tăng tốc đọc | |

Ba lưu ý về Lambda trong VPC: | Lưu ý | Chi tiết | |---|---| | Cần endpoint hoặc NAT để gọi dịch vụ AWS | | | RDS Proxy gom kết nối CSDL | | | Đặt ở nhiều subnet cho sẵn sàng cao | |

Ba lưu ý về di trú CSDL: | Lưu ý | Chi tiết | |---|---| | DMS full load + CDC giảm thời gian ngừng | | | Multi-AZ cho sẵn sàng cao khi ghi nhiều | | | Read replica cho tải đọc | |

Ba lưu ý về đo lường: | Metric | Ý nghĩa | |---|---| | Duration | thời gian chạy, quyết định chi phí | | Invocations | số lời gọi | | ConcurrentExecutions | mức đồng thời |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | So Duration trước và sau di trú | | | Đo tỷ lệ cache hit của API Gateway | | | Xem hoá đơn Lambda tháng sau | |

Và một lời khuyên: hãy hạ timeout của Lambda xuống ngay sau khi di trú cơ sở dữ liệu. Timeout dài là thứ che giấu chi phí: khi CSDL đã nằm trong cùng VPC, một hàm chạy quá 30 giây gần như chắc chắn là đang mắc kẹt chứ không phải đang làm việc — và với timeout 15 phút, bạn sẽ trả tiền cho toàn bộ khoảng mắc kẹt đó.

Câu 488 AWS Application Integration

A company runs a data processing application on-premises and plans to move it to the AWS Cloud. Files are uploaded by users to a web application which then stores the files on an NFS-based storage system and places a message on a queue. The files are then processed from the queue and the results are returned to the user (and stored in long-term storage). This process can take up to 30 minutes. The processing times vary significantly and can be much higher during business hours.

What is the MOST cost-effective migration recommendation?

  1. A

    Create a queue using Amazon MQ. Run the web application on Amazon EC2 and configure it to publish to the new queue. Launch an Amazon EC2 instance from a preconfigured AMI to poll the queue, pull requests, and process the files. Store the processed files in Amazon EFS. Terminate the EC2 instance after the task is complete.

  2. B

    Create a queue using Amazon SQS. Run the web application on Amazon EC2 and configure it to publish to the new queue. Use an AWS Lambda function to poll the queue, pull requests, and process the files. Store the processed files in an Amazon S3 bucket.

  3. C

    Create a queue using Amazon MQ. Run the web application on Amazon EC2 and configure it to publish to the new queue. Use an AWS Lambda function to poll the queue, pull requests, and process the files. Store the processed files in Amazon EFS.

  4. D

    Create a queue using Amazon SQS. Run the web application on Amazon EC2 and configure it to publish to the new queue. Use Amazon EC2 instances in an EC2 Auto Scaling group to pull requests from the queue and process the files. Scale the EC2 instances based on the SQS queue length. Store the processed files in an Amazon S3 bucket.

Xem giải thích

Đáp án

**D — Tạo hàng đợi bằng Amazon SQS; chạy ứng dụng web trên EC2 và cấu hình nó đẩy vào hàng đợi; dùng EC2 Auto Scaling group lấy yêu cầu từ hàng đợi và xử lý tệp, co giãn theo độ dài hàng đợi; lưu tệp đã xử lý vào Amazon S3.

Vì sao đúng

Ba đặc điểm của bài toán quyết định mọi lựa chọn: | Đặc điểm | Hệ quả | |---|---| | Xử lý mất tới 30 phút | Lambda không dùng được (tối đa 15 phút) | | Tải dao động mạnh theo giờ | cần co giãn theo hàng đợi | | Cần rẻ nhất | SQS + S3, không phải Amazon MQ + EFS |

⚠ Điểm mấu chốt: Lambda tối đa 15 phút — đây là ràng buộc cứng:

Đề nói "quá trình này có thể mất tới
  30 phút"
        ↓
    Lambda hết giờ ở 15 phút
        ↓
    → phương án B và C loại ngay
    → không cần đọc phần còn lại

⚠ Và giới hạn này không nâng được:

Không phải hạn ngạch mềm
        ↓
    Không mở ticket xin tăng được
        ↓
    Việc chạy lâu → Fargate, Batch,
      hoặc EC2

Bảng thời gian chạy tối đa: | Dịch vụ | Tối đa | |---|---| | Lambda | 15 phút | | Fargate task | không giới hạn | | AWS Batch | không giới hạn | | EC2 | không giới hạn |

⚠ Điểm mấu chốt thứ hai: SQS rẻ hơn Amazon MQ nhiều: | | SQS | Amazon MQ | |---|---|---| | Mô hình | serverless | broker chạy liên tục | | Chi phí | theo yêu cầu | theo giờ broker | | Giao thức | API riêng của AWS | AMQP, MQTT, STOMP, JMS | | Chọn khi | xây mới | di trú ứng dụng dùng broker sẵn |

Amazon MQ: ~150 USD/tháng cho broker
  nhỏ nhất chạy hai AZ
        ↓
    SQS: 0,40 USD mỗi triệu yêu cầu
        ↓
    Đề hỏi "rẻ nhất"
    → và ứng dụng đang được viết lại
      nên không cần giao thức cũ

⚠ Và Amazon MQ chỉ đúng khi di trú ứng dụng đã dùng JMS hoặc AMQP:

Ứng dụng cũ dùng ActiveMQ hay RabbitMQ
        ↓
    Không muốn sửa mã
        ↓
    → Amazon MQ giữ nguyên giao thức
        ↓
    Đề nói ứng dụng đang di trú và
      thiết kế lại
    → SQS phù hợp hơn

⚠ Điểm mấu chốt thứ ba: S3 rẻ hơn EFS nhiều lần: | Kho | Giá xấp xỉ mỗi GB-tháng | |---|---| | S3 Standard | 0,023 USD | | EFS Standard | 0,30 USD |

Tệp đã xử lý là kết quả cuối
        ↓
    Chỉ đọc lại thỉnh thoảng
        ↓
    Không cần POSIX, không cần nhiều
      máy cùng ghi
    → S3 đúng và rẻ hơn 13 lần

Co giãn theo độ dài hàng đợi:

aws cloudwatch put-metric-alarm \
  --alarm-name hang-doi-dai \
  --namespace AWS/SQS \
  --metric-name ApproximateNumberOfMessagesVisible \
  --dimensions Name=QueueName,Value=hang-doi-xu-ly \
  --statistic Average --period 300 \
  --threshold 100 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 1

⚠ Và cách đúng hơn là dùng target tracking với backlog per instance:

aws autoscaling put-scaling-policy \
  --auto-scaling-group-name asg-xu-ly \
  --policy-name theo-hang-doi \
  --policy-type TargetTrackingScaling \
  --target-tracking-configuration '{
    "TargetValue": 10.0,
    "CustomizedMetricSpecification": {
      "MetricName": "TonDongMoiMay",
      "Namespace": "UngDung",
      "Statistic": "Average"},
    "EstimatedInstanceWarmup": 300}'

Tính chỉ số tồn đọng mỗi máy:

import boto3

cw = boto3.client('cloudwatch')
sqs = boto3.client('sqs')
asg = boto3.client('autoscaling')

def handler(su_kien, ngu_canh):
    thuoc_tinh = sqs.get_queue_attributes(
        QueueUrl=URL_HANG_DOI,
        AttributeNames=['ApproximateNumberOfMessages'])
    so_tin = int(thuoc_tinh['Attributes']
                 ['ApproximateNumberOfMessages'])
    nhom = asg.describe_auto_scaling_groups(
        AutoScalingGroupNames=['asg-xu-ly'])['AutoScalingGroups'][0]
    so_may = max(len([i for i in nhom['Instances']
                      if i['LifecycleState'] == 'InService']), 1)
    cw.put_metric_data(Namespace='UngDung', MetricData=[{
        'MetricName': 'TonDongMoiMay',
        'Value': so_tin / so_may,
        'Unit': 'Count'}])

⚠ Và vì sao đếm số thông điệp thuần không đủ:

1.000 thông điệp
        ↓
    Với 2 máy → rất tệ
        ↓
    Với 100 máy → bình thường
        ↓
    → phải chia cho số máy mới có ý
      nghĩa

⚠ Và visibility timeout phải bằng thời gian xử lý dài nhất:

aws sqs set-queue-attributes \
  --queue-url <url> \
  --attributes VisibilityTimeout=2100
Xử lý tới 30 phút = 1.800 giây
        ↓
    Đặt visibility timeout 2.100 giây
      (35 phút)
        ↓
    Ngắn hơn → thông điệp hiện lại khi
      đang xử lý
    → tệp bị xử lý hai lần

⚠ Và tối đa của visibility timeout là 12 giờ:

Việc chạy lâu hơn thế
        ↓
    Phải gia hạn định kỳ trong lúc xử

      lý
sqs.change_message_visibility(
    QueueUrl=URL_HANG_DOI,
    ReceiptHandle=the,
    VisibilityTimeout=600)

⚠ Và nên bảo vệ instance đang xử lý khỏi bị thu nhỏ:

aws autoscaling set-instance-protection \
  --auto-scaling-group-name asg-xu-ly \
  --instance-ids i-abc --protected-from-scale-in
Máy đang xử lý tệp 25 phút
        ↓
    Auto Scaling quyết định thu nhỏ
        ↓
    Giết đúng máy đó
    → công việc mất, thông điệp quay
      lại hàng đợi sau 35 phút

Bỏ bảo vệ khi xong:

asg.set_instance_protection(
    InstanceIds=[ma_may],
    AutoScalingGroupName='asg-xu-ly',
    ProtectedFromScaleIn=False)

⚠ Hoặc dùng lifecycle hook cho êm hơn:

aws autoscaling put-lifecycle-hook \
  --auto-scaling-group-name asg-xu-ly \
  --lifecycle-hook-name cho-xu-ly-xong \
  --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \
  --heartbeat-timeout 2100 --default-result CONTINUE

⚠ Và Spot Instance giảm chi phí rất nhiều ở đây:

Công việc chạy lại được (thông điệp
  quay về hàng đợi)
        ↓
    Bị thu hồi → máy khác nhận lại
        ↓
    Rẻ hơn tới 90%
    → nhưng phải xử lý tín hiệu thu hồi
Instance metadata báo trước 2 phút
        ↓
    Ứng dụng nghe tín hiệu
        ↓
    Trả thông điệp về hàng đợi ngay
    → thay vì chờ hết visibility
      timeout

⚠ Và nên có dead-letter queue:

aws sqs set-queue-attributes --queue-url <url> \
  --attributes '{"RedrivePolicy":
    "{\"deadLetterTargetArn\":\"<arn-dlq>\",\"maxReceiveCount\":\"3\"}"}'

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Không giới hạn thời gian xử lý | | | Co giãn theo tải thật | | | Rẻ hơn Amazon MQ và EFS nhiều lần | |

⚠ Và Fargate là lựa chọn hiện đại hơn EC2:

Không phải quản AMI, không phải vá hệ
  điều hành
        ↓
    Co giãn theo cùng chỉ số hàng đợi
        ↓
    Nhưng đắt hơn EC2 Spot cho tải
      chạy lâu
    → đề không đưa phương án này

Vì sao các phương án khác sai

  • **A. Amazon MQ + EC2 khởi chạy từ AMI dựng sẵn + EFS, kết thúc sau khi xong — đây là phương án gần nhất và kiến trúc hàng đợi + worker là đúng, nhưng Amazon MQ tính tiền theo giờ broker và EFS đắt hơn S3 nhiều lần; ngoài ra khởi chạy một instance mới cho mỗi việc rất chậm.
  • **B. SQS + AWS Lambda thăm dò hàng đợi — Lambda tối đa 15 phút, không xử lý được việc mất tới 30 phút.
  • **C. Amazon MQ + Lambda + EFS — vừa vướng giới hạn 15 phút của Lambda vừa đắt ở cả hai thành phần còn lại.

Ghi nhớ

⚠ Bốn lựa chọn xử lý bất đồng bộ — bảng phải thuộc: | Lựa chọn | Thời gian tối đa | |---|---| | Lambda | 15 phút | | Fargate | không giới hạn | | AWS Batch | không giới hạn | | EC2 ASG | không giới hạn |

Từ khoá nhận diện:

"up to 30 minutes" → loại Lambda ngay "most cost-effective queue" → SQS, không phải Amazon MQ "migrate existing JMS app" → Amazon MQ "scale on queue length" → backlog per instance

Ba lưu ý về SQS và Amazon MQ: | Lưu ý | Chi tiết | |---|---| | SQS serverless, trả theo yêu cầu | | | MQ trả theo giờ broker | | | MQ chỉ khi cần giao thức chuẩn | |

Ba lưu ý về visibility timeout: | Lưu ý | Chi tiết | |---|---| | Phải dài hơn thời gian xử lý dài nhất | | | Tối đa 12 giờ | | | Gia hạn được bằng ChangeMessageVisibility | |

Ba lưu ý về co giãn theo hàng đợi: | Lưu ý | Chi tiết | |---|---| | Dùng tồn đọng mỗi máy, không dùng số thông điệp thuần | | | Đặt EstimatedInstanceWarmup đủ dài | | | Bảo vệ máy đang xử lý khỏi thu nhỏ | |

Ba lưu ý về Spot: | Lưu ý | Chi tiết | |---|---| | Rẻ hơn tới 90% | | | Nghe tín hiệu thu hồi 2 phút | | | Trả thông điệp về hàng đợi khi bị thu hồi | |

Ba lưu ý về lưu trữ kết quả: | Kho | Dùng khi | |---|---| | S3 | kết quả cuối, chỉ đọc | | EFS | nhiều máy cùng ghi, cần POSIX | | EBS | một máy, hiệu năng cao |

Ba lưu ý về độ tin cậy: | Lưu ý | Chi tiết | |---|---| | Dead-letter queue cho việc hỏng | | | Xử lý phải idempotent | | | Cảnh báo ApproximateAgeOfOldestMessage | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Đẩy 100 việc, xem ASG có tăng không | | | Giết một máy đang xử lý, kiểm việc có quay lại hàng đợi | | | Đo chi phí mỗi việc xử lý | |

Và một lời khuyên: hãy bật scale-in protection cho instance khi nó bắt đầu xử lý một việc và tắt đi khi xong. Auto Scaling không biết máy nào đang bận — nó chọn máy để kết thúc theo quy tắc riêng, và với việc chạy 30 phút thì xác suất nó giết đúng máy đang làm dở là chuyện xảy ra hằng ngày chứ không phải hiếm.

Câu 489 AWS Application Integration

An eCommerce company are running a promotional campaign and expect a large volume of user sign-ups on a web page that collects user information and preferences. The website runs on Amazon EC2 instances and uses an Amazon RDS for PostgreSQL DB instance. The volume of traffic is expected to be high and may be unpredictable with several spikes in activity. The traffic will result in a large number of database writes.

A solutions architect needs to build a solution that does not change the underlying data model and ensures that submissions are not dropped before they are committed to the database.
Which solution meets these requirements?

  1. A

    Use scheduled scaling to scale up the existing DB instance immediately before the event and then automatically scale down afterwards.

  2. B

    Migrate to Amazon DynamoDB and manage throughput capacity with automatic scaling.

  3. C

    Create an Amazon SQS queue and decouple the application and database layers. Configure an AWS Lambda function to write items from the queue into the database.

  4. D

    Create an Amazon ElastiCache for Memcached cluster in front of the existing database instance to increase write performance.

Xem giải thích

Đáp án

**C — Tạo một hàng đợi Amazon SQS để tách rời tầng ứng dụng và tầng cơ sở dữ liệu; cấu hình một hàm AWS Lambda đọc từ hàng đợi và ghi vào cơ sở dữ liệu.

Vì sao đúng

Đề có hai ràng buộc rất cụ thể, và chúng loại gần hết các phương án: | Ràng buộc | Hệ quả | |---|---| | Không được đổi mô hình dữ liệu | phải giữ PostgreSQL | | Không được mất bản đăng ký nào | phải có bộ đệm bền vững |

⚠ Điểm mấu chốt: hàng đợi hấp thụ đỉnh mà CSDL không chịu nổi:

10.000 lượt đăng ký/giây ập tới
        ↓
    CSDL chỉ ghi được 500/giây
        ↓
    Không có hàng đợi → 9.500 lượt
      thất bại
        ↓
    Có hàng đợi → nhận hết vào hàng
      đợi
    → Lambda ghi vào CSDL theo nhịp
      CSDL chịu được
Hàng đợi dài lên tạm thời
        ↓
    Rồi rút xuống khi đỉnh qua
        ↓
    → không mất bản ghi nào
    → chỉ có độ trễ, không có thất bại

⚠ Và SQS giữ thông điệp tới 14 ngày:

aws sqs create-queue --queue-name dang-ky \
  --attributes '{
    "MessageRetentionPeriod": "1209600",
    "VisibilityTimeout": "60",
    "ReceiveMessageWaitTimeSeconds": "20"}'
CSDL chết hoàn toàn nửa ngày
        ↓
    Thông điệp vẫn nằm nguyên trong
      hàng đợi
        ↓
    CSDL trở lại → xử lý tiếp
    → đây chính là "không mất bản nào"

⚠ Và vì sao phương án B vi phạm ràng buộc rõ ràng nhất:

B di trú sang DynamoDB
        ↓
    Đề nói RÕ "không đổi mô hình dữ
      liệu"
        ↓
    DynamoDB là NoSQL khoá–giá trị
        ↓
    Chuyển từ quan hệ sang đó là đổi
      mô hình
    → loại ngay

⚠ Và vì sao phương án D không giải quyết gì:

D dùng ElastiCache for Memcached ở
  trước CSDL
        ↓
    Cache tăng tốc ĐỌC
        ↓
    Đề nói tải là GHI
        ↓
    Cache không hấp thụ được lượt ghi
    → và Memcached không bền vững

⚠ Và đây là hiểu lầm rất phổ biến:

"Đặt cache trước CSDL để tăng hiệu
  năng"
        ↓
    Đúng với đọc
        ↓
    Với ghi thì cache không giúp gì
    → trừ khi dùng write-behind, mà
      Memcached không có

⚠ Và vì sao phương án A không đủ:

A dùng scheduled scaling nâng cấp
  instance trước sự kiện
        ↓
    Đề nói lưu lượng "không đoán trước
      được, nhiều đợt đột biến"
        ↓
    Scheduled scaling cần biết TRƯỚC
      thời điểm
        ↓
    Và RDS đổi kích thước instance gây
      NGỪNG DỊCH VỤ vài phút

⚠ Và đổi kích thước RDS không phải thao tác tức thì:

`modify-db-instance` đổi class
        ↓
    Multi-AZ: chuyển đổi, ngừng ~60-120
      giây
        ↓
    Single-AZ: ngừng vài phút
        ↓
    → không phản ứng kịp với đột biến

Kiến trúc đúng:

Người dùng
    ↓
EC2 (web) → SQS
                ↓
            Lambda
                ↓
            RDS PostgreSQL

Nối Lambda vào SQS:

aws lambda create-event-source-mapping \
  --function-name ghi-dang-ky \
  --event-source-arn <arn-sqs> \
  --batch-size 25 \
  --maximum-batching-window-in-seconds 5 \
  --scaling-config MaximumConcurrency=20 \
  --function-response-types ReportBatchItemFailures

⚠ Và MaximumConcurrency là chi tiết QUYẾT ĐỊNH ở đây:

Không đặt giới hạn
        ↓
    Lambda co giãn tới hàng nghìn
      instance
        ↓
    Mỗi cái mở một kết nối PostgreSQL
        ↓
    → CSDL hết `max_connections`
    → hàng đợi vừa cứu CSDL vừa giết
      nó
Đặt `MaximumConcurrency=20`
        ↓
    Tối đa 20 kết nối cùng lúc
        ↓
    Hàng đợi dài ra nhưng CSDL sống
    → đây mới là tách rời thật sự

⚠ Và RDS Proxy giải quyết triệt để hơn:

aws rds create-db-proxy \
  --db-proxy-name proxy-dang-ky \
  --engine-family POSTGRESQL \
  --auth '[{"SecretArn": "<arn-secret>"}]' \
  --role-arn <arn-role> \
  --vpc-subnet-ids subnet-a subnet-b \
  --require-tls
Proxy gom kết nối
        ↓
    Hàng trăm Lambda dùng chung một
      nhóm kết nối nhỏ
        ↓
    Và giữ kết nối giữa các lần gọi
    → bỏ được chi phí bắt tay TLS mỗi
      lần

Ghi theo lô:

import json, os, psycopg

def handler(su_kien, ngu_canh):
    hong = []
    ban_ghi = []
    for r in su_kien['Records']:
        try:
            d = json.loads(r['body'])
            ban_ghi.append((d['email'], d['ten'],
                            json.dumps(d.get('tuyChon', {}))))
        except Exception:
            hong.append({'itemIdentifier': r['messageId']})

    if ban_ghi:
        with psycopg.connect(os.environ['CHUOI_KET_NOI']) as ket_noi:
            with ket_noi.cursor() as con_tro:
                con_tro.executemany(
                    'INSERT INTO dang_ky (email, ten, tuy_chon) '
                    'VALUES (%s, %s, %s) ON CONFLICT (email) DO NOTHING',
                    ban_ghi)
    return {'batchItemFailures': hong}

⚠ Và ON CONFLICT DO NOTHING là bắt buộc:

SQS chuẩn bảo đảm giao ÍT NHẤT một
  lần
        ↓
    Thông điệp có thể tới hai lần
        ↓
    Không xử lý trùng → hai bản ghi
      cùng email
    → mọi hàm tiêu thụ SQS phải
      idempotent

⚠ Và ghi theo lô nhanh hơn ghi từng dòng rất nhiều:

25 lệnh `INSERT` riêng
        ↓
    25 vòng đi về mạng
        ↓
    Một lệnh `executemany`
    → một vòng, nhanh hơn nhiều lần

⚠ Và ReportBatchItemFailures tránh xử lý lại cả lô:

Không bật
        ↓
    Một bản ghi hỏng → cả lô 25 quay
      lại hàng đợi
        ↓
    24 bản ghi tốt bị ghi lại lần nữa
    → và lần nữa, và lần nữa

⚠ Và phải có dead-letter queue:

aws sqs set-queue-attributes --queue-url <url> \
  --attributes '{"RedrivePolicy":
    "{\"deadLetterTargetArn\":\"<arn-dlq>\",\"maxReceiveCount\":\"5\"}"}'

⚠ Và tầng web phải trả lời người dùng NGAY:

Nhận đăng ký → đẩy vào SQS → trả
  "đã nhận"
        ↓
    Không chờ ghi CSDL xong
        ↓
    Người dùng thấy phản hồi tức thì
    → đây là giá trị lớn thứ hai của
      hàng đợi

⚠ Nhưng phải xử lý được việc người dùng không thấy dữ liệu ngay:

Đăng ký xong, vào trang cá nhân
        ↓
    Bản ghi chưa được ghi
        ↓
    → thiết kế giao diện chấp nhận độ
      trễ
    → hoặc ghi vào cache trước

⚠ Và nên theo dõi độ sâu hàng đợi:

aws cloudwatch put-metric-alarm \
  --alarm-name hang-doi-ton-dong \
  --namespace AWS/SQS \
  --metric-name ApproximateAgeOfOldestMessage \
  --dimensions Name=QueueName,Value=dang-ky \
  --statistic Maximum --period 300 \
  --threshold 600 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 --alarm-actions <arn-sns>
Tuổi thông điệp cũ nhất tăng dần
        ↓
    Người tiêu thụ không theo kịp
        ↓
    → tăng `MaximumConcurrency` hoặc
      nâng cấp CSDL

⚠ Và có thể dùng Aurora Serverless v2 nếu muốn CSDL tự co giãn:

aws rds create-db-cluster \
  --db-cluster-identifier cum-dang-ky \
  --engine aurora-postgresql \
  --serverless-v2-scaling-configuration \
    MinCapacity=0.5,MaxCapacity=16
Co giãn theo giây, không ngừng dịch
  vụ
        ↓
    Vẫn là PostgreSQL, không đổi mô
      hình dữ liệu
    → nhưng đề không đưa phương án này

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Không mất bản đăng ký nào | | | Giữ nguyên mô hình dữ liệu | | | Người dùng nhận phản hồi tức thì | |

Vì sao các phương án khác sai

  • **A. Dùng scheduled scaling nâng cấp instance trước sự kiện rồi hạ xuống sau — đây là phương án gần nhất và giữ nguyên mô hình dữ liệu, nhưng đề nói lưu lượng không đoán trước được nên không lên lịch được, và đổi kích thước RDS gây ngừng dịch vụ vài phút.
  • **B. Di trú sang DynamoDB với auto scaling — vi phạm trực tiếp yêu cầu "không đổi mô hình dữ liệu".
  • **D. Đặt ElastiCache for Memcached trước CSDL — cache tăng tốc đọc, không hấp thụ được tải ghi, và Memcached không bền vững.

Ghi nhớ

⚠ Bốn cách xử lý đỉnh tải ghi — bảng phải thuộc: | Cách | Đổi mô hình dữ liệu | |---|---| | Hàng đợi + worker | không | | Aurora Serverless v2 | không | | Chuyển sang DynamoDB | CÓ | | Nâng cấp instance | không, nhưng ngừng dịch vụ |

Từ khoá nhận diện:

"no submissions dropped" → hàng đợi bền vững "without changing the data model" → giữ CSDL quan hệ "unpredictable spikes" → không dùng scheduled scaling "cache in front of database" → chỉ giúp đọc

Ba lưu ý về SQS làm bộ đệm: | Lưu ý | Chi tiết | |---|---| | Giữ tới 14 ngày | | | Hấp thụ đỉnh, CSDL ghi theo nhịp của nó | | | Người dùng nhận phản hồi ngay | |

Ba lưu ý về Lambda + SQS + CSDL: | Lưu ý | Chi tiết | |---|---| | MaximumConcurrency giới hạn số kết nối | | | RDS Proxy gom kết nối | | | Ghi theo lô nhanh hơn từng dòng | |

Ba lưu ý về idempotency: | Lưu ý | Chi tiết | |---|---| | SQS chuẩn giao ít nhất một lần | | | ON CONFLICT DO NOTHING hoặc upsert | | | FIFO queue nếu cần đúng một lần | |

Ba lưu ý về giám sát: | Metric | Ý nghĩa | |---|---| | ApproximateNumberOfMessagesVisible | độ sâu hàng đợi | | ApproximateAgeOfOldestMessage | tồn đọng bao lâu | | NumberOfMessagesDeleted | tốc độ xử lý |

Ba lưu ý về trải nghiệm người dùng: | Lưu ý | Chi tiết | |---|---| | Trả phản hồi ngay sau khi vào hàng đợi | | | Thiết kế chấp nhận độ trễ ghi | | | Cho người dùng mã tra cứu nếu cần | |

Ba lưu ý về CSDL: | Lưu ý | Chi tiết | |---|---| | Aurora Serverless v2 co giãn không ngừng dịch vụ | | | Multi-AZ cho sẵn sàng cao khi ghi nhiều | | | Theo dõi DatabaseConnections | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Chạy thử tải với đỉnh dự kiến | | | Kiểm không có bản ghi trùng | | | Đo DatabaseConnections lúc đỉnh | |

Và một lời khuyên: hãy đặt MaximumConcurrency cho event source mapping ngay khi nối Lambda vào SQS trước một cơ sở dữ liệu quan hệ. Không có nó, hàng đợi bảo vệ CSDL khỏi đỉnh lưu lượng nhưng lại thả hàng nghìn Lambda vào tấn công nó cùng lúc — và triệu chứng cuối cùng vẫn là CSDL từ chối kết nối, chỉ khác là giờ khó lần ra hơn.

Câu 490 AWS Networking & Content Delivery

An application stores user comment data in multiple Amazon DynamoDB tables. A solutions architect must use a serverless architecture to make the data accessible publicly through a simple and cost-effective API over HTTPS. The solution must scale automatically in response to demand.

Which solutions meet these requirements?

  1. A

    Create an Amazon API Gateway REST API. Configure this API with direct integrations to DynamoDB by using API Gateway's AWS Service integration type.

  2. B

    Create an Amazon API Gateway REST API. Configure this API with integrations to AWS Lambda functions that return data from the DynamoDB tables.

  3. C

    Create an Amazon API Gateway HTTP API. Configure this API with integrations to AWS Lambda functions that return data from the DynamoDB tables.

  4. D

    Create an Amazon API Gateway HTTP API. Configure this API with direct integrations to DynamoDB by using API Gateway's AWS Service integration type.

Xem giải thích

Đáp án

**C — Tạo một Amazon API Gateway HTTP API và cấu hình nó tích hợp với các hàm AWS Lambda trả dữ liệu từ bảng DynamoDB.

Vì sao đúng

Đề nêu ba yêu cầu, và HTTP API + Lambda là tổ hợp đáp ứng tốt nhất: | Yêu cầu | Cách đáp ứng | |---|---| | Serverless | HTTP API + Lambda + DynamoDB | | Đơn giản và tiết kiệm chi phí | HTTP API rẻ hơn REST API ~71% | | Tự co giãn theo nhu cầu | cả ba đều tự co giãn |

⚠ Điểm mấu chốt: HTTP API rẻ hơn REST API rất nhiều: | | REST API | HTTP API | |---|---|---| | Giá mỗi triệu yêu cầu | 3,50 USD | 1,00 USD | | Độ trễ | cao hơn | thấp hơn ~60% | | Tích hợp AWS Service | có | hạn chế | | Request/response mapping | có | rất hạn chế | | API key + usage plan | có | KHÔNG | | WAF | có | KHÔNG | | Xác thực JWT gốc | không | có |

Đề nói "đơn giản và tiết kiệm chi
  phí"
        ↓
    → HTTP API
    → loại phương án A và B dùng REST
      API

⚠ Điểm mấu chốt thứ hai: HTTP API KHÔNG tích hợp thẳng được với DynamoDB:

Tích hợp kiểu "AWS Service" cho phép
  gọi thẳng dịch vụ AWS
        ↓
    REST API: hỗ trợ đầy đủ
        ↓
    HTTP API: chỉ hỗ trợ một số dịch
      vụ giới hạn
        ↓
    DynamoDB KHÔNG nằm trong danh sách
      đó
    → phương án D không dựng được
Danh sách tích hợp AWS Service của
  HTTP API:
        ↓
    Lambda, HTTP proxy, EventBridge,
    SQS, Step Functions, Kinesis,
    AppConfig
        ↓
    → không có DynamoDB

⚠ Và đây là lý do phải qua Lambda:

HTTP API → Lambda → DynamoDB
        ↓
    Lambda là tích hợp chuẩn của HTTP
      API
        ↓
    Và Lambda gọi DynamoDB bằng SDK
    → đơn giản, ai cũng viết được

Tạo HTTP API:

aws apigatewayv2 create-api \
  --name api-binh-luan \
  --protocol-type HTTP \
  --target <arn-lambda>

⚠ Và --target tạo sẵn route mặc định:

Một lệnh duy nhất
        ↓
    Tạo API, tạo tích hợp, tạo route
      `$default`, tạo stage `$default`
        ↓
    → so với REST API cần 5-6 lệnh
    → đây là "đơn giản" mà đề nói tới

Route cụ thể hơn:

aws apigatewayv2 create-integration \
  --api-id abc123 \
  --integration-type AWS_PROXY \
  --integration-uri <arn-lambda> \
  --payload-format-version 2.0

aws apigatewayv2 create-route \
  --api-id abc123 \
  --route-key 'GET /binh-luan/{maBai}' \
  --target integrations/xyz789

⚠ Và payload-format-version 2.0 khác 1.0 về cấu trúc sự kiện:

1.0: giống REST API, có `httpMethod`,
  `path`
        ↓
    2.0: gọn hơn, có
      `requestContext.http.method`
        ↓
    Và 2.0 cho phép trả về chuỗi thuần
    → Lambda tự bọc thành phản hồi 200

Hàm Lambda:

import json, os, boto3
from boto3.dynamodb.conditions import Key

bang = boto3.resource('dynamodb').Table(os.environ['TEN_BANG'])

def handler(su_kien, ngu_canh):
    ma_bai = su_kien['pathParameters']['maBai']
    kq = bang.query(
        KeyConditionExpression=Key('maBai').eq(ma_bai),
        Limit=50, ScanIndexForward=False)
    return {
        'statusCode': 200,
        'headers': {'content-type': 'application/json',
                    'cache-control': 'public, max-age=60'},
        'body': json.dumps(kq['Items'], default=str,
                           ensure_ascii=False)}

⚠ Và dùng Query chứ đừng dùng Scan:

`Scan` đọc TOÀN BỘ bảng
        ↓
    Tốn đơn vị đọc theo kích thước
      bảng
        ↓
    `Query` chỉ đọc phân vùng cần
    → chi phí khác nhau hàng trăm lần

⚠ Và HTTP API không có API key hay usage plan:

Cần giới hạn theo khách hàng
        ↓
    HTTP API không làm được
        ↓
    → phải dùng REST API
        ↓
    Đề nói "công khai", "đơn giản"
    → không cần khoá API

⚠ Và HTTP API cũng không gắn được WAF:

Cần chống SQL injection, bot
        ↓
    → REST API hoặc đặt CloudFront
      trước HTTP API rồi gắn WAF ở đó

⚠ Và HTTP API có throttling nhưng đơn giản hơn:

aws apigatewayv2 update-stage \
  --api-id abc123 --stage-name '$default' \
  --default-route-settings \
    ThrottlingBurstLimit=5000,ThrottlingRateLimit=10000

⚠ Và HTTPS là mặc định, không cấu hình gì:

Mọi endpoint API Gateway đều HTTPS
        ↓
    Chứng chỉ do AWS quản
        ↓
    Đề nói "qua HTTPS"
    → tự động thoả

Tên miền riêng:

aws apigatewayv2 create-domain-name \
  --domain-name api.congty.vn \
  --domain-name-configurations \
    CertificateArn=<arn-acm>,EndpointType=REGIONAL

aws apigatewayv2 create-api-mapping \
  --domain-name api.congty.vn \
  --api-id abc123 --stage '$default'

⚠ Và nên đặt CORS nếu gọi từ trình duyệt:

aws apigatewayv2 update-api --api-id abc123 \
  --cors-configuration \
    AllowOrigins=https://congty.vn,\
AllowMethods=GET,OPTIONS,\
AllowHeaders=content-type,\
MaxAge=600
HTTP API xử lý CORS ở tầng API
        ↓
    Không phải thêm header trong Lambda
        ↓
    REST API thì phải tự lo
    → thêm một điểm "đơn giản hơn"

⚠ Và nên bật cache ở CloudFront nếu dữ liệu ít đổi:

Bình luận người dùng đọc nhiều, ghi
  ít
        ↓
    CloudFront trước HTTP API
        ↓
    Giảm lời gọi Lambda và đọc DynamoDB
    → và HTTP API không có caching sẵn
      như REST API

⚠ Và HTTP API thiếu caching là hạn chế đáng biết: | | REST API | HTTP API | |---|---|---| | Caching tích hợp | có (trả phí theo giờ) | KHÔNG | | Giải pháp | — | CloudFront phía trước |

⚠ Và DynamoDB nên để on-demand cho API công khai:

aws dynamodb update-table --table-name binh-luan \
  --billing-mode PAY_PER_REQUEST
Lưu lượng công khai khó đoán
        ↓
    On-demand tự co giãn
    → và không bị throttle vì đoán sai
      công suất

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Rẻ hơn REST API khoảng 71% | | | Độ trễ thấp hơn | | | Cấu hình đơn giản hơn nhiều | |

⚠ Và nên bật access log để thấy lỗi:

aws apigatewayv2 update-stage --api-id abc123 \
  --stage-name '$default' \
  --access-log-settings \
    DestinationArn=<arn-log-group>,\
Format='{"requestId":"$context.requestId","status":"$context.status","error":"$context.error.message","latency":"$context.responseLatency"}'

Vì sao các phương án khác sai

  • **B. REST API tích hợp với Lambda trả dữ liệu từ DynamoDB — đây là phương án gần nhất và hoàn toàn hoạt động, nhưng REST API đắt gấp 3,5 lần HTTP API và có nhiều tính năng (API key, usage plan, request mapping) mà bài toán này không cần.
  • **A. REST API tích hợp thẳng DynamoDB bằng AWS Service integration — dựng được nhưng đòi viết VTL mapping template khá phức tạp, và vẫn là REST API đắt hơn.
  • **D. HTTP API tích hợp thẳng DynamoDB — HTTP API không hỗ trợ DynamoDB trong danh sách tích hợp AWS Service.

Ghi nhớ

⚠ Bốn khác biệt REST API và HTTP API — bảng phải thuộc: | Tính năng | REST API | HTTP API | |---|---|---| | Giá mỗi triệu yêu cầu | 3,50 USD | 1,00 USD | | API key, usage plan | có | không | | WAF | có | không | | Caching tích hợp | có | không | | Xác thực JWT gốc | không | có | | Tích hợp DynamoDB trực tiếp | có | không |

Từ khoá nhận diện:

"simple and cost-effective API" → HTTP API "API keys for customers" → REST API "WAF protection" → REST API hoặc CloudFront + HTTP API "JWT authorizer" → HTTP API

Ba lưu ý về HTTP API: | Lưu ý | Chi tiết | |---|---| | Tích hợp AWS Service rất hạn chế | | | CORS cấu hình ở tầng API | | | Không có caching, dùng CloudFront | |

Ba lưu ý về payload format: | Lưu ý | Chi tiết | |---|---| | 2.0 gọn hơn 1.0 | | | 2.0 cho trả về chuỗi thuần | | | Cấu trúc sự kiện khác nhau — không dùng lẫn | |

Ba lưu ý về DynamoDB: | Lưu ý | Chi tiết | |---|---| | Query rẻ hơn Scan rất nhiều | | | On-demand cho lưu lượng khó đoán | | | Thiết kế khoá phân vùng quyết định hiệu năng | |

Ba lưu ý về Lambda: | Lưu ý | Chi tiết | |---|---| | Dùng lại client giữa các lần gọi | | | Đặt timeout ngắn cho API đọc | | | Graviton rẻ hơn ~20% | |

Ba lưu ý về bảo mật API công khai: | Lưu ý | Chi tiết | |---|---| | Đặt throttling | | | CloudFront + WAF nếu cần lọc | | | Không trả chi tiết lỗi ra ngoài | |

Ba lưu ý về giám sát: | Lưu ý | Chi tiết | |---|---| | Bật access log | | | Theo dõi 5xx và IntegrationLatency | | | Bật X-Ray nếu cần trace | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Gọi thử endpoint bằng curl | | | So chi phí ước tính giữa hai loại API | | | Kiểm CORS từ trình duyệt thật | |

Và một lời khuyên: hãy kiểm tra danh sách tích hợp AWS Service của HTTP API trước khi thiết kế dựa vào nó. Danh sách đó ngắn hơn nhiều so với REST API, và phát hiện ra DynamoDB không có trong đó sau khi đã vẽ xong kiến trúc là chuyện xảy ra thường xuyên hơn người ta nghĩ.