Dự án trên AWS

Xây dựng ứng dụng web hiện đại

Triển khai một ứng dụng web, kết nối với cơ sở dữ liệu và phân tích hành vi của người dùng

Mô-đun 5: Thu thập hành vi người dùng

Trong mô-đun này, bạn sẽ thu thập hành vi người dùng bằng AWS Lambda và các dịch vụ phi máy chủ khác.

Tổng quan

Giờ trang web Mythical Mysfits đã sẵn sàng hoạt động. Hãy cùng tạo ra một cách để hiểu rõ hơn tương tác của khách hàng với trang web này cũng như thú cưng trên trang web. Chúng ta rất dễ dàng phân tích các hành động của người dùng trên trang web mà gây ra sự thay đổi trong backend, chẳng hạn như nhận nuôi hoặc thích thú cưng.

Tuy nhiên, nếu biết được hành động mà người dùng thực hiện trên trang web trước cả thời điểm thích hoặc nhận nuôi thú cưng, thì bạn có thể thiết kế trải nghiệm người dùng tốt hơn trong tương lai, nhờ đó thú cưng sẽ được nhận nuôi nhanh hơn nữa. Để có thể thu thập những thông tin này, chúng ta sẽ cung cấp cho frontend trang web khả năng gửi một yêu cầu nhỏ (mỗi khi người dùng nhấp vào hồ sơ của thú cưng) sang API vi dịch vụ mới mà chúng ta sẽ tạo. Những bản ghi này sẽ được xử lý trong thời gian thực bởi một hàm mã phi máy chủ, sau đó được tổng hợp và lưu trữ để bạn có thể phân tích trong tương lai khi cần.

Nguyên tắc để thiết kế ứng dụng web hiện đại là ưu tiên các dịch vụ chuyên dụng, rạch ròi và theo mô-đun. Do đó, thay vì bổ sung các phương pháp và chức năng mới vào dịch vụ Mysfits hiện có, chúng ta sẽ tạo một dịch vụ mới và rạch ròi, chỉ nhằm mục đích nhận các sự kiện nhấp của người dùng từ trang web Mysfits. Ngăn xếp đầy đủ này đã được trình bày trong mẫu CloudFormation cho sẵn.

Sơ đồ kiến trúc

thu thập hành vi người dùng

Tại sao lại chọn AWS Lambda cho phương án triển khai này?

Lambda phù hợp với các ứng dụng thiên về dữ liệu và cần phản hồi theo thời gian thực đối với những thay đổi về dữ liệu, trạng thái hệ thống hay hành động của người dùng. Những ứng dụng này thường kết nối vào các kho dữ liệu để truy cập và phân tích dữ liệu trong quá trình xử lý lô, phân tích luồng dữ liệu và suy luận máy học. Lambda được tích hợp với những kho dữ liệu như Kinesis Data Streams and Data Firehose, S3, CloudWatch Events, CloudWatch Logs và DynamoDB, với tổng cộng 17 nguồn dữ liệu tính đến nay, nên sẽ rất phù hợp với các ứng dụng này.   

Tài nguyên phi máy chủ dùng trong mô-đun này

Luồng phân phối AWS Kinesis Firehose: Kinesis Firehose là dịch vụ có quản lý với độ khả dụng cao để truyền liên tục dữ liệu theo thời gian thực. Dịch vụ này sẽ tiếp nhận các bản ghi dữ liệu và tự động thu nạp chúng vào một số vị trí lưu trữ thích hợp trong AWS, chẳng hạn như vùng lưu trữ Amazon S3 hoặc cụm kho dữ liệu Amazon Redshift. Kinesis Firehose cũng cho phép tự động phân phối tất cả các bản ghi mà luồng dữ liệu tiếp nhận sang một hàm phi máy chủ tạo bằng AWS Lambda. Điều này nghĩa là mã mà bạn vừa viết có thể thực hiện mọi tác vụ xử lý bổ sung hoặc biến đổi các bản ghi trước khi chúng được tổng hợp và lưu trữ tại vị trí đích theo cấu hình.

Vùng lưu trữ Amazon S3: Một bộ chứa mới sẽ được tạo trong S3, là nơi mọi bản ghi sự kiện nhấp đã xử lý sẽ được tổng hợp thành các tệp và lưu trữ dưới dạng đối tượng.

Hàm AWS Lambda: AWS Lambda cho phép nhà phát triển viết các hàm mã chỉ chứa những nội dung cần cho logic của họ. Sau đó, họ có thể triển khai, gọi, đưa vào sử dụng và thay đổi quy mô của code mà không cần phải quản lý cơ sở hạ tầng hay những thứ tương tự. Ở đây, hàm mã phi máy chủ được xác định bằng AWS SAM. Hàm này sẽ được viết trong Python, triển khai cho AWS Lambda rồi xử lý và bổ sung cho các bản ghi nhấp được tiếp nhận bằng luồng phân phối. Mã chúng ta viết rất đơn giản và có thể bổ sung thêm nội dung ngay trên frontend trang web mà không cần thêm bất kỳ khâu xử lý nào sau đó. Hàm này sẽ truy xuất các thuộc tính khác về lượt nhấp trên Mysfit để làm cho bản ghi lượt nhấp có ý nghĩa hơn (so với dữ liệu đã truy xuất bằng frontend trang web). Tuy nhiên, trong khuôn khổ buổi học này, mã chúng ta viết chỉ nhằm mục đích thể hiện những khả năng về mặt cấu trúc khi dùng hàm mã phi máy chủ để thực hiện thêm bất kỳ tác vụ xử lý hoặc biến đổi cần thiết nào trong thời gian thực, trước khi các bản ghi được lưu trữ. Khi đã tạo xong hàm Lambda và đặt cấu hình cho luồng phân phối Kinesis Firehose làm nguồn sự kiện của hàm, thì luồng phân phối sẽ tự động phân phối các bản ghi dưới dạng sự kiện đến hàm mã vừa tạo, sau đó tiếp nhận các phản hồi mà mã của chúng ta trả về, rồi phân phối các bản ghi sau cập nhật đến vùng lưu trữ Amazon S3 đã được cấu hình.

Một REST API của Amazon API Gateway: Tương tự các dịch vụ AWS khác, AWS Kinesis Firehose cũng cung cấp API dịch vụ. Trong trường hợp này, chúng ta sẽ sử dụng phép toán PutRecord để đưa các bản ghi sự kiện nhấp của người dùng vào luồng phân phối. Tuy nhiên, chúng ta không muốn frontend trang web phải tích hợp trực tiếp với API PutRecord của Kinesis Firehose. Làm như vậy sẽ khiến chúng ta phải quản lý thông tin đăng nhập AWS trong mã frontend để xác thực những yêu cầu API đó với API PutRecord. Đồng thời, người dùng cũng sẽ thấy trực tiếp API AWS đang được sử dụng (kẻ xấu có thể lợi dụng điều này để thêm các bản ghi độc hại, không đúng quy chuẩn vào luồng phân phối, khiến chúng ta không đạt được mục tiêu là hiểu rõ hành thực tế của người dùng). Vậy nên, thay vào đó, chúng ta sẽ sử dụng Amazon API Gateway để tạo một proxy dịch vụ AWS cho API PutRecord của Kinesis Firehose. Điều này cho phép chúng ta tự tạo điểm cuối RESTful của riêng mình và không cần phải quản lý thông tin đăng nhập AWS trên frontend cho các yêu cầu. Đồng thời, chúng ta cũng sẽ dùng mẫu ánh xạ yêu cầu trong API Gateway. Với mẫu này, chúng ta có thể tự mình quyết định cấu trúc tải trọng của yêu cầu, qua đó sẽ hạn chế được các yêu cầu đến những cấu trúc mong muốn, rồi biến đổi những yêu cầu theo đúng quy chuẩn đó thành cấu trúc phù hợp cho API PutRecord của Kinesis Firehose.

Vai trò IAM: Kinesis Firehose đòi hỏi một vai trò dịch vụ cho phép nó phân phối các bản ghi đã tiếp nhận dưới dạng sự kiện sang hàm Lambda vừa tạo, cũng như phân phối các bản ghi đã xử lý sang vùng lưu trữ đích trên S3. API của Amazon API Gateway cũng đòi hỏi một vai trò mới cho phép API này gọi API PutRecord trong Kinesis Firehose cho từng yêu cầu API đã tiếp nhận.

Hướng dẫn thực hiện

  • A: Tạo kho lưu trữ CodeCommit mới

    Ngăn xếp mới bạn sắp triển khai bằng CloudFormation sẽ không chỉ chứa các tài nguyên của môi trường cơ sở hạ tầng, mà còn chứa cả chính mã ứng dụng mà AWS Lambda sẽ thực thi để xử lý các sự kiện truyền. Để tạo cả cơ sở hạ tầng lẫn mã trong cùng một lần triển khai, chúng ta sẽ sử dụng một công cụ AWS khác được cài đặt sẵn trong IDE AWS Cloud9 là AWS SAM CLI. Mã của hàm AWS Lambda sẽ được phân phối đến dịch vụ bằng cách tải mã hàm trong gói .zip lên vùng lưu trữ Amazon S3.

    SAM CLI sẽ tự động xử lý quá trình này cho chúng ta. Bằng công cụ này, chúng ta có thể tạo một mẫu CloudFormation tham chiếu cục bộ trong hệ thống tệp mà toàn bộ mã của hàm Lambda được lưu trữ. Sau đó, SAM CLI sẽ gói mẫu này vào một tệp .zip, tải lên vùng lưu trữ Amazon S3 đã cấu hình, rồi tạo một mẫu CloudFormation mới cho biết vị trí trong S3 mà gói .zip vừa tạo được tải lên để triển khai cho AWS Lambda. Sau đó, chúng ta có thể triển khai mẫu CloudFormation tạo bởi SAM CLI đó cho AWS rồi theo dõi môi trường được tạo cùng với hàm Lambda có sử dụng gói mã do SAM CLI tải lên.

    Đầu tiên, hãy tạo một kho lưu trữ CodeCommit mới chứa mã dịch vụ truyền:

    aws codecommit create-repository --repository-name MythicalMysfitsStreamingService-Repository

    Để phản hồi lệnh này, hãy sao chép giá trị cho "cloneUrlHttp". Giá trị này thường có dạng: https://git-codecommit.REPLACE_ME_REGION.amazonaws.com/v1/repos/MythicalMysfitsStreamingService-Repository

    Tiếp đến, hãy nhân bản kho lưu trữ mới và trông đó vào IDE của chúng ta:

    cd ~/environment/
    git clone {insert the copied cloneValueUrl from above}
    B: Sao chép mã nền cho dịch vụ streaming

    Bây giờ, hãy di chuyển thư mục chúng ta đang làm việc vào kho lưu trữ mới này:

    cd ~/environment/MythicalMysfitsStreamingService-Repository/

    Sau đó, sao chép các thành phần của ứng dụng ở mô-đun 5 vào thư mục kho lưu trữ mới này:

    cp -r ~/environment/aws-modern-application-workshop/module-5/app/streaming/* .

    Sau đó, hãy sao chép cả mẫu CloudFormation cho mô-đun mới này.

    cp ~/environment/aws-modern-application-workshop/module-5/cfn/* .
  • A: Dùng Pip để cài đặt các tác nhân phụ thuộc hàm Lambda

    Giờ đây, chúng ta có thư mục kho lưu trữ được cài đặt với tất cả các thành phần lạ cho trước:

    Mẫu CFN để tạo ngăn xếp đầy đủ.

    Tập lệnh Python chứa mã của hàm Lambda: streamProcessor.py

    Phương pháp mà khách hàng AWS hay dùng đó là lưu trữ mẫu CloudFormation cùng với mã ứng dụng trong kho lưu trữ. Theo cách này, bạn có thể tiện theo dõi mọi thay đổi đối với ứng dụng và môi trường của ứng dụng đó tại cùng một nơi.

    Tuy nhiên, nếu để ý kỹ mã trong tệp streamProcessor.py, bạn sẽ thấy rằng nó đang dùng gói Python yêu cầu để thực hiện yêu cầu API với dịch vụ Mythical Mysfits bạn tạo trước đó. Trong môi trường thời gian chạy AWS Lambda sẽ không có sẵn các thư viện từ bên ngoài, vì mỗi khách hàng AWS có thể sử dụng các phiên bản khác nhau của nhiều thư viện, v.v.

    Bạn sẽ phải gói tất cả các tác nhân phụ thuộc của thư viện lại với nhau bằng hàm mã Lambda của mình trước khi hàm này được tải lên dịch vụ Lambda. Chúng ta sẽ dùng pip của trình quản lý gói Python để hoàn tất việc này. Trong cửa sổ đầu cuối Cloud9, hãy chạy lệnh sau để cài đặt cục bộ gói yêu cầu và các tác nhân phụ thuộc cùng với mã hàm của bạn:

    pip install requests -t .

    Khi lệnh này chạy xong, bạn sẽ thấy một số thư mục khác chứa gói python được lưu trữ trong thư mục kho lưu trữ của mình.

    B: Cập nhật mã hàm Lambda

    Tiếp theo, chúng ta sẽ sửa một dòng code trước khi mã hàm Lambda hoàn toàn sẵn sàng để triển khai. Có một dòng trong tệp streamProcessor.py cần được thay bằng ApiEndpoint cho API của dịch vụ Mysfits - cùng một ApiEndpoint dịch vụ mà bạn đã tạo ở mô-đun 4 và sử dụng trên frontend của trang web.

    replace-api-endpoint

    Dịch vụ đó được dùng để tích hợp với MysfitsTable trong DynamoDB. Do đó, mặc dù chúng ta có thể viết hàm Lambda để tích hợp trực tiếp với bảng DynamoDB, nhưng làm vậy sẽ xâm phạm mục đích của vi dịch vụ đầu tiên và khiến chúng ta phải xử lý nhiều mã nền hoặc mã nền bị phân tán trong cùng một bảng. Thay vào đó, chúng ta sẽ tích hợp với bảng đó thông qua dịch vụ hiện có, giúp ứng dụng có kiến trúc rạch ròi và theo mô-đun hơn.

    C: Đẩy code vào CodeCommit

    Hãy sửa đổi dòng code cho kho lưu trữ mới để những thay đổi này được lưu trong CodeCommit:

    git add .
    git commit -m "New stream processing service."
    git push
  • A: Tạo một vùng lưu trữ S3 cho gói mã hàm Lambda

    Khi đã thay đổi dòng đó trong tệp Python và mã chạy, chúng ta có thể dùng AWS SAM CLI để đóng gói toàn bộ mã hàm, tải lên S3 rồi triển khai mẫu CloudFormation để tạo ngăn xếp truyền.

    Đầu tiên, hãy dùng AWS CLI để tạo vùng lưu trữ S3 mới làm nơi tải lên toàn bộ gói mã hàm Lambda. Tên vùng lưu trữ S3 phải là duy nhất trên toàn hệ thống trong số tất cả khách hàng AWS. Vì vậy, hãy đổi đuôi của tên vùng lưu trữ này bằng một chuỗi chưa ai đặt:

    B: Dùng SAM CLI để đóng gói mã cho Lambda

    Khi đã tạo xong vùng lưu trữ, chúng ta có thể dùng SAM CLI để đóng gói và tải mã lên rồi biến đổi mẫu CloudFormation, hãy nhớ thay tham số cuối bằng tên vùng lưu trữ bạn vừa tạo ở trên (lệnh này cũng giả định rằng cửa sổ đầu cuối của bạn vẫn nằm trong thư mục đang hoạt động của kho lưu trữ):

    sam package --template-file ./real-time-streaming.yml --output-template-file ./transformed-streaming.yml --s3-bucket replace-with-your-bucket-name

    Nếu thành công, bạn sẽ thấy tệp transformed-streaming.yml trong thư mục ./MythicalMysfitsStreamingService-Repository/. Nếu nhìn vào nội dung của thư mục này, bạn sẽ thấy rằng tham số CodeUri của hàm Lambda phi máy chủ đã được thay bằng vị trí đối tượng nơi mà SAM CLI tải gói mã của bạn lên.

    C: Triển khai ngăn xếp bằng AWS CloudFormation

    Lệnh SAM CLI cũng trả về lệnh CloudFormation cần phải chạy để tạo ngăn xếp đầy đủ mới. Tuy nhiên, vì ngăn xếp của chúng ta tạo ra các tài nguyên IAM, nên bạn sẽ phải bổ sung thêm một tham số vào lệnh này. Chạy lệnh sau để triển khai ngăn xếp truyền:

    aws cloudformation deploy --template-file /home/ec2-user/environment/MythicalMysfitsStreamingService-Repository/cfn/transformed-streaming.yml --stack-name MythicalMysfitsStreamingStack --capabilities CAPABILITY_IAM

    Khi tạo xong ngăn xếp này, vi dịch vụ xử lý theo thời gian thực sẽ được tạo hoàn chỉnh.

    Trong trường hợp chỉ có mã của hàm Lambda thay đổi và phần còn lại của ngăn xếp CloudFormation vẫn giữ nguyên, thì bạn có thể chạy lại các lệnh AWS SAM CLI và CloudFormation giống như ở trên. Điều này không làm thay đổi môi trường cơ sở hạ tầng, nhưng mã hàm Lambda của bạn sẽ được triển khai.

  • A: Cập nhật nội dung trang web

    Ngăn xếp truyền đã sẵn sàng hoạt động, chúng ta giờ sẽ phải phát hành phiên bản mới của frontend Mythical Mysfits có chứa JavaScript để gửi các sự kiện sang dịch vụ của chúng ta mỗi khi người dùng nhấp vào hồ sơ thú cưng.

    Tệp index.html mới sẽ có trong: ~/environment/aws-modern-application-workshop/module-5/web/index.html

    Tệp này chứa các phần giữ chỗ giống như ở mô-đun 4 cần được cập nhật, đồng thời có thêm một phần giữ chỗ cho điểm cuối dịch vụ xử lý luồng mà bạn vừa tạo. Để biết các giá trị trước đây của biến này, bạn có thể tham khảo tệp index.html mà bạn đã cập nhật trong khuôn khổ mô-đun 4.

    Thực hiện lệnh sau đối với stack streaming mới để truy xuất điểm cuối API Gateway mới cho dịch vụ xử lý luồng của bạn:

    aws cloudformation describe-stacks --stack-name MythicalMysfitsStreamingStack
    B: Đẩy phiên bản trang web mới sang S3

    Thay giá trị chính thức trong index.html cho streamingApiEndpoint. Lúc này, bạn đã sẵn sàng để phát hành trang chủ Mythical Mysfits mới cập nhật:

    aws s3 cp ~/environment/aws-modern-application-workshop/module-5/web/index.html s3://YOUR-S3-BUCKET/

    Làm mới trang web Mythical Mysfits trong trình duyệt một lần nữa. Giờ đây, trang web của bạn sẽ ghi lại và xuất bản mỗi khi người dùng nhấp vào hồ sơ thú cưng!

    Để xem các bản ghi đã được xử lý, hãy chuyển tới vùng lưu trữ đích S3 mà bạn đã tạo như một phần của MythicalMysfitsStreamingStack.

    Kiến trúc ứng dụng hiện đại của bạn đã hoàn thiện rồi đó! Bạn nên khám phá Bảng điều khiển AWS và tất cả các dịch vụ mà bạn đã tạo để vận hành Mythical Mysfits!

  • Hãy nhớ xóa mọi tài nguyên đã tạo trong hội thảo này để đảm bảo rằng chi phí cho tài nguyên không vượt quá dự tính của bạn. Bạn nên sử dụng Bảng điều khiển AWS để khám phá các tài nguyên đã tạo và xóa đi khi thích hợp.

    Đối với 2 trường hợp mà bạn đã cấp tài nguyên bằng AWS CloudFormation, bạn có thể xóa những tài nguyên đó bằng cách chạy lệnh CLI cho từng ngăn xếp:

    aws cloudformation delete-stack --stack-name STACK-NAME-HERE

    Để xóa tất cả tài nguyên đã tạo, bạn có thể truy cập vào các Bảng điều khiển AWS sau đây có chứa các tài nguyên mà bạn đã tạo trong suốt hội thảo Mythical Mysfits:

Kết luận

Trải nghiệm này giúp bạn hình dung những điều mà lập trình viên cần làm khi thiết kế và xây dựng các kiến trúc ứng dụng hiện đại trên AWS. Trên AWS, nhà phát triển có thể lập trình để cấp tài nguyên bằng AWS CLI, tái sử dụng định nghĩa cơ sở hạ tầng thông qua AWS CloudFormation, tự động xây dựng và triển khai những thay đổi đối với mã bằng các dịch vụ bộ công cụ soạn thảo mã của AWS dành cho nhà phát triển, cũng như tận dụng nhiều chức năng của dịch vụ điện toán và ứng dụng mà không cần phải cung cấp hay quản lý bất kỳ máy chủ nào!

Tiếp theo, để tìm hiểu thêm về những tuyệt tác đằng sau trang web Mythical Mysfits bạn đã tạo, hãy đào sâu nghiên cứu các mẫu CloudFormation và những tài nguyên có trong đó.

Chúng tôi hy vọng bạn yêu thích Hội thảo ứng dụng web hiện đại của AWS! Hướng dẫn này cũng được lưu trữ trên GitHub nên bạn có thể gửi vấn đề nếu có đề xuất nào. Bạn cũng có thể khởi tạo yêu cầu kéo trên GitHub nếu muốn đóng góp để cải thiện mã.

Nếu bạn muốn tìm hiểu thêm về việc phát triển trên AWS, hãy truy cập Trung tâm nhà phát triển AWS.

Xin chúc mừng!

Bạn đã xây dựng được một ứng dụng web hiển đại trên AWS.
Hãy chia sẻ với bạn bè hoặc gửi ý kiến phản hồi cho chúng tôi.

Twilight Glitter cảm thấy ấn tượng với sản phẩm của bạn