我有一个 Spring Boot 项目。
想象两个 API 接受相同的对象作为输入,并用它来做不同的事情。 在执行操作之前,每个API都会验证对象,特别是有一个名为progressiveNr的数字字段,这个数字基本上用于了解特定凭证的请求进度(不详细说明,如果不清楚我会讨论它) ).
每个API都会根据优惠券检查progressiveNr是否正确,因此您不能向我发送progressiveNrs 1、2、4、3,但必须按顺序发送。
事情就是这样,客户端调用了 2 个 API,间隔几毫秒: API 1 {requestId:196,voucherId:1,progressiveNr:2},API 2 {requestId:197,voucherId:1,progressiveNr:3}。
对于 requestId 197,我们给出了错误“progressiveNr 必须为 2”。 这是因为,正是在 196 正在处理时,它仍处于验证阶段,因此尚未执行任何插入,另一个 API 是通过 197 调用的,其值为 3,然而,考虑到 196 尚未在在插入阶段,表格仍然正确地显示progressiveNr=1,因此给出了一个错误,说我期望progressiveNr=2。
在互联网上搜索我发现锁作为解决方案,但我不清楚如何应用它..
这些是控制器调用的方法
@Override
@LogExecutionTime(printArgs = true, printResponse = true)
public ResponseDTO subve(List<RequestSubveDTO> richieste) {
List<ScartoTracciatoConnexa> daScartare = new ArrayList<>();
//requests subve validation
richieste.forEach(request -> {
ScartoTracciatoConnexa sTC = validateSubve(request);
if (sTC != null) daScartare.add(sTC);
});
//do other things
//do the action
asyncService.subve(richieste, daScartare);
return new ResponseDTO(EsitiCodes.REQUEST_ACCEPTED);
}
private ScartoTracciatoConnexa validateSubve(RequestSubveDTO request) {
try {
validatorService.validateSubve(request);
} catch (InvalidRequestException e) {
return generaScarto(request, request.getNumVoucher(), SUBVE, e);
}
return null;
}
@Override
@LogExecutionTime(printArgs = true, printResponse = true)
public ResponseDTO renew(List<RequestRenewDTO> richieste) {
List<ScartoTracciatoConnexa> daScartare = new ArrayList<>();
//requests renew validation
richieste.forEach(request -> {
ScartoTracciatoConnexa sTC = validateRenew(request);
if (sTC != null) daScartare.add(sTC);
});
//do other things
//do the action
asyncService.renew(richieste, daScartare);
return new ResponseDTO(EsitiCodes.REQUEST_ACCEPTED);
}
private ScartoTracciatoConnexa validateRenew(RequestRenewDTO request) {
try {
validatorService.validateRenew(request);
} catch (InvalidRequestException e) {
return generaScarto(request, request.getNumVoucher(), RENEW, e);
}
return null;
}
这是我的验证器服务:
@LogExecutionTime
@Transactional(readOnly = true)
public void validateRenew(RequestRenewDTO dto) throws InvalidRequestException {
//Other validations
//progressiveNr validation
int lastProgNr = myObjectService.getLastProgNumByVoucherId(dto.getVoucherId()) + 1;
if (lastProgNr != dto.getProgressiveNr())
throw new InvalidRequestException();
}
//THE SAME FOR validateSubve(RequestSubveDTO dto)
有人可以帮助我吗?预先感谢!
锁和“阻塞”仅在两个服务“实际上”同时处理并持有锁时才相关。但是,如果对服务 3 的请求比服务 2 早一整秒(或 10!)到达,该怎么办?当服务 2 尚未运行时,它无法持有锁(以阻止服务 3).. “等待”更重要,所以这里相关的是什么..但是您需要问自己,服务 3 应该等待多长时间才能查看服务 2 是否完成?
如果您想让服务等待其前一个服务,那么每个服务都需要执行重新检查,以查看前一个服务是否已完成或在超时时失败。
或者,
可能是更好的解决方案,您可以在 API 中指定,在响应确认服务 2 已成功完成之前,不得发送对服务 3 的请求。