GCP中Firestore公网与PSC端点读写延迟一致,如何实现Cloud Shell级低延迟?
GCP Firestore 低延迟优化:VM实例达到Cloud Shell级延迟的方法
问题描述
我在GCP中部署了Firestore数据库,最初通过公网路由访问时,读写延迟约为280-300ms。为降低延迟,我创建了Private Service Connect(PSC)端点以私网访问数据库,但延迟并未改善。我分别在VM实例和Cloud Shell中运行测试脚本,VM端延迟仍维持在原水平,而Cloud Shell端延迟约为80ms。请问在GCP中是否可以让VM端达到Cloud Shell级别的低延迟?如果可以,该如何实现?
测试脚本
const admin = require('firebase-admin'); const path = require('path'); const axios = require('axios'); // Initialize Firebase Admin SDK const serviceAccount = require(path.resolve(__dirname, '/home/amityadav/sa.json')); // Replace with your own service account key path admin.initializeApp({ credential: admin.credential.cert(serviceAccount) }); console.log('Credentials After initializeApp:', serviceAccount.client_email); const db = admin.firestore(); const collectionName = 'testCollection'; const documentId = 'testDoc'; const docRef = db.collection(collectionName).doc(documentId); console.log('Firestore Path:', `projects/${serviceAccount.project_id}/databases/(default)/documents/${collectionName}/${documentId}`); // Function to test network latency async function testNetworkLatency(url) { const start = Date.now(); try { await axios.get(url); const end = Date.now(); return end - start; } catch (error) { console.error(`Error accessing ${url}:`, error); return -1; } } // Function to check if accessing DB privately or publicly async function checkAccessMethod() { const privateUrl = 'http://metadata.google.internal'; // Known private endpoint const publicUrl = 'https://www.google.com'; // Public endpoint const privateLatency = await testNetworkLatency(privateUrl); const publicLatency = await testNetworkLatency(publicUrl); console.log(`Private Network Latency: ${privateLatency} ms`); console.log(`Public Network Latency: ${publicLatency} ms`); if (privateLatency > 0 && (privateLatency < publicLatency)) { console.log('Accessing Firestore privately.'); } else { console.log('Accessing Firestore publicly.'); } } // Function to write data to Firestore async function writeToFirestore(data) { const startWrite = Date.now(); try { await db.collection(collectionName).doc(documentId).set(data); const endWrite = Date.now(); const writeLatency = endWrite - startWrite; console.log(`Write Latency: ${writeLatency} ms`); } catch (error) { console.error('Error writing to Firestore:', error); } } // Function to read data from Firestore async function readFromFirestore() { const startRead = Date.now(); try { const docRef = db.collection(collectionName).doc(documentId); const snapshot = await docRef.get(); const endRead = Date.now(); const readLatency = endRead - startRead; console.log(`Read Latency: ${readLatency} ms`); // Print the data fetched (optional) if (snapshot.exists) { console.log('Fetched Data:', snapshot.data()); } else { console.log('No data found'); } } catch (error) { console.error('Error reading from Firestore:', error); } } // Function to execute write and read operations every 2 seconds async function executeOperations() { try { const testData = { message: 'Hello, Firestore!' }; // Check if accessing DB privately or publicly await checkAccessMethod(); // Write data to Firestore await writeToFirestore(testData); // Read data from Firestore await readFromFirestore(); } catch (error) { console.error('Error executing operations:', error); } } // Start executing operations every 2 seconds setInterval(executeOperations, 2000);
解决方案
可以实现,以下是具体优化步骤:
1. 对齐VM与Firestore的部署区域
Cloud Shell默认部署在GCP核心服务所在区域,与Firestore同区域的私网访问延迟会显著降低:
- 登录Firestore控制台查看数据库的部署区域(如
us-central1)。 - 将VM实例迁移到该区域,或在同一区域重新创建VM。
2. 验证PSC端点配置有效性
当前脚本的私网访问判断逻辑不准确,需直接确认Firestore流量是否走PSC:
- 在VM上执行
tcpdump host firestore.googleapis.com,查看目标IP是否为PSC端点的内部IP(而非公网IP)。 - 确认PSC端点已绑定到VM所在的VPC,且VPC防火墙规则允许VM与PSC端点的443端口通信。
- 检查VPC Service Controls配置,确保VM所在VPC已被纳入Firestore的访问允许列表。
3. 升级VM网络与实例规格
- 切换到Premium Tier网络:将VM的网络服务层级从Standard改为Premium,该层级提供与Cloud Shell一致的低延迟网络路径。
- 选择高规格VM实例:避免使用共享CPU的入门级实例(如f1-micro),选用n2、c2等系列的专用CPU实例,减少VM自身资源瓶颈。
- 清理不必要的网络中间件:关闭VM上无关的代理、防火墙规则,避免额外的延迟损耗。
4. 优化Firestore客户端配置
- 使用最新版本的
firebase-admin库,新版本包含网络连接优化。 - 启用连接池复用,减少TCP握手延迟:
const db = admin.firestore({ poolSize: 15, // 增加连接池大小 keepAlive: true }); - 采用批量操作:合并多个读写请求为批量操作,减少网络往返次数。
5. 配置Firestore区域副本(可选)
若无法迁移VM到Firestore主区域,可创建Firestore区域副本,让VM访问就近的副本节点,降低跨区域延迟。
内容的提问来源于stack exchange,提问作者Amit Yadav
相关产品推荐
相关产品推荐

