Phân phát nội dung động và dịch vụ vi mô lưu trữ bằng Cloud Run

Kết hợp Cloud Run với tính năng Lưu trữ Firebase để tạo và phân phát quảng cáo nội dung động hoặc xây dựng API REST dưới dạng dịch vụ vi mô.

Bằng cách sử dụng Cloud Run, bạn có thể triển khai ứng dụng được đóng gói trong hình ảnh vùng chứa. Sau đó, sử dụng Dịch vụ Lưu trữ Firebase, bạn có thể chuyển hướng các yêu cầu HTTPS để kích hoạt ứng dụng trong vùng chứa.

  • Hỗ trợ Cloud Run một số ngôn ngữ (bao gồm Go, Node.js, Python và Java), mang đến cho bạn sự linh hoạt khi sử dụng ngôn ngữ lập trình và khung chương trình mà bạn chọn.
  • Cloud Run điều chỉnh tự động và theo chiều ngang hình ảnh vùng chứa của bạn để xử lý các yêu cầu đã nhận được, sau đó thu nhỏ khi nhu cầu giảm xuống.
  • Bạn chỉ trả tiền cho CPU, bộ nhớ và kết nối mạng tiêu thụ trong quá trình xử lý yêu cầu.

Ví dụ về các trường hợp sử dụng và mẫu cho Cloud Run được tích hợp với Lưu trữ Firebase, hãy truy cập vào thông tin tổng quan về mô hình không máy chủ.


Hướng dẫn này chỉ cho bạn cách:

  1. Viết một ứng dụng Hello World đơn giản
  2. Thêm ứng dụng vào vùng chứa rồi tải ứng dụng đó lên Container Registry
  3. Triển khai hình ảnh vùng chứa cho Cloud Run
  4. Các yêu cầu Lưu trữ trực tiếp đến ứng dụng trong vùng chứa của bạn

Xin lưu ý rằng để cải thiện hiệu suất phân phát nội dung động, bạn có thể tinh chỉnh chế độ cài đặt bộ nhớ đệm nếu muốn.

Trước khi bắt đầu

Trước khi sử dụng Cloud Run, bạn cần hoàn thành một số nhiệm vụ ban đầu, bao gồm cả việc thiết lập tài khoản thanh toán trên đám mây, bật tính năng Cloud Run API và cài đặt công cụ dòng lệnh gcloud.

Thiết lập thông tin thanh toán cho dự án

Cloud Run cung cấp hạn mức sử dụng miễn phí, nhưng bạn vẫn phải có Tài khoản thanh toán trên Cloud liên kết với dự án Firebase của bạn để sử dụng hoặc dùng thử Cloud Run.

Bật API và cài đặt SDK

  1. Bật Cloud Run API trong bảng điều khiển API của Google:

    1. Mở Trang API Cloud Run trong bảng điều khiển API của Google.

    2. Khi được nhắc, hãy chọn dự án Firebase của bạn.

    3. Nhấp vào Bật trên trang Cloud Run API.

  2. Cài đặt và khởi chạy Cloud SDK.

  3. Kiểm tra để đảm bảo bạn đã định cấu hình công cụ gcloud cho đúng dự án:

    gcloud config list

Bước 1: Viết ứng dụng mẫu

Xin lưu ý rằng Cloud Run hỗ trợ nhiều ngôn ngữ khác ngoài các ngôn ngữ được nêu trong mẫu sau đây.

Tiến hành

  1. Tạo một thư mục mới có tên là helloworld-go, sau đó thay đổi thư mục thành nó:

    mkdir helloworld-go
    cd helloworld-go
  2. Tạo tệp mới có tên helloworld.go, sau đó thêm đoạn mã sau:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("helloworld: received a request")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    
    func main() {
    	log.Print("helloworld: starting server...")
    
    	http.HandleFunc("/", handler)
    
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    
    	log.Printf("helloworld: listening on port %s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    

    Mã này tạo một máy chủ web cơ bản nghe trên cổng được xác định bởi biến môi trường PORT.

Ứng dụng đã hoàn tất và sẵn sàng để bạn lưu trữ cũng như tải lên Sổ đăng ký vùng chứa (container Registry).

Node.js

  1. Tạo một thư mục mới có tên là helloworld-nodejs, sau đó thay đổi thư mục vào đó:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Tạo tệp package.json có các nội dung sau:

    {
      "name": "knative-serving-helloworld",
      "version": "1.0.0",
      "description": "Simple hello world sample in Node",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "express": "^4.19.2"
      }
    }
    
  3. Tạo tệp mới có tên index.js, sau đó thêm đoạn mã sau:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      console.log('Hello world received a request.');
    
      const target = process.env.TARGET || 'World';
      res.send(`Hello ${target}!\n`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });
    

    Mã này tạo một máy chủ web cơ bản nghe trên cổng được xác định bởi biến môi trường PORT.

Ứng dụng đã hoàn tất và sẵn sàng để bạn lưu trữ cũng như tải lên Sổ đăng ký vùng chứa (container Registry).

Python

  1. Tạo một thư mục mới có tên là helloworld-python, sau đó thay đổi thư mục vào đó:

    mkdir helloworld-python
    cd helloworld-python
  2. Tạo tệp mới có tên app.py, sau đó thêm đoạn mã sau:

    import os
    
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        target = os.environ.get('TARGET', 'World')
        return 'Hello {}!\n'.format(target)
    
    if __name__ == "__main__":
        app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))
    

    Mã này tạo một máy chủ web cơ bản nghe trên cổng được xác định bởi biến môi trường PORT.

Ứng dụng đã hoàn tất và sẵn sàng để bạn lưu trữ cũng như tải lên Sổ đăng ký vùng chứa (container Registry).

Java

  1. Cài đặt JDK Java SE 8 trở lênCURL.

    Xin lưu ý rằng chúng ta chỉ cần thực hiện thao tác này để tạo dự án web mới trong bước tiếp theo. Dockerfile, được mô tả ở phần sau, sẽ tải tất cả vào vùng chứa.

  2. Trong bảng điều khiển, hãy tạo một dự án web trống mới bằng cURL, sau đó lệnh giải nén:

    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d name=helloworld \
        -d artifactId=helloworld \
        -o helloworld.zip
    unzip helloworld.zip

    Thao tác này sẽ tạo một dự án SpringBoot.

  3. Cập nhật lớp SpringBootApplication trong src/main/java/com/example/helloworld/HelloworldApplication.java theo thêm @RestController để xử lý việc ánh xạ /, đồng thời thêm một Trường @Value để cung cấp biến môi trường TARGET:

    package com.example.helloworld;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    public class HelloworldApplication {
    
      @Value("${TARGET:World}")
      String target;
    
      @RestController
      class HelloworldController {
        @GetMapping("/")
        String hello() {
          return "Hello " + target + "!";
        }
      }
    
      public static void main(String[] args) {
        SpringApplication.run(HelloworldApplication.class, args);
      }
    }
    

    Mã này tạo một máy chủ web cơ bản nghe trên cổng được xác định bởi biến môi trường PORT.

Ứng dụng đã hoàn tất và sẵn sàng để bạn lưu trữ cũng như tải lên Sổ đăng ký vùng chứa (container Registry).

Bước 2: Lưu trữ một ứng dụng rồi tải ứng dụng đó lên Container Registry

  1. Vùng chứa ứng dụng mẫu bằng cách tạo một tệp mới có tên Dockerfile trong cùng thư mục với tệp nguồn. Sao chép nội dung sau vào .

    Tiến hành

    # Use the official Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    FROM golang:latest as builder
    
    ARG TARGETOS
    ARG TARGETARCH
    
    # Create and change to the app directory.
    WORKDIR /app
    
    # Retrieve application dependencies using go modules.
    # Allows container builds to reuse downloaded dependencies.
    COPY go.* ./
    RUN go mod download
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build the binary.
    # -mod=readonly ensures immutable go.mod and go.sum in container builds.
    RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -mod=readonly -v -o server
    
    # Use the official Alpine image for a lean production container.
    # https://hub.docker.com/_/alpine
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM alpine:3
    RUN apk add --no-cache ca-certificates
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /app/server /server
    
    # Run the web service on container startup.
    CMD ["/server"]
    

    Node.js

    # Use the official lightweight Node.js 12 image.
    # https://hub.docker.com/_/node
    FROM node:12-slim
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package*.json ./
    
    # Install production dependencies.
    RUN npm install --only=production
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Python

    # Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.7-slim
    
    # Allow statements and log messages to immediately appear in the Knative logs
    ENV PYTHONUNBUFFERED True
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
    

    Java

    # Use the official maven/Java 8 image to create a build artifact: https://hub.docker.com/_/maven
    FROM maven:3.5-jdk-8-alpine as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY pom.xml .
    COPY src ./src
    
    # Build a release artifact.
    RUN mvn package -DskipTests
    
    # Use the Official OpenJDK image for a lean production stage of our multi-stage build.
    # https://hub.docker.com/_/openjdk
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM openjdk:8-jre-alpine
    
    # Copy the jar to the production image from the builder stage.
    COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar
    
    # Run the web service on container startup.
    CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"]
    

  2. Tạo hình ảnh vùng chứa bằng Cloud Build bằng cách chạy lệnh sau từ thư mục chứa Dockerfile của bạn:

    gcloud builds submit --tag gcr.io/PROJECT_ID/helloworld

    Sau khi thành công, bạn sẽ thấy thông báo THÀNH CÔNG chứa tên hình ảnh
    (gcr.io/PROJECT_ID/helloworld).

Hình ảnh vùng chứa hiện được lưu trữ trong Container Registry và có thể được sử dụng lại nếu mong muốn.

Lưu ý rằng, thay vì Cloud Build, bạn có thể sử dụng phiên bản được cài đặt cục bộ của Docker đến tạo vùng chứa cục bộ.

Bước 3: Triển khai hình ảnh vùng chứa cho Cloud Run

  1. Triển khai bằng lệnh sau:

    gcloud run deploy --image gcr.io/PROJECT_ID/helloworld

  2. Khi được nhắc:

Để đạt được hiệu suất tốt nhất, hãy sắp xếp lại dịch vụ Cloud Run với tính năng Lưu trữ bằng cách sử dụng các khu vực sau:

  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1

Ghi lại vào Cloud Run từ tính năng Lưu trữ được hỗ trợ trong những khu vực sau:

  • asia-east1
  • asia-east2
  • asia-northeast1
  • asia-northeast2
  • asia-northeast3
  • asia-south1
  • asia-south2
  • asia-southeast1
  • asia-southeast2
  • australia-southeast1
  • australia-southeast2
  • europe-central2
  • europe-north1
  • europe-southwest1
  • europe-west1
  • europe-west12
  • europe-west2
  • europe-west3
  • europe-west4
  • europe-west6
  • europe-west8
  • europe-west9
  • me-central1
  • me-west1
  • northamerica-northeast1
  • northamerica-northeast2
  • southamerica-east1
  • southamerica-west1
  • us-central1
  • us-east1
  • us-east4
  • us-east5
  • us-south1
  • us-west1
  • us-west2
  • us-west3
  • us-west4
  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1
  1. Hãy đợi trong giây lát để quá trình triển khai hoàn tất. Khi thành công, dòng lệnh hiển thị URL dịch vụ. Ví dụ: https://helloworld-RANDOM_HASH-us-central1.a.run.app

  2. Truy cập vào vùng chứa mà bạn đã triển khai bằng cách mở URL dịch vụ trong trình duyệt web.

Bước tiếp theo sẽ hướng dẫn bạn cách truy cập vào ứng dụng trong vùng chứa này từ một URL lưu trữ Firebase để có thể tạo nội dung động cho Trang web được lưu trữ trên Firebase.

Bước 4: Hướng các yêu cầu lưu trữ đến ứng dụng nằm trong vùng chứa của bạn

Bằng viết lại quy tắc, bạn có thể chuyển hướng các yêu cầu khớp các mẫu cụ thể với một đích đến duy nhất.

Ví dụ sau đây cho biết cách chuyển hướng tất cả yêu cầu từ trang /helloworld trên trang web Lưu trữ của bạn để kích hoạt việc khởi động và chạy thực thể của vùng chứa helloworld.

  1. Đảm bảo rằng:

    Để biết hướng dẫn chi tiết về cách cài đặt CLI và khởi tạo Lưu trữ, hãy xem Hướng dẫn bắt đầu sử dụng tính năng lưu trữ.

  2. Mở tệp firebase.json của bạn.

  3. Thêm cấu hình rewrite sau trong phần hosting:

    "hosting": {
      // ...
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/helloworld",
        "run": {
          "serviceId": "helloworld",  // "service name" (from when you deployed the container image)
          "region": "us-central1",    // optional (if omitted, default is us-central1)
          "pinTag": true              // optional (see note below)
        }
      } ]
    }
    
  4. Triển khai cấu hình lưu trữ cho trang web của bạn bằng cách chạy lệnh sau từ gốc của thư mục dự án:

    firebase deploy --only hosting

Vùng chứa của bạn hiện có thể truy cập được thông qua các URL sau:

  • Các miền con Firebase của bạn:
    PROJECT_ID.web.app/PROJECT_ID.firebaseapp.com/

  • Bất kỳ miền tuỳ chỉnh nào đã kết nối:
    CUSTOM_DOMAIN/

Truy cập trang cấu hình Lưu trữ cho thông tin chi tiết khác về quy tắc ghi lại. Bạn có thể cũng sẽ tìm hiểu về thứ tự ưu tiên của câu trả lời cho nhiều cấu hình Lưu trữ.

Kiểm thử cục bộ

Trong quá trình phát triển, bạn có thể chạy và kiểm tra cục bộ hình ảnh vùng chứa. Để hướng dẫn chi tiết, hãy truy cập vào Tài liệu về Cloud Run.

Các bước tiếp theo