Skip to content

Commit 302a36a

Browse files
committed
perf: request limit
1 parent 918ef58 commit 302a36a

File tree

8 files changed

+47
-20
lines changed

8 files changed

+47
-20
lines changed

document/content/docs/upgrading/4-14/4143.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ description: 'FastGPT V4.14.2 更新说明'
99
1. 全局变量支持文件上传
1010
2. 知识库文件迁移至 S3(全部使用文件的地方均已迁移)
1111
3. 系统插件,插件市场中会提示是否有新版本,并提供更新按键。
12+
4. 工作流运行 QPM 限制。
1213

1314
## ⚙️ 优化
1415

document/data/doc-last-modified.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"document/content/docs/upgrading/4-14/4140.mdx": "2025-11-06T15:43:00+08:00",
118118
"document/content/docs/upgrading/4-14/4141.mdx": "2025-11-19T10:15:27+08:00",
119119
"document/content/docs/upgrading/4-14/4142.mdx": "2025-11-18T19:27:14+08:00",
120-
"document/content/docs/upgrading/4-14/4143.mdx": "2025-11-21T16:42:49+08:00",
120+
"document/content/docs/upgrading/4-14/4143.mdx": "2025-11-21T18:05:13+08:00",
121121
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00",
122122
"document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00",
123123
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",

packages/service/common/api/frequencyLimit.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
1+
/* 基于 Team 的限流 */
12
import { getGlobalRedisConnection } from '../../common/redis';
23
import { jsonRes } from '../../common/response';
34
import type { NextApiResponse } from 'next';
45

6+
export enum LimitTypeEnum {
7+
chat = 'chat'
8+
}
9+
const limitMap = {
10+
[LimitTypeEnum.chat]: {
11+
seconds: 60,
12+
limit: Number(process.env.CHAT_MAX_QPM || 5000)
13+
}
14+
};
15+
516
type FrequencyLimitOption = {
617
teamId: string;
7-
seconds: number;
8-
limit: number;
9-
keyPrefix: string;
18+
type: LimitTypeEnum;
1019
res: NextApiResponse;
1120
};
1221

13-
export const teamFrequencyLimit = async ({
14-
teamId,
15-
seconds,
16-
limit,
17-
keyPrefix,
18-
res
19-
}: FrequencyLimitOption) => {
22+
export const teamFrequencyLimit = async ({ teamId, type, res }: FrequencyLimitOption) => {
23+
const { seconds, limit } = limitMap[type];
2024
const redis = getGlobalRedisConnection();
21-
const key = `${keyPrefix}:${teamId}`;
25+
const key = `frequency:${type}:${teamId}`;
2226

2327
const result = await redis
2428
.multi()

packages/service/type/env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ declare global {
3232
PASSWORD_LOGIN_LOCK_SECONDS?: string;
3333
PASSWORD_EXPIRED_MONTH?: string;
3434
MAX_LOGIN_SESSION?: string;
35+
CHAT_MAX_QPM?: string;
3536

3637
// 安全配置
3738
// 密码登录锁定时间

projects/app/.env.template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ PASSWORD_LOGIN_LOCK_SECONDS=
9696
PASSWORD_EXPIRED_MONTH=
9797
# 最大登录客户端数量,默认为 10
9898
MAX_LOGIN_SESSION=
99+
# 工作流QPM
100+
CHAT_MAX_QPM=5000
99101

100102
# 特殊配置
101103
# 自定义跨域,不配置时,默认都允许跨域(逗号分割)

projects/app/src/pages/api/core/chat/chatTest.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
import { saveChat, updateInteractiveChat } from '@fastgpt/service/core/chat/saveChat';
5050
import { getLocale } from '@fastgpt/service/common/middle/i18n';
5151
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
52-
import { clone } from 'lodash';
52+
import { LimitTypeEnum, teamFrequencyLimit } from '@fastgpt/service/common/api/frequencyLimit';
5353

5454
export type Props = {
5555
messages: ChatCompletionMessageParam[];
@@ -93,6 +93,16 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
9393
per: ReadPermissionVal
9494
});
9595

96+
if (
97+
!(await teamFrequencyLimit({
98+
teamId,
99+
type: LimitTypeEnum.chat,
100+
res
101+
}))
102+
) {
103+
return;
104+
}
105+
96106
const isPlugin = app.type === AppTypeEnum.workflowTool;
97107
const isTool = app.type === AppTypeEnum.tool;
98108

projects/app/src/pages/api/v1/chat/completions.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ import { getWorkflowToolInputsFromStoreNodes } from '@fastgpt/global/core/app/to
6060
import { UserError } from '@fastgpt/global/common/error/utils';
6161
import { getLocale } from '@fastgpt/service/common/middle/i18n';
6262
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
63-
import { teamFrequencyLimit } from '@fastgpt/service/common/api/frequencyLimit';
64-
import { clone } from 'lodash';
63+
import { LimitTypeEnum, teamFrequencyLimit } from '@fastgpt/service/common/api/frequencyLimit';
6564

6665
type FastGptWebChatProps = {
6766
chatId?: string; // undefined: get histories from messages, '': new chat, 'xxxxx': get histories from db
@@ -190,14 +189,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
190189
if (
191190
!(await teamFrequencyLimit({
192191
teamId,
193-
keyPrefix: 'chat:completions',
194-
seconds: 60,
195-
limit: 5000,
192+
type: LimitTypeEnum.chat,
196193
res
197194
}))
198195
) {
199-
return {};
196+
return;
200197
}
198+
201199
retainDatasetCite = retainDatasetCite && !!responseDetail;
202200
const isPlugin = app.type === AppTypeEnum.workflowTool;
203201

projects/app/src/pages/api/v2/chat/completions.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import { getWorkflowToolInputsFromStoreNodes } from '@fastgpt/global/core/app/to
6161
import { UserError } from '@fastgpt/global/common/error/utils';
6262
import { getLocale } from '@fastgpt/service/common/middle/i18n';
6363
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
64-
import { clone } from 'lodash';
64+
import { LimitTypeEnum, teamFrequencyLimit } from '@fastgpt/service/common/api/frequencyLimit';
6565

6666
type FastGptWebChatProps = {
6767
chatId?: string; // undefined: get histories from messages, '': new chat, 'xxxxx': get histories from db
@@ -186,6 +186,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
186186
chatId
187187
});
188188
})();
189+
190+
if (
191+
!(await teamFrequencyLimit({
192+
teamId,
193+
type: LimitTypeEnum.chat,
194+
res
195+
}))
196+
) {
197+
return;
198+
}
199+
189200
retainDatasetCite = retainDatasetCite && !!responseDetail;
190201
const isPlugin = app.type === AppTypeEnum.workflowTool;
191202

0 commit comments

Comments
 (0)