【issues/9871】AI聊天助手访问限流配置统一到ai-chat,空或非正数时关闭对应限流

This commit is contained in:
zhangdaiscott 2026-09-01 10:15:09 +08:00
parent 45f7be38d5
commit 169872c4b4
11 changed files with 121 additions and 83 deletions

View File

@ -49,6 +49,29 @@ public class AiChatConfig {
*/
private ModelConfig aiModelEmbed = new ModelConfig();
/**
* AI 聊天助手访问限流配置
*/
private RateLimitConfig rateLimit = new RateLimitConfig();
/**
* AI 聊天助手访问限流参数
*
* @author scott
* @since 2026-09-01 issues/9871 AI聊天助手访问限流配置优化
*/
@Data
public static class RateLimitConfig {
/** 每会话每分钟最多发送消息次数,为空或小于等于 0 时不限制 */
private Integer sendPerSessionPerMinute;
/** 每 IP 每分钟最多发送消息次数,为空或小于等于 0 时不限制 */
private Integer sendPerIpPerMinute;
/** 每会话每小时最多上传文件次数,为空或小于等于 0 时不限制 */
private Integer uploadPerSessionPerHour;
}
@Data
public static class ModelConfig {
/**
@ -102,4 +125,4 @@ public class AiChatConfig {
private double volume = 0.0;
}
}
}

View File

@ -3,8 +3,7 @@ package org.jeecg.modules.airag.app.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.IpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.jeecg.config.AiChatConfig;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@ -22,30 +21,25 @@ import java.util.concurrent.TimeUnit;
@Service
public class AiragChatRateLimitService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 每会话每分钟最多发送消息次数
*/
@Value("${jeecg.airag.rate-limit.send-per-session-per-minute:20}")
private int sendPerSessionPerMinute;
/**
* IP 每分钟最多发送消息次数
*/
@Value("${jeecg.airag.rate-limit.send-per-ip-per-minute:60}")
private int sendPerIpPerMinute;
/**
* 每会话每小时最多上传文件次数
*/
@Value("${jeecg.airag.rate-limit.upload-per-session-per-hour:20}")
private int uploadPerSessionPerHour;
private final RedisTemplate redisTemplate;
private final AiChatConfig.RateLimitConfig rateLimit;
private static final DateTimeFormatter MINUTE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
private static final DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHH");
/**
* 构造 AI 聊天助手访问限流服务
*
* @param redisTemplate Redis 操作模板
* @param aiChatConfig AI 聊天配置
* @author scott
* @since 2026-09-01 issues/9871 AI聊天助手访问限流配置优化
*/
public AiragChatRateLimitService(RedisTemplate redisTemplate, AiChatConfig aiChatConfig) {
this.redisTemplate = redisTemplate;
this.rateLimit = aiChatConfig.getRateLimit();
}
/**
* 校验 /airag/chat/send 调用频次
*
@ -56,9 +50,9 @@ public class AiragChatRateLimitService {
String clientIp = IpUtils.getIpAddr(request);
String minute = LocalDateTime.now().format(MINUTE_FORMAT);
checkLimit("airag:rate:send:session:" + sessionId + ":" + minute, sendPerSessionPerMinute, 120,
checkLimit("airag:rate:send:session:" + sessionId + ":" + minute, rateLimit.getSendPerSessionPerMinute(), 120,
"发送消息过于频繁,请稍后再试");
checkLimit("airag:rate:send:ip:" + clientIp + ":" + minute, sendPerIpPerMinute, 120,
checkLimit("airag:rate:send:ip:" + clientIp + ":" + minute, rateLimit.getSendPerIpPerMinute(), 120,
"发送消息过于频繁,请稍后再试");
}
@ -72,9 +66,9 @@ public class AiragChatRateLimitService {
String clientIp = IpUtils.getIpAddr(request);
String hour = LocalDateTime.now().format(HOUR_FORMAT);
checkLimit("airag:rate:upload:session:" + sessionId + ":" + hour, uploadPerSessionPerHour, 7200,
checkLimit("airag:rate:upload:session:" + sessionId + ":" + hour, rateLimit.getUploadPerSessionPerHour(), 7200,
"上传文件过于频繁,请稍后再试");
checkLimit("airag:rate:upload:ip:" + clientIp + ":" + hour, uploadPerSessionPerHour, 7200,
checkLimit("airag:rate:upload:ip:" + clientIp + ":" + hour, rateLimit.getUploadPerSessionPerHour(), 7200,
"上传文件过于频繁,请稍后再试");
}
@ -85,7 +79,10 @@ public class AiragChatRateLimitService {
* @param limit 窗口上限
* @param expireSeconds key 过期时间
*/
private void checkLimit(String key, int limit, int expireSeconds, String errorMessage) {
private void checkLimit(String key, Integer limit, int expireSeconds, String errorMessage) {
if (limit == null || limit <= 0) {
return;
}
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == null) {
return;

View File

@ -190,6 +190,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -254,15 +262,6 @@ jeecg:
# Unipush配置 云函数调用 URL 化地址
unicloud:
pushUrl:
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -166,6 +166,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -225,15 +233,6 @@ jeecg:
endpoint: https://api.search.brave.com/res/v1/web/search
count: 10
timeout: 15
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -188,6 +188,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -377,4 +385,4 @@ justauth:
cache:
type: default
prefix: 'demo::'
timeout: 1h
timeout: 1h

View File

@ -183,6 +183,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -245,15 +253,6 @@ jeecg:
# Unipush配置 云函数调用 URL 化地址
unicloud:
pushUrl:
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -180,6 +180,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -239,15 +247,6 @@ jeecg:
endpoint: https://api.search.brave.com/res/v1/web/search
count: 10
timeout: 15
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -193,6 +193,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -252,15 +260,6 @@ jeecg:
endpoint: https://api.search.brave.com/res/v1/web/search
count: 10
timeout: 15
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -186,6 +186,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN

View File

@ -175,6 +175,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN
@ -234,15 +242,6 @@ jeecg:
endpoint: https://api.search.brave.com/res/v1/web/search
count: 10
timeout: 15
airag:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# 平台上线安全配置
firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填)

View File

@ -190,6 +190,14 @@ jeecg:
timeout: 60
skills-dir:
skills-shell-dir:
# AI聊天助手访问限流配置
rate-limit:
# 单 session 每分钟上限
send-per-session-per-minute: 10
# 单 IP 每分钟上限
send-per-ip-per-minute: 20
# 单 session 每小时上限
upload-per-session-per-hour: 20
# AI文生图绘画
ai-model-draw:
# 提供商 OPENAI/ZHIPU/QWEN