添加限流工具,修改模板onlyIf

This commit is contained in:
2025-01-23 15:10:29 +08:00
parent 1aa1ae5e2b
commit 7bd9a7507f
10 changed files with 64 additions and 32 deletions

View File

@ -3,6 +3,5 @@ package com.ycwl.basic.constant;
public class FaceConstant {
public static final String FACE_DB_NAME_PFX="face:db:";
public static final String USER_FACE_DB_NAME="userFace";
public static final String FACE_SAMPLE_URL_PFX="face:sample:url:";
public static final String FACE_USER_URL_PFX="face:user:url:";
}

View File

@ -23,4 +23,6 @@ public interface FaceSampleMapper {
int update(FaceSampleEntity faceSample);
List<FaceSampleEntity> listByIds(List<Long> list);
FaceSampleEntity getEntity(Long faceSampleId);
}

View File

@ -2,6 +2,8 @@ package com.ycwl.basic.model.pc.faceDetectLog.resp;
import lombok.Data;
import java.util.Date;
@Data
public class MatchLocalRecord {
private Long faceSampleId;
@ -9,4 +11,5 @@ public class MatchLocalRecord {
private Float score;
private Float confidence;
private String idStr;
private Date shotDate;
}

View File

@ -72,5 +72,9 @@ public class TemplateEntity {
private Integer status;
private Date createTime;
private Date updateTime;
private Integer sort;
private Integer cropEnable;
private String onlyIf;
private List<TemplateEntity> children;
}

View File

@ -83,8 +83,10 @@ public class TemplateRespVO {
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
private List<TemplateRespVO> children;
private BigDecimal price;
private BigDecimal slashPrice;
private Integer sort;
private Integer cropEnable;
private String onlyIf;
private List<TemplateRespVO> children;
}

View File

@ -0,0 +1,26 @@
package com.ycwl.basic.ratelimiter;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SlidingWindowRateLimiter {
private final Semaphore semaphore;
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
public SlidingWindowRateLimiter(int maxRequestsPerSecond) {
this.semaphore = new Semaphore(maxRequestsPerSecond);
// Schedule a task to release all permits every second
scheduler.scheduleAtFixedRate(() -> semaphore.release(maxRequestsPerSecond - semaphore.availablePermits()), 1, 1, TimeUnit.SECONDS);
}
public void allowRequest() throws InterruptedException {
semaphore.acquire();
}
public void shutdown() {
scheduler.shutdown();
}
}

View File

@ -60,4 +60,8 @@ public class FaceRepository {
redisTemplate.delete(String.format(FACE_CACHE_KEY, faceId));
redisTemplate.delete(String.format(FACE_SAMPLE_CACHE_KEY, faceId));
}
public FaceSampleEntity getFaceSample(Long faceSampleId) {
return faceSampleMapper.getEntity(faceSampleId);
}
}

View File

@ -37,6 +37,7 @@ import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.ratelimiter.SlidingWindowRateLimiter;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
@ -86,6 +87,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
private SourceMapper sourceMapper;
@Autowired
private OrderBiz orderBiz;
private SlidingWindowRateLimiter limiter = new SlidingWindowRateLimiter(5); // 阿里云人脸检索限制qps=5
private IAcsClient getClient() {
DefaultProfile profile = DefaultProfile.getProfile(
@ -180,7 +182,11 @@ public class TaskFaceServiceImpl implements TaskFaceService {
record.setIdStr(item.getExtraData());
record.setFaceSampleId(Long.parseLong(item.getExtraData()));
if (StringUtils.isNumeric(item.getDbName())) {
record.setFaceUrl(getFaceSampleUrl(record.getFaceSampleId()));
FaceSampleEntity faceSample = faceRepository.getFaceSample(record.getFaceSampleId());
if (faceSample != null) {
record.setFaceUrl(faceSample.getFaceUrl());
record.setShotDate(faceSample.getCreateAt());
}
} else {
record.setFaceUrl(getFaceUrl(record.getFaceSampleId()));
}
@ -218,7 +224,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
}
faceSampleEntity.setUpdateAt(new Date());
faceSampleMapper.update(faceSampleEntity);
addFaceSampleUrlCache(faceSampleId, faceSampleRespVO.getFaceUrl());
return respVo;
}
@ -229,6 +234,11 @@ public class TaskFaceServiceImpl implements TaskFaceService {
request.setDbName(dbName);
request.setEntityId(entityId);
IAcsClient client = getClient();
try {
limiter.allowRequest();
} catch (InterruptedException e) {
return null;
}
try {
client.getAcsResponse(request);
} catch (ClientException e) {
@ -465,30 +475,4 @@ public class TaskFaceServiceImpl implements TaskFaceService {
}
redisTemplate.opsForValue().set(FaceConstant.FACE_USER_URL_PFX + faceId, faceUrl, 3, TimeUnit.DAYS);
}
public String getFaceSampleUrl(Long faceSampleId) {
if (faceSampleId == null) {
return null;
}
if (redisTemplate.hasKey(FaceConstant.FACE_SAMPLE_URL_PFX + faceSampleId)) {
return redisTemplate.opsForValue().get(FaceConstant.FACE_SAMPLE_URL_PFX + faceSampleId);
}
FaceSampleRespVO faceSampleRespVO = faceSampleMapper.getById(faceSampleId);
if (faceSampleRespVO == null) {
return null;
}
String faceUrl = faceSampleRespVO.getFaceUrl();
if (StringUtils.isNotBlank(faceUrl)) {
addFaceSampleUrlCache(faceSampleId, faceUrl);
}
return faceUrl;
}
public void addFaceSampleUrlCache(Long faceSampleId, String faceUrl) {
if (faceSampleId == null) {
return;
}
if (StringUtils.isBlank(faceUrl)) {
return;
}
redisTemplate.opsForValue().set(FaceConstant.FACE_SAMPLE_URL_PFX + faceSampleId, faceUrl, 3, TimeUnit.DAYS);
}
}