使用 Python 进行后台处理

许多应用都需要在 Web 请求情境之外进行后台处理。本教程创建了一个 Web 应用,让用户输入要翻译的文本,然后显示之前的翻译的列表。翻译在后台进程中完成,避免阻止用户的请求。

下图说明了翻译请求过程。

架构图。

教程应用的工作原理的事件序列如下:

  1. 访问网页,查看存储在 Firestore 中的之前的翻译的列表。
  2. 通过输入 HTML 表单请求翻译文本。
  3. 翻译请求被发布到 Pub/Sub。
  4. 触发已订阅该 Pub/Sub 主题的 Cloud Run 函数。
  5. Cloud Run 函数使用 Cloud Translation 来翻译文本。
  6. Cloud Run 函数将结果存储在 Firestore 中。

本教程适用于有兴趣了解如何使用 Google Cloud进行后台处理的用户。您无需拥有 Pub/Sub、Firestore、App Engine 或 Cloud Run functions 相关经验。不过,具有一定程度的 Python、JavaScript 和 HTML 相关经验会有助于您了解所有代码。

目标

  • 了解并部署 Cloud Run 函数。
  • 了解并部署 App Engine 应用。
  • 试用该应用。

费用

在本文档中,您将使用 Google Cloud的以下收费组件:

如需根据您的预计使用情况来估算费用,请使用价格计算器

新 Google Cloud 用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud新手,请 创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Firestore, Cloud Run functions, Pub/Sub, and Cloud Translation APIs.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Firestore, Cloud Run functions, Pub/Sub, and Cloud Translation APIs.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  8. 在 Google Cloud 控制台中,通过 Cloud Shell 打开此应用。

    转到 Cloud Shell

    利用 Cloud Shell,您可以直接在浏览器中通过命令行访问云端资源。在浏览器中打开 Cloud Shell,然后点击继续下载示例代码并切换到应用目录。

  9. 在 Cloud Shell 中,配置 gcloud 工具以使用您的 Google Cloud 项目:
    # Configure gcloud for your project
    gcloud config set project YOUR_PROJECT_ID

了解 Cloud Run 函数

  • 该函数首先导入多个依赖项,例如 Firestore 和 Translation。
    import base64
    import hashlib
    import json
    
    from google.cloud import firestore
    from google.cloud import translate_v2 as translate
  • 系统初始化全局 Firestore 和 Translation 客户端,以便可以在各函数调用之间重复使用它们。这样,您便无需针对每次函数调用初始化新的客户端(此操作会降低执行速度)。
    # Get client objects once to reuse over multiple invocations.
    xlate = translate.Client()
    db = firestore.Client()
  • Translation API 会将字符串翻译为您选择的语言。
    def translate_string(from_string, to_language):
        """ Translates a string to a specified language.
    
        from_string - the original string before translation
    
        to_language - the language to translate to, as a two-letter code (e.g.,
            'en' for english, 'de' for german)
    
        Returns the translated string and the code for original language
        """
        result = xlate.translate(from_string, target_language=to_language)
        return result['translatedText'], result['detectedSourceLanguage']
  • Cloud Run 函数首先会解析 Pub/Sub 消息,以获取要翻译的文本和所需的目标语言。

    然后,Cloud Run 函数会翻译文本并将其存储在 Firestore 中,并使用事务来确保没有重复的翻译。

    def document_name(message):
        """ Messages are saved in a Firestore database with document IDs generated
            from the original string and destination language. If the exact same
            translation is requested a second time, the result will overwrite the
            prior result.
    
            message - a dictionary with fields named Language and Original, and
                optionally other fields with any names
    
            Returns a unique name that is an allowed Firestore document ID
        """
        key = '{}/{}'.format(message['Language'], message['Original'])
        hashed = hashlib.sha512(key.encode()).digest()
    
        # Note that document IDs should not contain the '/' character
        name = base64.b64encode(hashed, altchars=b'+-').decode('utf-8')
        return name
    
    
    @firestore.transactional
    def update_database(transaction, message):
        name = document_name(message)
        doc_ref = db.collection('translations').document(document_id=name)
    
        try:
            doc_ref.get