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

Firebase Function调用Typesense客户端时出现随机超时问题

Firebase Cloud Function 调用 Typesense 偶尔超时失败(随机发生在 onCreate/onUpdate 触发器中)

问题描述

配置了监听 Firestore 数据更新的 Firebase Cloud Function,多数情况下能正常执行并同步数据到 Typesense,但偶尔会出现超时失败。该问题在其他使用 Typesense 客户端的 onCreate、onUpdate 类型函数中也随机出现。

日志情况

  • 失败时函数日志显示超时(来自 Google Cloud 控制台日志)
  • 成功时日志显示完整执行流程,包含Typesense: Program [ID] successfully updated!的完成标记

相关代码

Firebase Function 代码

// Firebase function triggered when a program is updated
export const onUpdate = functions
  // 256MB memory and timeout of 2 minutes
  .runWith({ memory: '256MB', timeoutSeconds: 120 })
  .firestore.document('programs/{docId}')
  .onCreate(async (snap, context) => {
    const id = context.params.docId;
    const data = snap.data();

    const client = useTypesense();

    const item = { ...data, id };

    console.log('Typesense: Updating Program');
    await client
      .collections('programs')
      .documents()
      .upsert(item)
      .then(() => {
        console.log(`Typesense: Program ${item.id} successfully updated!`);
      })
      .catch((error) => {
        console.error('Typesense: Error creating Program: ' + item.id, error);
      });

    return null;
  });

Typesense 客户端初始化函数(useTypesense)

import Typesense from 'typesense';

const useTypesense = () => {
  const host = 'api.oniworkout.app'
  const port = '443'
  const protocol = 'https'
  const apiKey = 'b3fxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';

  console.log(
    `Typesense: Initializing client with host: ${host}, port: ${port}, protocol: ${protocol}, apiKey: ${apiKey.substring(
      0,
      3
    )}`
  );

  const client = new Typesense.Client({
    nodes: [
      {
        host,
        port,
        protocol,
      },
    ],
    apiKey,
    connectionTimeoutSeconds: 120,
    retryIntervalSeconds: 120,
  });

  return client;
};

已尝试的排查措施

  • 将 Firebase Function 超时时间从 60 秒延长至 120 秒,问题仍存在
  • 检查 Typesense 实例健康接口,返回{"ok":true},实例状态正常

解决方案建议

1. 优化 Typesense 客户端重试策略

当前retryIntervalSeconds: 120过长,且未设置重试次数,网络波动时易超出函数超时窗口。调整参数如下:

const client = new Typesense.Client({
  nodes: [{ host, port, protocol }],
  apiKey,
  connectionTimeoutSeconds: 30, // 缩短单次请求超时,避免长时间挂起
  retryIntervalSeconds: 2, // 缩短重试间隔
  numRetries: 3, // 设置重试次数
  retryOnStatusCodes: [429, 500, 502, 503, 504], // 针对常见错误码重试
});

2. 复用 Typesense 客户端连接

每次函数触发都重新初始化客户端会增加连接开销,将客户端初始化放在函数外部实现复用:

// 全局初始化一次,复用连接
const client = new Typesense.Client({
  nodes: [{ host: 'api.oniworkout.app', port: '443', protocol: 'https' }],
  apiKey: 'b3fxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
  connectionTimeoutSeconds: 30,
  retryIntervalSeconds: 2,
  numRetries: 3,
});

export const onUpdate = functions
  .runWith({ memory: '256MB', timeoutSeconds: 120 })
  .firestore.document('programs/{docId}')
  .onCreate(async (snap, context) => {
    const id = context.params.docId;
    const data = snap.data();
    const item = { ...data, id };

    console.log('Typesense: Updating Program');
    try {
      await client.collections('programs').documents().upsert(item);
      console.log(`Typesense: Program ${item.id} successfully updated!`);
    } catch (error) {
      console.error('Typesense: Error creating Program: ' + item.id, error);
      // 抛出错误触发 Firebase 自动重试(可选,upsert 操作本身幂等)
      throw error;
    }
    return null;
  });

3. 开启 Firebase Function 自动重试

针对异步触发器,配置函数失败时自动重试:

export const onUpdate = functions
  .runWith({ 
    memory: '256MB', 
    timeoutSeconds: 120,
    retry: true // 开启自动重试
  })
  .firestore.document('programs/{docId}')
  .onCreate(...);

4. 对齐部署区域

确保 Firebase Function 与 Typesense 实例的部署区域尽可能接近,减少网络延迟。

5. 监控 Typesense 实例负载

通过 Typesense 的/metrics接口监控 CPU、内存、请求队列等指标,判断是否需要升级实例规格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:55:15