Firebase函数每日UTC14:00左右故障,重部署可临时恢复
SvelteKit + Firebase 每日UTC14:00后Functions失效问题排查与解决
问题背景
基于SvelteKit的Firebase应用,同时采用Hosting+Functions部署架构,服务端代码编译为单个worker.js处理客户端请求。多数时段运行正常,但每日UTC14:00过后,Functions会完全失效,仅需通过GitHub Action无代码重部署即可恢复。
故障触发的两类错误
1. /service-worker.js 路由找不到错误
Error: Not found: /service-worker.js at resolve2 (file:///workspace/index.js:2750:18) at resolve (file:///workspace/index.js:2583:34) at Object.handle (file:///workspace/chunks/hooks.server.js:42:16) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async respond (file:///workspace/index.js:2581:22) at async handle (file:///workspace/node_modules/firebase-frameworks/dist/sveltekit/index.js:13:22)
2. IAM权限拒绝日志
{ insertId: "66f4196c00064965dcbf6873" labels: {3} logName: "projects/MYAPPNAME/logs/run.googleapis.com%2Fstderr" receiveTimestamp: "2024-09-25T14:08:44.418319648Z" resource: {2} spanId: "9273010944203965244" textPayload: "Permission 'iam.serviceAccounts.signBlob' denied on resource (or it may not exist).; Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature." timestamp: "2024-09-25T14:08:44.412005Z" trace: "57be6ab1ccede7137ab99da15a2b120e" }
附firebase.json配置
{ "hosting": { "source": ".", "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], "frameworksBackend": { "region": "europe-west1" }, "rewrites": [ { "source": "**", "function": "THEAUTOMATEDFUNCTIONNAME" } ] }, "emulators": { "auth": { "port": 9099 }, "firestore": { "port": 8080 }, "database": { "port": 9000 }, "storage": { "port": 9199 }, "ui": { "enabled": true }, "singleProjectMode": true }, "firestore": { "rules": "firestore.rules", "indexes": "firestore.indexes.json" }, "storage": { "rules": "storage. Rules" } }
故障原因分析
- IAM权限绑定临时失效:每日固定时间触发权限错误,且重部署即可恢复,核心原因是Firebase自动创建的Functions默认服务账号(
[项目ID]@appspot.gserviceaccount.com)的iam.serviceAccounts.signBlob权限被临时移除或角色绑定丢失。重部署时Firebase会重新校验并修复服务账号的权限绑定,因此能临时解决问题。 - 冷启动导致路由解析异常:UTC14:00大概率是云函数的定期冷启动/缓存刷新时间点,此时SvelteKit编译后的
worker.js未正确加载静态资源路由规则,导致/service-worker.js请求无法匹配,触发404错误。 - Hosting与Functions路由冲突:
rewrites配置将所有请求转发到Functions,但服务端worker未单独处理/service-worker.js的路由逻辑,重部署时会重新生成路由映射表,临时修复冲突。
彻底解决方法
1. 永久授予服务账号IAM权限
- 打开Google Cloud Console的IAM页面,找到Firebase Functions默认服务账号(格式:
[你的项目ID]@appspot.gserviceaccount.com)。 - 为该账号添加Service Account Token Creator角色(此角色包含
iam.serviceAccounts.signBlob权限),确保权限绑定为永久生效,避免后续自动丢失。
2. 修复SvelteKit路由与Service Worker配置
- 确保
service-worker.js放在SvelteKit项目的static目录下,避免被编译逻辑忽略。 - 在
hooks.server.js中添加专门的路由处理逻辑,优先匹配/service-worker.js请求:// hooks.server.js export async function handle({ event, resolve }) { if (event.url.pathname === '/service-worker.js') { const response = await resolve(event, { transformPageChunk: () => null }); response.headers.set('Cache-Control', 'public, max-age=0, must-revalidate'); return response; } return resolve(event); } - 检查
firebase.json的hosting.ignore配置,确保service-worker.js未被误加入忽略列表。
3. 优化云函数冷启动配置
- 在
firebase.json的frameworksBackend中添加minInstances配置,设置至少1个常驻实例,避免每日UTC14:00左右的冷启动触发异常:"frameworksBackend": { "region": "europe-west1", "minInstances": 1 }
4. 验证修复效果
- 部署完成后,手动访问
/service-worker.js确认返回正常;同时测试Auth相关功能,确保iam.serviceAccounts.signBlob权限正常生效。
内容的提问来源于stack exchange,提问作者M Afifi
相关产品推荐
相关产品推荐

