Cung cấp nội dung Firestore đi kèm từ CDN

Nhiều ứng dụng phục vụ cùng một nội dung cho tất cả người dùng khi tải trang đầu tiên. Ví dụ: một trang tin tức có thể hiển thị những câu chuyện mới nhất hoặc một trang thương mại điện tử có thể hiển thị các mặt hàng bán chạy nhất.

Nếu nội dung này được cung cấp từ Cloud Firestore, mỗi người dùng sẽ đưa ra một truy vấn mới cho cùng kết quả khi họ tải ứng dụng. Vì những kết quả này không được lưu vào bộ nhớ đệm giữa những người dùng nên ứng dụng sẽ chậm hơn và tốn kém hơn mức cần thiết.

Giải pháp: Gói

Các gói Cloud Firestore cho phép bạn tập hợp các gói dữ liệu từ các kết quả truy vấn phổ biến trên phần phụ trợ bằng cách sử dụng SDK quản trị Firebase và phân phát các đốm màu được tính toán trước này được lưu vào bộ nhớ đệm trên CDN. Điều này mang lại cho người dùng của bạn trải nghiệm tải lần đầu nhanh hơn nhiều và giảm chi phí truy vấn Cloud Firestore của bạn.

Trong hướng dẫn này, chúng tôi sẽ sử dụng Chức năng đám mây để tạo gói và Firebase Hosting để lưu trữ động và phân phát nội dung gói. Thông tin thêm về các gói có sẵn trong hướng dẫn .

Trước tiên, hãy tạo một hàm HTTP công khai đơn giản để truy vấn 50 "câu chuyện" mới nhất và cung cấp kết quả dưới dạng một gói.

Node.js
exports.createBundle = functions.https.onRequest(async (request, response) => {
  // Query the 50 latest stories
  const latestStories = await db.collection('stories')
    .orderBy('timestamp', 'desc')
    .limit(50)
    .get();

  // Build the bundle from the query results
  const bundleBuffer = db.bundle('latest-stories')
    .add('latest-stories-query', latestStories)
    .build();

  // Cache the response for up to 5 minutes;
  // see https://firebase.google.com/docs/hosting/manage-cache
  response.set('Cache-Control', 'public, max-age=300, s-maxage=600');

  response.end(bundleBuffer);
});
      
Java

package com.example;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.FirestoreBundle;
import com.google.cloud.firestore.Query.Direction;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.cloud.FirestoreClient;
import java.io.BufferedWriter;
import java.io.IOException;

public class ExampleFunction implements HttpFunction {

  public static FirebaseApp initializeFirebase() throws IOException {
    if (FirebaseApp.getApps().isEmpty()) {
      FirebaseOptions options = FirebaseOptions.builder()
          .setCredentials(GoogleCredentials.getApplicationDefault())
          .setProjectId("YOUR-PROJECT-ID")
          .build();

      FirebaseApp.initializeApp(options);
    }

    return FirebaseApp.getInstance();
  }

  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    // Get a Firestore instance
    FirebaseApp app = initializeFirebase();
    Firestore db = FirestoreClient.getFirestore(app);

    // Query the 50 latest stories
    QuerySnapshot latestStories = db.collection("stories")
        .orderBy("timestamp", Direction.DESCENDING)
        .limit(50)
        .get()
        .get();

    // Build the bundle from the query results
    FirestoreBundle bundle = db.bundleBuilder("latest-stores")
        .add("latest-stories-query", latestStories)
        .build();

    // Cache the response for up to 5 minutes
    // see https://firebase.google.com/docs/hosting/manage-cache
    response.appendHeader("Cache-Control", "public, max-age=300, s-maxage=600");

    // Write the bundle to the HTTP response
    BufferedWriter writer = response.getWriter();
    writer.write(new String(bundle.toByteBuffer().array()));
  }
}
      

Tiếp theo, hãy định cấu hình Firebase Hosting để phân phát và lưu vào bộ nhớ đệm Chức năng đám mây này bằng cách sửa đổi firebase.json . Với cấu hình này, CDN lưu trữ Firebase sẽ phân phát nội dung gói theo cài đặt bộ đệm do Chức năng đám mây đặt. Khi bộ đệm hết hạn, nó sẽ làm mới nội dung bằng cách kích hoạt lại chức năng.

firebase.json
{
  "hosting": {
    // ...
    "rewrites": [{
      "source": "/createBundle",
      "function": "createBundle"
    }]
  },
  // ...
}

Cuối cùng, trong ứng dụng web của bạn, tìm nạp nội dung đi kèm từ CDN và tải nó vào Firestore SDK.

// If you are using module bundlers.
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/firestore/bundle" // This line enables bundle loading as a side effect.

async function fetchFromBundle() {
  // Fetch the bundle from Firebase Hosting, if the CDN cache is hit the 'X-Cache'
  // response header will be set to 'HIT'
  const resp = await fetch('/createBundle');

  // Load the bundle contents into the Firestore SDK
  await db.loadBundle(resp.body);

  // Query the results from the cache
  // Note: omitting "source: cache" will query the Firestore backend.
  
  const query = await db.namedQuery('latest-stories-query');
  const storiesSnap = await query.get({ source: 'cache' });

  // Use the results
  // ...
}

Tiết kiệm ước tính

Hãy xem xét một trang web tin tức có 100.000 người dùng mỗi ngày và mỗi người dùng tải 50 câu chuyện hàng đầu giống nhau trong lần tải đầu tiên. Nếu không có bất kỳ bộ nhớ đệm nào, điều này sẽ dẫn đến 50 x 100.000 = 5.000.000 lượt đọc tài liệu mỗi ngày từ Cloud Firestore.

Bây giờ, giả sử trang web áp dụng kỹ thuật trên và lưu trữ 50 kết quả đó trong tối đa 5 phút. Vì vậy, thay vì tải kết quả truy vấn cho mọi người dùng, kết quả được tải chính xác 12 lần mỗi giờ. Cho dù có bao nhiêu người dùng truy cập trang web thì số lượng truy vấn tới Cloud Firestore vẫn giữ nguyên. Thay vì 5.000.000 lượt đọc tài liệu, trang này sẽ sử dụng 12 x 24 x 50 = 14.400 lượt đọc tài liệu mỗi ngày. Các chi phí bổ sung nhỏ cho Dịch vụ lưu trữ Firebase và Chức năng đám mây có thể dễ dàng được bù đắp bằng khoản tiết kiệm chi phí của Cloud Firestore.

Trong khi nhà phát triển được hưởng lợi từ việc tiết kiệm chi phí thì người hưởng lợi lớn nhất lại là người dùng. Tải 50 tài liệu này từ Firebase Hosting CDN thay vì trực tiếp từ Cloud Firestore có thể dễ dàng giảm 100-200 mili giây trở lên so với thời gian tải nội dung của trang. Các nghiên cứu đã nhiều lần chỉ ra rằng các trang có tốc độ nhanh có nghĩa là người dùng hạnh phúc hơn.