使用Node SDK调用IBM Watson NLU API遇Too Many Requests错误求解决方案
解决IBM Watson NLU调用Too Many Requests错误的方案
我来帮你搞定这个问题——你碰到的Too Many Requests错误,本质是短时间内发送的请求频率超过了NLU服务的隐性速率限制(虽然标准计划文档没明确标注,但这类云服务都会有这类防护机制)。结合你提供的代码,我给你几个可行的解决思路:
1. 改成串行请求+固定延迟(最直接的修复)
你的原代码用forEach遍历数组,并且每个请求几乎是同时发起的,20-30个请求瞬间打过去,很容易触发限流。改成串行处理,每次请求后等待一段时间再发下一个,就能避免这个问题。
调整后的代码示例:
// 先写一个简单的延迟函数 const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); // 用async/await实现串行处理 async function processSegments() { for (const segment of segmentList) { const params = { text: segment, features: { keywords: { sentiment: false }, sentiment: { document: true } } }; logger.info("Analyse Segment : " + segment); try { const analysisResult = await NLUService.analyze(params); // 在这里执行插入数据库的操作:Inserting analysisResult.sentiment.document.score to Database . . . } catch (err) { logger.error(err.stack); } // 每次请求后延迟500毫秒,可以根据实际情况调整(比如300ms、400ms) await delay(500); } } // 调用执行 processSegments();
你可以测试调整延迟时间,找到一个既不触发限流又不会太慢的平衡点。
2. 加上重试机制(应对偶尔的限流)
有时候即使加了延迟,也可能因为服务端临时负载高触发限流,这时候加上重试逻辑(配合指数退避)会更稳妥:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); // 带重试的分析函数 async function analyzeWithRetry(params, maxRetries = 3) { let retries = 0; while (retries < maxRetries) { try { return await NLUService.analyze(params); } catch (err) { if (err.message.includes("Too Many Requests") && retries < maxRetries - 1) { const waitTime = 1000 * Math.pow(2, retries); // 指数退避:1s, 2s, 4s... logger.warn(`触发限流,${waitTime}ms后重试(剩余次数:${maxRetries - retries - 1})`); await delay(waitTime); retries++; } else { throw err; } } } } // 串行处理+重试 async function processSegments() { for (const segment of segmentList) { const params = { text: segment, features: { keywords: { sentiment: false }, sentiment: { document: true } } }; logger.info("Analyse Segment : " + segment); try { const analysisResult = await analyzeWithRetry(params); // 插入数据库操作... } catch (err) { logger.error(`最终处理失败:${err.stack}`); } // 基础延迟,减少触发限流的概率 await delay(300); } } processSegments();
指数退避的好处是,随着重试次数增加,等待时间翻倍,给服务足够的恢复时间,避免反复触发限流。
3. 确认服务的实际速率限制
虽然标准计划文档没写,但你可以通过IBM Cloud控制台查看你的NLU服务实例的监控数据(比如请求次数、响应状态码),或者联系IBM支持团队确认具体的QPS限制。知道准确的限制后,你可以更精准地设置延迟时间,平衡效率和合规性。
最后提一句:你的原代码用forEach结合Promise的方式,其实并没有实现串行执行——forEach不会等待每个Promise完成,所以所有请求是同时发起的,这才是导致20-30个请求就触发限流的核心原因。改成for...of配合async/await就能解决这个并发问题。
内容的提问来源于stack exchange,提问作者Mdumanoj
相关产品推荐
相关产品推荐

