使用 Firestore 处理会话


本教程介绍如何在 App Engine 上处理会话。

许多应用需要处理身份验证和用户偏好设置的会话。PHP 附带基于内存的实现可实现此功能。但此实现不适用于可以通过多个实例提供的应用,因为各实例之间记录的会话可能不同。

目标

  • 编写应用。
  • 在本地运行应用。
  • 在 App Engine 上部署应用。

费用

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

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

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

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Firestore API.

    Enable the API

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the Firestore API.

    Enable the API

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. 配置 gcloud CLI 以使用您的新 Google Cloud 项目:
    # Configure gcloud for your project
    gcloud config set project PROJECT_ID
    PROJECT_ID 替换为您之前创建或选择的 Google Cloud 项目 ID。

设置项目

  1. 在终端窗口中,从您选择的目录启动,并创建一个名为 sessions 的新目录。本教程的所有代码均位于 sessions 目录内。

  2. 切换到 sessions 目录:

    cd sessions
    
  3. 安装依赖项:

    composer require google/cloud-firestore
    

在本教程结束时,最终文件结构类似于以下内容:

sessions
├── app.yaml
└── composer.json
├── index.php

编写应用

  • 在终端窗口中,使用以下内容创建名为 index.php 的文件:

    <?php
    /*
     * Copyright 2019 Google LLC
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    require_once __DIR__ . '/vendor/autoload.php';
    
    use Google\Cloud\Firestore\FirestoreClient;
    
    $projectId = getenv('GOOGLE_CLOUD_PROJECT');
    // Instantiate the Firestore Client for your project ID.
    $firestore = new FirestoreClient([
        'projectId' => $projectId,
    ]);
    
    $handler = $firestore->sessionHandler(['gcLimit' => 500]);
    
    // Configure PHP to use the the Firebase session handler.
    session_set_save_handler($handler, true);
    session_save_path('sessions');
    session_start();
    
    $colors = ['red', 'blue', 'green', 'yellow', 'pink'];
    /**
     * This is an example of a front controller for a flat file PHP site. Using a
     * Static list provides security against URL injection by default.
     */
    switch (@parse_url($_SERVER['REQUEST_URI'])['path']) {
        case '/':
            if (!isset($_SESSION['views'])) {
                $_SESSION['views'] = 0;
                $_SESSION['color'] = $colors[rand(0, 4)];
            }
            printf(
                '<body bgcolor="%s">Views: %s</body>',
                $_SESSION['color'],
                $_SESSION['views']++
            );
            break;
        default:
            http_response_code(404);
            exit('Not Found');
    }
    

此应用为每位用户显示不同语言的问候语。回访用户始终会收到同一种语言的问候语。

多个应用窗口显示不同语言的问候语。

在应用存储用户偏好设置之前,您需要存储会话中当前用户的相关信息。此示例应用使用 Firestore 来存储会话数据。

您可以通过 Firestore session handler 来使用 Firestore 处理 PHP 会话。

下图说明了 Firestore 如何处理 App Engine 应用的会话。

架构图:用户、App Engine、Firestore。

设置 session_set_save_handler 之后,每个请求都有一个 $_SESSION 全局变量供您访问会话。会话数据存储在 Firestore 中。

在本地运行

  1. 启动内置 PHP Web 服务器:

    php -S localhost:8080
    
  2. 在网络浏览器中查看应用:

    Cloud Shell

    在 Cloud Shell 工具栏中,点击 Web 预览 Web 预览,然后选择在端口 8080 上预览

    本地机器

    在浏览器中,转到 http://localhost:8080

    您会看到五个问候语之一:“Hello World”、“Hallo Welt”、“Hola mundo”、“Salut le Monde”或“Ciao Mondo”。如果您使用其他浏览器或无痕模式打开网页,语言会更改。您可以在 Google Cloud 控制台中查看和修改会话数据。

    Google Cloud 控制台中的 Firestore 会话。

  3. 要停止 HTTP 服务器,请在终端窗口中按 Control+C

在 App Engine 上部署并运行

通过 App Engine 标准环境,您可以构建和部署在繁重负载和大量数据的压力下仍能可靠运行的应用。

本教程使用 App Engine 标准环境来部署服务器。

  1. 在您的终端窗口中,创建一个 app.yaml 文件并复制以下内容:

    runtime: php73
    
  2. 在 App Engine 上部署应用:

    gcloud app deploy
    
  3. 如需查看实际应用,请输入以下网址:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    替换以下内容:

现在,问候语由在 App Engine 实例上运行的 Web 服务器提供。

删除会话

PHP 会执行会话垃圾回收 (GC),根据您的 php.ini 配置移除旧会话和过期会话。默认情况下,Firestore 会话处理程序不会清理会话,但您可以在创建会话处理程序时传递 gcLimit 选项,以将该处理程序配置为执行此操作:

$handler = $firestore->sessionHandler(['gcLimit' => 500]);

系统会使用基于概率的会话 GC 移除会话,您也可以显式调用 session_gc 函数来移除会话。

调试应用

如果您无法连接到 App Engine 应用,请检查以下内容:

  1. 检查 gcloud 部署命令是否已成功完成,并且未输出任何错误。如果存在错误(例如 message=Build failed),修复问题,然后再次尝试部署 App Engine 应用
  2. 在 Google Cloud 控制台中,转到 Logs Explorer 页面。

    转到“日志浏览器”页面

    1. 最近选择的资源下拉列表中,点击 App Engine 应用,然后点击所有 module_id。您将看到访问您的应用时的请求列表,如果您未发现请求列表,请确认您是否已从下拉列表中选择所有 module_id。如果您发现 Google Cloud 控制台出现错误消息,请检查应用代码是否与“编写 Web 应用”相关部分中的代码匹配。

    2. 确保已启用 Firestore API。

清理

删除项目

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

删除 App Engine 实例

  1. In the Google Cloud console, go to the Versions page for App Engine.

    Go to Versions

  2. Select the checkbox for the non-default app version that you want to delete.
  3. 如需删除应用版本,请点击删除

后续步骤