DashScopeRateLimiter.java 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package com.pharmacopoeia.service;
  2. import com.pharmacopoeia.config.DashScopeRateLimitProperties;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.stereotype.Service;
  6. import java.time.LocalDate;
  7. import java.util.concurrent.atomic.AtomicInteger;
  8. /**
  9. * 百炼 API 全局调用限流器(内存计数,重启清零)。
  10. * 控制后端 → 百炼的总调用量,与用户侧限流独立。
  11. */
  12. @Service
  13. public class DashScopeRateLimiter {
  14. private static final Logger log = LoggerFactory.getLogger(DashScopeRateLimiter.class);
  15. private final DashScopeRateLimitProperties props;
  16. private final AtomicInteger minuteCount = new AtomicInteger(0);
  17. private final AtomicInteger hourCount = new AtomicInteger(0);
  18. private final AtomicInteger dayCount = new AtomicInteger(0);
  19. private volatile String currentDate = LocalDate.now().toString();
  20. private volatile int currentHour = java.time.LocalTime.now().getHour();
  21. public DashScopeRateLimiter(DashScopeRateLimitProperties props) {
  22. this.props = props;
  23. }
  24. /** 尝试获取一次调用许可。返回 true 表示放行,false 表示超限。 */
  25. public boolean tryAcquire() {
  26. if (!props.isEnabled()) return true;
  27. resetIfNeeded();
  28. if (props.getPerMinute() > 0 && minuteCount.incrementAndGet() > props.getPerMinute()) {
  29. log.warn("百炼 API 每分钟限流触发: {}/{}", minuteCount.get(), props.getPerMinute());
  30. return false;
  31. }
  32. if (props.getPerHour() > 0 && hourCount.incrementAndGet() > props.getPerHour()) {
  33. log.warn("百炼 API 每小时限流触发: {}/{}", hourCount.get(), props.getPerHour());
  34. return false;
  35. }
  36. if (props.getPerDay() > 0 && dayCount.incrementAndGet() > props.getPerDay()) {
  37. log.warn("百炼 API 每日限流触发: {}/{}", dayCount.get(), props.getPerDay());
  38. return false;
  39. }
  40. return true;
  41. }
  42. private void resetIfNeeded() {
  43. String today = LocalDate.now().toString();
  44. int nowHour = java.time.LocalTime.now().getHour();
  45. if (!currentDate.equals(today)) {
  46. dayCount.set(0);
  47. currentDate = today;
  48. }
  49. if (currentHour != nowHour) {
  50. hourCount.set(0);
  51. currentHour = nowHour;
  52. }
  53. }
  54. }