Di chuyển từ ứng dụng Java của Google App Engine sang Cloud Run bằng Docker

1. Tổng quan

Chuỗi lớp học lập trình này (hướng dẫn thực hành theo tiến độ riêng) nhằm giúp các nhà phát triển Java sử dụng Google App Engine (Chuẩn) hiện đại hoá ứng dụng của họ bằng cách hướng dẫn họ thực hiện một loạt quy trình di chuyển. Bằng cách làm theo các bước này, bạn có thể cập nhật ứng dụng để dễ di chuyển hơn và quyết định lưu trữ chúng cho Cloud Run, dịch vụ tương tự lưu trữ vùng chứa của Google Cloud cho App Engine, cũng như các dịch vụ lưu trữ vùng chứa khác.

Hướng dẫn này chỉ cho bạn cách chứa một ứng dụng App Engine để triển khai dịch vụ được quản lý hoàn toàn cho Cloud Run bằng Dockerfile. Các tệp Docker là phương thức triển khai phù hợp nhất cho quá trình di chuyển này, nhưng cũng cung cấp nhiều lựa chọn nhất để tuỳ chỉnh quy trình xây dựng của bạn.

Ngoài hướng dẫn cho bạn các bước cần thiết để chuyển từ App Engine sang Cloud Run, bạn cũng sẽ tìm hiểu cách nâng cấp một ứng dụng Java 8 App Engine lên Java 17.

Nếu ứng dụng mà bạn muốn di chuyển sử dụng nhiều dịch vụ đi kèm cũ của App Engine hoặc các tính năng cụ thể khác của App Engine, thì hướng dẫn Truy cập vào các dịch vụ đi kèm của App Engine cho Java 11/17 có thể là điểm khởi đầu phù hợp hơn so với lớp học lập trình này.

Bạn sẽ tìm hiểu cách

  • Sử dụng Cloud Shell
  • Bật Cloud Run, Artifact Registry và API Cloud Build
  • Mở rộng vùng chứa ứng dụng bằng Docker, Docker và Cloud Build
  • Triển khai hình ảnh vùng chứa cho Cloud Run

Bạn cần có

Khảo sát

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ có thể đọc Đọc và hoàn thành bài tập

Bạn đánh giá trải nghiệm sử dụng Java của mình ở mức nào?

Người mới tập Trung cấp Thành thạo

Bạn đánh giá thế nào về trải nghiệm sử dụng các dịch vụ của Google Cloud?

Người mới tập Trung cấp Thành thạo

2. Thông tin khái quát

Các hệ thống PaaS như App Engine và Cloud Functions mang đến nhiều tiện ích cho nhóm và ứng dụng của bạn, chẳng hạn như cho phép SysAdmins và Devops tập trung vào việc xây dựng các giải pháp. Với các nền tảng không nghiêm ngặt, ứng dụng của bạn có thể tự động mở rộng quy mô khi cần, giảm quy mô về 0 nhờ tính năng thanh toán trả tiền cho mỗi lần sử dụng để giúp kiểm soát chi phí và sử dụng nhiều ngôn ngữ phát triển phổ biến.

Tuy nhiên, tính linh hoạt của vùng chứa cũng rất hấp dẫn. Với khả năng chọn bất kỳ ngôn ngữ, thư viện hay tệp nhị phân nào, vùng chứa mang đến cho bạn lợi ích tốt nhất của cả hai thế giới: sự tiện lợi của mô hình không máy chủ cùng tính linh hoạt của vùng chứa. Đây là toàn bộ nội dung của Google Cloud Run.

Việc tìm hiểu cách sử dụng Cloud Run không thuộc phạm vi của lớp học lập trình này; có trong tài liệu về Cloud Run. Mục tiêu ở đây là giúp bạn làm quen với cách chứa ứng dụng App Engine cho Cloud Run (hoặc các dịch vụ lưu trữ trên vùng chứa khác) trong vùng chứa. Có một vài điều bạn nên biết trước khi tiếp tục, chủ yếu là trải nghiệm người dùng của bạn sẽ hơi khác một chút.

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách xây dựng và triển khai vùng chứa. Bạn sẽ tìm hiểu cách dùng Dockerfile để chứa ứng dụng của mình, di chuyển khỏi cấu hình App Engine và xác định các bước xây dựng cho Cloud Build (không bắt buộc). Việc này sẽ liên quan đến việc loại bỏ một số tính năng cụ thể của App Engine. Nếu không muốn làm theo cách này, bạn vẫn có thể nâng cấp lên môi trường thời gian chạy Java 11/17 trong khi vẫn giữ lại ứng dụng trên App Engine.

3. Thiết lập/Chuẩn bị

1. Thiết lập dự án

Trong hướng dẫn này, bạn sẽ dùng một ứng dụng mẫu trong kho lưu trữ appengine-java-migration-samples trên một dự án hoàn toàn mới. Đảm bảo dự án có tài khoản thanh toán đang hoạt động.

Nếu có ý định chuyển một ứng dụng hiện có trên App Engine sang Cloud Run, bạn có thể dùng ứng dụng đó để thực hiện việc này.

Chạy lệnh sau để bật các API cần thiết cho dự án của bạn:

gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com

2. Tải ứng dụng mẫu cơ sở

Sao chép ứng dụng mẫu trên máy của bạn hoặc trên Cloud Shell, sau đó chuyển đến thư mục baseline.

Mẫu này là một ứng dụng Kho dữ liệu dựa trên Servlet Java 8 nhằm triển khai trên App Engine. Làm theo hướng dẫn trong tài liệu README về cách chuẩn bị ứng dụng này để triển khai App Engine.

3. (Không bắt buộc) Triển khai ứng dụng cơ sở

Những điều sau đây chỉ cần thiết nếu bạn muốn xác nhận rằng ứng dụng hoạt động trên App Engine trước khi chúng tôi di chuyển sang Cloud Run.

Hãy tham khảo các bước trong README.md:

  1. Cài đặt/Làm quen lại với CLI gcloud
  2. Khởi chạy gcloud CLI cho dự án của bạn bằng gcloud init
  3. Tạo dự án App Engine bằng gcloud app create
  4. Triển khai ứng dụng mẫu cho App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. Xác nhận rằng ứng dụng chạy trên App Engine mà không gặp vấn đề nào

4. Tạo kho lưu trữ Artifact Registry

Sau khi vùng chứa ứng dụng, bạn sẽ cần đến nơi nào đó để đẩy và lưu trữ hình ảnh của mình. Bạn nên dùng Artifact Registry để thực hiện việc này trên Google Cloud.

Tạo kho lưu trữ có tên migration bằng gcloud như sau:

gcloud artifacts repositories create migration --repository-format=docker \
--description="Docker repository for the migrated app" \
--location="northamerica-northeast1"

Lưu ý rằng kho lưu trữ này sử dụng kiểu định dạng docker, nhưng có sẵn một số loại kho lưu trữ.

Tại thời điểm này, bạn đã có ứng dụng cơ sở App Engine và dự án Google Cloud của bạn đã sẵn sàng di chuyển ứng dụng đó sang Cloud Run.

4. Sửa đổi tệp ứng dụng

Trong trường hợp ứng dụng của bạn sử dụng nhiều dịch vụ, cấu hình đi kèm cũ của App Engine hoặc các tính năng khác chỉ dành cho App Engine, bạn nên tiếp tục truy cập vào các dịch vụ đó trong khi nâng cấp lên môi trường thời gian chạy mới. Lớp học lập trình này minh hoạ đường dẫn di chuyển cho các ứng dụng đã sử dụng các dịch vụ độc lập hoặc có thể được tái cấu trúc để làm như vậy.

1. Nâng cấp lên Java 17

Nếu ứng dụng của bạn chạy trên Java 8, hãy cân nhắc nâng cấp lên một phiên bản LTS mới hơn như 11 hoặc 17 để bắt kịp các bản cập nhật bảo mật và có quyền truy cập vào các tính năng ngôn ngữ mới.

Hãy bắt đầu bằng cách cập nhật các thuộc tính trong pom.xml để thêm những thuộc tính sau:

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

Điều này sẽ đặt phiên bản dự án thành 17, thông báo cho trình bổ trợ trình biên dịch rằng bạn muốn truy cập vào các tính năng ngôn ngữ java 17 và muốn các lớp được biên dịch tương thích với JVM Java 17.

2. Bao gồm máy chủ web

Có một số điểm khác biệt giữa App Engine và Cloud Run mà bạn cần cân nhắc khi chuyển đổi giữa hai công cụ này. Có một điểm khác biệt là trong khi thời gian chạy Java 8 của App Engine cung cấp và quản lý một máy chủ Jetty cho các ứng dụng được lưu trữ, nhưng Cloud Run thì không. Chúng ta sẽ sử dụng tính năng Spring Boot để cung cấp máy chủ web và vùng chứa servlet.

Thêm các phần phụ thuộc sau:

<dependencies>
<!-- ... -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <version>2.6.6</version>
       <exclusions>
           <!-- Exclude the Tomcat dependency -->
           <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-tomcat</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- Use Jetty instead -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jetty</artifactId>
       <version>2.6.6</version>
   </dependency>
<!-- ... -->
</dependencies>

Theo mặc định, Spring Boot nhúng máy chủ Tomcat, nhưng mẫu này sẽ loại trừ cấu phần phần mềm đó và gắn với Jetty để giảm thiểu sự khác biệt về hành vi mặc định sau khi di chuyển.

3. Thiết lập Spring Boot

Mặc dù Spring Boot sẽ có thể sử dụng lại các servlet mà không cần sửa đổi, nhưng bạn sẽ phải thiết lập một số cấu hình để đảm bảo có thể tìm thấy các servlet này.

Tạo lớp MigratedServletApplication.java sau trong gói com.example.appengine:

package com.example.appengine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
@EnableAutoConfiguration
public class MigratedServletApplication {
    public static void main(String[] args) {
        SpringApplication.run(MigratedServletApplication.class, args);
    }
}

Lưu ý là việc này bao gồm cả chú giải @ServletComponentScan. Chú giải này sẽ tìm (trong gói hiện tại theo mặc định) cho mọi @WebServlets và làm cho chúng xuất hiện như dự kiến.

4. Đóng gói ứng dụng dưới dạng tệp JAR

Mặc dù bạn có thể chứa ứng dụng bắt đầu từ một cuộc chiến, nhưng sẽ dễ dàng hơn nếu bạn đóng gói ứng dụng dưới dạng tệp JAR có thể thực thi. Tính năng này sẽ không yêu cầu nhiều cấu hình, đặc biệt là đối với các dự án sử dụng Maven làm công cụ xây dựng – vì việc đóng gói jar là hành vi mặc định.

Xoá thẻ packaging trong tệp pom.xml:

<packaging>war</packaging>

Tiếp theo, hãy thêm spring-boot-maven-plugin:

<plugins>
<!-- ... -->
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.6</version>
  </plugin>
<!-- ... -->
</plugins>

5. Di chuyển khỏi cấu hình, dịch vụ và phần phụ thuộc của App Engine

Như đã đề cập trong phần đầu của lớp học lập trình này, Cloud Run và App Engine được thiết kế để cung cấp những trải nghiệm người dùng khác nhau. Một số tính năng mà App Engine cung cấp ngay từ đầu (chẳng hạn như các dịch vụ CronTask Hàng đợi) cần được tạo lại theo cách thủ công và sẽ được đề cập chi tiết hơn trong các mô-đun sau.

Ứng dụng mẫu không sử dụng các dịch vụ theo gói cũ, nhưng người dùng có ứng dụng đó có thể tham khảo hướng dẫn sau:

Vì bạn sẽ triển khai cho Cloud Run từ giờ trở đi nên bạn có thể xoá appengine-maven-plugin:

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>appengine-maven-plugin</artifactId>
 <version>2.4.1</version>
 <configuration>
   <!-- can be set w/ -DprojectId=myProjectId on command line -->
   <projectId>${app.projectId}</projectId>
   <!-- set the GAE version or use "GCLOUD_CONFIG" for an autogenerated GAE version -->
   <version>GCLOUD_CONFIG</version>
 </configuration>
</plugin>

5. Trong vùng chứa ứng dụng

Đến đây, bạn đã sẵn sàng thông báo cho Cloud Build về cách xây dựng vùng chứa của ứng dụng trên thực tế. Với phương pháp chứa này, bạn không cần phải có một tệp cấu hình bản dựng riêng (cloudbuild.yaml). Chúng ta chỉ cần xác định một Dockerfile tối thiểu làm điểm bắt đầu:

TỪ elip-temurin

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

SAO CHÉP ${JAR_FILE} app.jar

EntryPOINT ["java", "-jar","/app.jar"]

Dockerfile này nhóm phiên bản uber-jar của dịch vụ khởi động mùa xuân trong một lớp duy nhất. Đây là phương pháp đơn giản nhất để hoá vùng chứa Dockerfile, nhưng cũng có một số hạn chế, đặc biệt là khi so sánh các lần lặp lại trong đó các phần phụ thuộc tương đối ổn định. Những mối lo ngại như thế này là lý do khiến phương pháp chứa vùng chứa này được xem là tiên tiến hơn. Tuy nhiên, về ưu điểm, việc viết tệp dockerfile của riêng bạn sẽ giúp bạn kiểm soát hoàn toàn hình ảnh cơ sở và khai thác các lợi ích về hiệu suất của việc viết hình ảnh được phân lớp cẩn thận.

2**. Chạy quy trình xây dựng**

Giờ đây, khi đã thông báo cho Cloud Build về các bước xây dựng mong muốn, bạn có thể triển khai chỉ bằng một cú nhấp chuột.

Chạy lệnh sau:

gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME

Thay thế các giá trị phần giữ chỗ trong lệnh trên bằng:

  • VỊ TRÍ: vị trí theo khu vực hoặc nhiều khu vực của kho lưu trữ.
  • PROJECT_ID: Mã dự án trên đám mây của bạn.
  • Kho lưu trữ: tên của kho lưu trữ Artifact Registry của bạn.
  • IMAGE_NAME: tên của hình ảnh vùng chứa của bạn.

Sau khi quá trình này hoàn tất, hình ảnh vùng chứa của bạn sẽ được tạo, lưu trữ trong Artifact Registry và triển khai lên Cloud Run.

Kết thúc lớp học lập trình này, ứng dụng của bạn sẽ giống như ứng dụng trong thư mục mod4-migrate-to-cloud-run.

Vậy là xong! Bạn đã di chuyển thành công một ứng dụng Java 8 App Engine sang Java 17 và Cloud Run, đồng thời hiểu rõ hơn về công việc liên quan khi chuyển đổi và chọn giữa các lựa chọn lưu trữ.

6. Tóm tắt/Dọn dẹp

Xin chúc mừng! Bạn đã nâng cấp, lưu trữ, di chuyển và ứng dụng của mình. Bài học này kết thúc hướng dẫn!

Từ đây, bước tiếp theo là tìm hiểu thêm về CI/CD và các tính năng bảo mật chuỗi cung ứng phần mềm mà giờ đây bạn có thể triển khai bằng Cloud Build:

Không bắt buộc: Dọn dẹp và/hoặc tắt dịch vụ

Nếu bạn đã triển khai ứng dụng mẫu trên App Engine trong quá trình hướng dẫn này, hãy nhớ tắt ứng dụng để tránh phát sinh phí. Khi đã sẵn sàng chuyển sang lớp học lập trình tiếp theo, bạn có thể bật lại lớp học này. Mặc dù các ứng dụng App Engine bị tắt, chúng sẽ không nhận được bất kỳ lưu lượng truy cập nào để phải chịu phí. Tuy nhiên, việc sử dụng Datastore có thể được tính phí nếu vượt quá hạn mức miễn phí, vì vậy hãy xóa đủ để nằm trong giới hạn đó.

Mặt khác, nếu không định tiếp tục quá trình di chuyển và muốn xoá hoàn toàn mọi thứ, thì bạn có thể xoá dịch vụ hoặc tắt hoàn toàn dự án.

7. Tài nguyên khác

Vấn đề/phản hồi trong lớp học lập trình mô-đun di chuyển App Engine

Nếu bạn gặp vấn đề với lớp học lập trình này, trước tiên, hãy tìm vấn đề của bạn trước khi gửi. Đường liên kết để tìm kiếm và báo cáo vấn đề mới:

Tài nguyên di chuyển

Tài nguyên trực tuyến

Dưới đây là các tài nguyên trực tuyến có thể phù hợp với hướng dẫn này:

App Engine

Thông tin khác về đám mây

Video

Giấy phép

Tác phẩm này được cấp phép theo Giấy phép chung Ghi nhận tác giả Creative Commons 2.0.