8 changed files with 159 additions and 13 deletions
@ -0,0 +1,53 @@ |
|||
package com.project.interaction.utils; |
|||
|
|||
import com.github.tingyugetc520.ali.dingtalk.api.DtService; |
|||
import com.github.tingyugetc520.ali.dingtalk.bean.message.DtCorpConversationMessage; |
|||
import com.github.tingyugetc520.ali.dingtalk.bean.message.DtCorpConversationMsgSendResult; |
|||
import com.github.tingyugetc520.ali.dingtalk.bean.message.DtMessage; |
|||
import com.google.common.collect.Lists; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.ArrayList; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class NotifyUtil { |
|||
|
|||
@Autowired |
|||
private DtService dtService; |
|||
|
|||
public void notify(Long taskId,Long clusterId) { |
|||
// "283712335120874575", "01231011386731976125",
|
|||
ArrayList<String> userIDList = Lists.newArrayList( "283712335120874575", "01231011386731976125","590204300932000212"); |
|||
|
|||
try { |
|||
String markdown = String.format("### 【告警】算法生题API调用失败通知 \n\n") + |
|||
String.format("## 核心信息\n") + |
|||
String.format("- 考试任务ID:%d\n", taskId) + |
|||
String.format("- 知识点簇ID:%d\n\n", clusterId) + |
|||
String.format("## 异常说明\n") + |
|||
String.format("算法服务生成题目时调用失败,可能导致考试题目不完整或无法正常作答,请尽快排查以下问题:\n") + |
|||
String.format("- 算法服务是否正常运行\n"); |
|||
DtCorpConversationMessage corpConversationMessage = DtCorpConversationMessage.builder() |
|||
.agentId(dtService.getDtConfigStorage().getAgentId()) |
|||
.userIds(Lists.newArrayList(userIDList)) |
|||
.msg(DtMessage.MARKDOWN() |
|||
.content("算法生题API调用失败通知") |
|||
.text(markdown) |
|||
.build()) |
|||
.build(); |
|||
DtCorpConversationMsgSendResult result = dtService.getCorpConversationMsgService().send(corpConversationMessage); |
|||
if (result.getErrCode() == 0) { |
|||
log.info(">>> [算法生题API调用失败通知] 成功发送通知 ,考试任务ID:{} ,知识点簇ID:{}", taskId, clusterId); |
|||
} else { |
|||
log.error(">>> [算法生题API调用失败通知] 发送失败.考试任务ID:{} ,知识点簇ID:{}, 错误码: {}, 错误信息: {}", taskId, clusterId, |
|||
result.getErrCode(), result.getErrMsg()); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
log.error(">>> [算法生题API调用失败通知] 钉钉接口调用异常, 考试任务ID:{} ,知识点簇ID:{}, 原因: {}",taskId, clusterId, e.getMessage()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.project.question.config; |
|||
|
|||
import com.project.question.domain.service.impl.QuestionGenerationRateLimiter; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
/** |
|||
* 题目生成相关配置 |
|||
*/ |
|||
@Configuration |
|||
public class QuestionGenerationConfig { |
|||
|
|||
@Value("${question.generation.rate-limit:5}") |
|||
private double rateLimit; |
|||
|
|||
/** |
|||
* 创建题目生成限流器 |
|||
*/ |
|||
@Bean |
|||
@ConditionalOnMissingBean(QuestionGenerationRateLimiter.class) |
|||
public QuestionGenerationRateLimiter questionGenerationRateLimiter() { |
|||
return new QuestionGenerationRateLimiter(this.rateLimit); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,36 @@ |
|||
package com.project.question.domain.service.impl; |
|||
|
|||
import com.google.common.util.concurrent.RateLimiter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
/** |
|||
* 题目生成API限流器 |
|||
* 用于控制调用算法服务的请求速率,防止一大批请求同时涌入导致服务压力过大 |
|||
*/ |
|||
@Component |
|||
@Slf4j |
|||
public class QuestionGenerationRateLimiter { |
|||
|
|||
/** |
|||
* RateLimiter 使用令牌桶算法 |
|||
* 每秒允许固定数量的请求通过 |
|||
*/ |
|||
private final RateLimiter rateLimiter; |
|||
|
|||
public QuestionGenerationRateLimiter(@Value("${question.generation.rate-limit:5}") double permitsPerSecond) { |
|||
this.rateLimiter = RateLimiter.create(permitsPerSecond); |
|||
log.info(">>> [限流器初始化] 题目生成限流速率设置为: {}/秒", permitsPerSecond); |
|||
} |
|||
|
|||
/** |
|||
* 获取令牌,如果令牌不足则阻塞等待 |
|||
* 调用此方法的线程会被阻塞,直到获取到令牌为止 |
|||
*/ |
|||
public void acquire() { |
|||
rateLimiter.acquire(); |
|||
} |
|||
|
|||
} |
|||
|
|||
Loading…
Reference in new issue