You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCP云函数中从Secret Manager获取API Key初始化Typesense客户端

解决方案:从GCP Secret Manager加载Typesense API Key并优化客户端初始化

一、修复Secret Manager调用与Typesense客户端初始化问题

你的核心问题是模块加载阶段无法直接使用异步操作,以下两种可靠方式可解决:

方法1:异步初始化函数+全局缓存(推荐,兼容多数场景)

调整代码结构,让Typesense客户端在第一次云函数调用时初始化并缓存,避免重复读取Secret Manager:

  1. 修改secretclient.js,导出异步函数并支持单独测试:
const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const secretClient = new SecretManagerServiceClient();

async function getTypesenseApiKey() {
  const [version] = await secretClient.accessSecretVersion({
    name: "projects/projectid/secrets/TYPESENSE_API_KEY/versions/latest",
  });
  const searchApiKey = version.payload.data.toString();
  console.log("Fetched Typesense API Key");
  return searchApiKey;
}

// 单独运行文件时测试密钥获取
if (require.main === module) {
  getTypesenseApiKey()
    .then(key => console.log("Test output:", key))
    .catch(err => console.error("Test error:", err));
}

module.exports = getTypesenseApiKey;
  1. 修改typesense.js,导出带缓存逻辑的客户端获取函数:
const Typesense = require("typesense");
const getTypesenseApiKey = require("./secretclient");

// 全局缓存已初始化的客户端
let cachedClient = null;

async function getTsClient() {
  if (cachedClient) {
    return cachedClient;
  }

  const apiKey = await getTypesenseApiKey();
  cachedClient = new Typesense.Client({
    nodes: [{
      host: "typesense.host.com",
      port: "443",
      protocol: "https",
    }],
    apiKey: apiKey,
    connectionTimeoutSeconds: 5,
  });

  return cachedClient;
}

module.exports = getTsClient;
  1. 更新index.js,在云函数内异步获取客户端:
const admin = require("firebase-admin");
const { onRequest } = require("firebase-functions/v2/https");
const getTsClient = require("./typesense");

admin.initializeApp();

exports.someProcess = onRequest(async (request, response) => {
  try {
    const tsClient = await getTsClient();
    // 构造searchParam逻辑
    const result = await tsClient.multiSearch.perform(searchParam);
    console.log(result);

    // 处理结果并保存到其他集合
    response.send(result);
  } catch (err) {
    console.error("Process error:", err);
    response.status(500).send("Internal Server Error");
  }
});

方法2:启用顶层await(需调整环境配置)

若你的Node.js版本≥14.8,可通过顶层await在模块加载时完成初始化:

  1. 修改typesense.js:
const Typesense = require("typesense");
const getTypesenseApiKey = require("./secretclient");

const apiKey = await getTypesenseApiKey();
const client = new Typesense.Client({
  nodes: [{
    host: "typesense.host.com",
    port: "443",
    protocol: "https",
  }],
  apiKey: apiKey,
  connectionTimeoutSeconds: 5,
});

exports.tsClient = client;
  1. 调整ESLint配置(若出现语法报错):
    在.eslintrc.js中添加:
module.exports = {
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
  },
  rules: {
    "no-top-level-await": "off",
  },
};
  1. 在GCP控制台将云函数的Node.js运行时版本设置为14或更高。

二、关于全局客户端缓存的合理性

完全合理。GCP云函数采用冷启动+热启动模式:

  • 冷启动:首次调用或空闲重启时,会重新加载模块
  • 热启动:短时间内重复调用时,会复用已加载的模块和全局对象

将Typesense客户端缓存为全局对象的好处:

  1. 减少Secret Manager调用次数,降低开销
  2. 避免重复创建客户端实例,提升响应速度
  3. 热启动时直接复用已初始化的客户端,缩短启动时间

若需定期轮换API Key,可添加缓存过期逻辑,或通过修改云函数环境变量触发重启,加载新密钥。

内容的提问来源于stack exchange,提问作者seven21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:08:21