by Julian Wood | on 06 FEB 2024 | in Amazon API Gateway, AWS Lambda, AWS Serverless Application Model, Java, Serverless | Permalink | Share
Bài đăng này được viết bởi Dennis Kieselhorst, Kiến trúc sư giải pháp chính.
Sự kết hợp giữa tính di động, tính hiệu quả, tính cộng đồng và tính đa dạng của các tính năng đã khiến Java trở thành lựa chọn phổ biến cho các doanh nghiệp để xây dựng ứng dụng của họ trong hơn 25 năm qua. Sự ra đời của các hàm phi máy chủ, do AWS Lambda tiên phong, đã thay đổi những gì bạn cần trong ngôn ngữ lập trình và môi trường thời gian chạy. Các chức năng thường tồn tại trong thời gian ngắn, chỉ có một mục đích và không yêu cầu cấu hình cơ sở hạ tầng rộng rãi.
Bài đăng trên blog này cho thấy cách bạn có thể hiện đại hóa một ứng dụng Java cũ để chạy trên Lambda với những thay đổi mã tối thiểu bằng cách sử dụng Bộ chứa Java không có máy chủ AWS được cập nhật (AWS Serverless Java Container).
So sánh mô hình triển khai
Các ứng dụng doanh nghiệp Java cổ điển thường chạy trên các máy chủ ứng dụng như JBoss/WildFly, Oracle WebLogic và IBM WebSphere hoặc các thùng chứa servlet như Apache Tomcat. Máy ảo Java cơ bản thường chạy 24/7 và phục vụ nhiều yêu cầu bằng khả năng đa luồng của nó.
Máy chủ ứng dụng Java chạy dài điển hình
Khi xây dựng các hàm Lambda bằng Java (building Lambda functions with Java), máy chủ HTTP không còn cần thiết nữa và có những điều cần cân nhắc khác khi chạy mã trong môi trường Lambda. Mã chạy trong môi trường thực thi, xử lý một lệnh gọi tại một thời điểm. Các chức năng có thể chạy tối đa 15 phút với bộ nhớ được phân bổ tối đa 10 Gb.
Các chức năng được kích hoạt bởi các sự kiện(events) như yêu cầu (Amazon API Gateway) HTTP có tải trọng tương ứng. Yêu cầu HTTP của Amazon API Gateway gọi hàm với tải trọng JSON sau:
Tải trọng yêu cầu HTTP của Amazon API Gateway
Mã để xử lý các sự kiện này khác với cách bạn triển khai nó trong ứng dụng truyền thống.
AWS Serverless Java Container
AWS Serverless Java Container giúp chạy các ứng dụng Java được viết bằng các khung như Spring, Spring Boot hoặc Jax-Rs/Jersey trong Lambda dễ dàng hơn.
Container cung cấp logic bộ điều hợp để giảm thiểu các thay đổi mã. Các sự kiện đến được dịch sang đặc điểm kỹ thuật servlet (Servlet specification) để các khung hoạt động như trước.
Phiên bản 1 của thư viện này đã được phát hành vào năm 2018 (Version 1 of this library was released in 2018). Hôm nay, AWS đang công bố phát hành phiên bản 2, hỗ trợ thông số kỹ thuật mới nhất của Jakarta EE, cùng với Spring Framework 6.x, Spring Boot 3.x và Jersey 3.x.
Ví dụ: Sửa đổi một ứng dụng khởi động Spring Boot
Ví dụ sau đây minh họa cách di chuyển ứng dụng Spring Boot 3. Bạn có thể tìm thấy ví dụ đầy đủ cho mùa xuân và các khung khác trong kho GitHub (GitHub repository).
1. Thêm phụ thuộc Java không có máy chủ AWS vào tệp bản dựng Maven POM của bạn (hoặc Gradle phù hợp):
| Java<dependency> <groupId>com.amazonaws.serverless</groupId> <artifactId>aws-serverless-java-container-springboot3</artifactId> <version>2.0.0</version></dependency> |
2. Spring Boot, theo mặc định, nhúng Apache Tomcat để đối phó với các yêu cầu HTTP. Các ví dụ sử dụng cổng API Amazon để xử lý các yêu cầu HTTP trong nước để bạn có thể loại trừ sự phụ thuộc.
| Java<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <artifactSet> <excludes> <exclude>org.apache.tomcat.embed:*</exclude> </excludes> </artifactSet> </configuration> </execution> </executions> </plugin> </plugins></build> |
Container Java Serverless AWS chấp nhận các yêu cầu proxy API Gateway và biến chúng thành một đối tượng Java đơn giản. Thư viện cũng chuyển đổi đầu ra thành một đối tượng phản hồi cổng API phù hợp. Khi bạn chạy quy trình xây dựng của mình, hiện tại Maven-plugin của Maven sẽ tạo ra một Uber-JAR kết hợp tất cả các phụ thuộc, mà bạn có thể tải lên Lambda (upload to Lambda).
3. Thời gian chạy Lambda phải biết phương thức xử lý nào sẽ được gọi. Bạn có thể định cấu hình và sử dụng cách triển khai SpringDelegatingLambdaContainerHandler hoặc triển khai lớp Java (implement your own handler Java class) trình xử lý của riêng bạn để ủy quyền cho Bộ chứa Java AWS Serverless. Điều này rất hữu ích nếu bạn muốn thêm chức năng bổ sung.
4. Định cấu hình tên xử lý trong cài đặt thời gian chạy của chức năng của bạn.
5. Định cấu hình một biến môi trường có tên là main_class (environment variable) để cho trình xử lý chung biết nơi tìm lớp chính ứng dụng gốc của bạn, thường được chú thích bằng @SpringBootApplication.
Định cấu hình biến môi trường MAIN_CLASS Bạn cũng có thể định cấu hình các cài đặt này bằng cách sử dụng các công cụ infrastructure as code (IaC), chẳng hạn như AWS CloudFormation,AWS Cloud Development Kit (AWS CDK) hoặc AWS Serverless Application Model (AWS SAM).Trong mẫu AWS SAM, những thay đổi liên quan như sau. Các mẫu đầy đủ là một phần của GitHub repository.
| YAMLSnapStart: ApplyOn: PublishedVersionsAutoPublishAlias: my-function-alias |
Tối ưu hóa cấu hình bộ nhớ
Khi chạy các chức năng Lambda, thời gian khởi động và dấu chân bộ nhớ là những cân nhắc quan trọng. Lượng bộ nhớ bạn định cấu hình cho chức năng Lambda của bạn cũng xác định lượng CPU ảo có sẵn. Thêm nhiều bộ nhớ theo tỷ lệ làm tăng lượng CPU, và do đó làm tăng công suất tính toán tổng thể có sẵn. Nếu một hàm là CPU-, mạng hoặc bộ nhớ, việc thêm nhiều bộ nhớ có thể cải thiện hiệu suất.
Lambda tính phí cho tổng số lượng gigabyte-giây được tiêu thụ bởi một chức năng. Gigabyte-giây là sự kết hợp của tổng bộ nhớ (tính bằng gigabyte) và thời lượng (tính bằng giây). Tăng bộ nhớ phát sinh chi phí bổ sung. Tuy nhiên, trong nhiều trường hợp, việc tăng bộ nhớ có sẵn gây ra sự giảm thời lượng chức năng do CPU bổ sung có sẵn. Do đó, việc tăng chi phí tổng thể có thể không đáng kể đối với hiệu suất bổ sung hoặc thậm chí có thể giảm.
Chọn bộ nhớ được phân bổ cho các hàm Lambda của bạn là một quá trình tối ưu hóa cân bằng tốc độ (thời lượng) và chi phí. Bạn có thể kiểm tra thủ công các chức năng bằng cách chọn phân bổ bộ nhớ khác nhau và đo thời gian hoàn thành. AWS Lambda Power Tuning Tuning là một công cụ để đơn giản hóa và tự động hóa quy trình mà bạn có thể sử dụng để tối ưu hóa cấu hình của mình.
Điều chỉnh năng lượng sử dụng các chức năng Bước AWS để chạy nhiều phiên bản đồng thời của hàm Lambda ở các phân bổ bộ nhớ khác nhau và đo lường hiệu suất. Hàm chạy trong tài khoản AWS của bạn, thực hiện các cuộc gọi HTTP trực tiếp và tương tác SDK, để đo lường hiệu suất trong kịch bản sản xuất.
Cải thiện thời gian bắt đầu lạnh với AWS Lambda Snapstart
Các ứng dụng truyền thống thường có một cây lớn phụ thuộc. Lambda tải mã chức năng và khởi tạo các phụ thuộc trong giai đoạn khởi tạo(initialization phase) vòng đời Lambda. Với nhiều phụ thuộc, thời gian khởi tạo này có thể quá dài cho các yêu cầu của bạn. AWS Lambda SnapStart cho các chức năng dựa trên Java có thể cung cấp hiệu suất khởi động nhanh hơn tới 10 lần.
Thay vì chạy giai đoạn khởi tạo chức năng trên mỗi lần khởi động lạnh, Lambda Snapstart chạy quá trình khởi tạo chức năng tại thời điểm triển khai. Lambda có một ảnh chụp nhanh về môi trường thực hiện khởi tạo. Ảnh chụp này được mã hóa và tồn tại trong bộ nhớ cache theo cấp bậc để truy cập độ trễ thấp. Khi chức năng được gọi và chia tỷ lệ, Lambda sẽ tiếp tục môi trường thực thi từ ảnh chụp nhanh thay vì chạy quá trình khởi tạo đầy đủ. Điều này dẫn đến độ trễ khởi động thấp hơn.
Để enable Lambda SnapStart bật Lambda SnapStart, trước tiên bạn phải bật cài đặt cấu hình và publish a function version.
Enabling SnapStart
Đảm bảo bạn trỏ điểm cuối cổng API của mình vào phiên bản được xuất bản hoặc bí danh (alias) để đảm bảo bạn đang sử dụng chức năng hỗ trợ SnapStart.
Các cài đặt tương ứng trong mẫu AWS SAM chứa các mục sau:
| YAML SnapStart: ApplyOn: PublishedVersions AutoPublishAlias: my-function-alias |
Đọc các cân nhắc tương thích Lambda SnapStart (Lambda SnapStart compatibility considerations) trong tài liệu vì ứng dụng của bạn có thể chứa mã cụ thể đòi hỏi sự chú ý.
Phần kết luận
Khi xây dựng các ứng dụng không có máy chủ với Lambda, bạn có thể cung cấp các tính năng nhanh hơn, nhưng ngôn ngữ và thời gian chạy của bạn phải hoạt động trong mô hình kiến trúc không có máy chủ. Container Java không có máy chủ AWS giúp kết nối giữa các ứng dụng doanh nghiệp Java truyền thống và các chức năng không có máy chủ bản địa hiện đại.
Bạn có thể tối ưu hóa cấu hình bộ nhớ của chức năng Java Lambda của mình bằng công cụ điều chỉnh năng lượng AWS Lambda và cho phép SnapStart tối ưu hóa thời gian khởi động lạnh ban đầu.
Java tự nhịp độ trong Hội thảo AWS Lambda (Java on AWS Lambda) cách xây dựng các ứng dụng Java bản địa trên đám mây và di chuyển ứng dụng Java hiện có sang Lambda.
Khám phá kho lưu trữ GitHub của AWS Serverless Java Containerr nơi bạn có thể báo cáo issues and feature requests.
Để có thêm tài nguyên học tập,hãy truy cập Serverless Land.