【发布时间】:2020-07-11 21:48:09
【问题描述】:
我们有一个 Spring Boot 应用程序,它链接到现场的各种客户端。 此应用程序有一个控制器,该控制器从客户端调用并与数据库和物理开关交互,以关闭或打开灯。
当两个或多个客户端访问服务器上的 API 时,就会出现问题,因为该方法会检查灯是打开还是关闭(在 DB 上)以更改其状态。出现这种情况,如果灯灭了,有2个客户端同时调用服务,第一个打开灯并改变db上的状态,但第二个也访问灯,db上的状态是off,但第一个客户端已经打开了灯,所以秒最终关闭它想打开它......也许我的解释有点不清楚,问题是:我可以告诉spring当时访问控制器一个请求吗?
感谢下面的回答,我们在切换开关的方法上引入了悲观锁定,但我们仍然有来自客户的 200 状态...
我们使用的是spring boot + hibernate
现在控制器有悲观锁的例外
try {
String pinName = interruttore.getPinName();
// logger.debug("Sono nel nuovo ciclo di
// gestione interruttore");
if (!interruttore.isStato()) { // solo se
// l'interruttore
// è
// spento
GpioPinDigitalOutput relePin = interruttore.getGpio()
.provisionDigitalOutputPin(RaspiPin.getPinByName(pinName));
interruttoreService.toggleSwitchNew(relePin, interruttore, lit); // accendo
interruttore.getGpio().unprovisionPin(relePin);
}
} catch (GpioPinExistsException ge) {
logger.error("Gpio già esistente");
} catch (PessimisticLockingFailureException pe){
logger.error("Pessimistic Lock conflict", pe);
return new ResponseEntity<Sensoristica>(sensoristica, HttpStatus.CONFLICT);
}
toggleSwitchNew如下
@Override
@Transactional(isolation=Isolation.REPEATABLE_READ)
public void toggleSwitchNew(GpioPinDigitalOutput relePin, Interruttore interruttore, boolean on) {
Date date = new Date();
interruttore.setDateTime(new Timestamp(date.getTime()));
interruttore.setStato(on);
String log = getLogStatus(on) + interruttore.getNomeInterruttore();
logger.debug(log);
relePin.high();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
logger.error("Errore sleep ", e);
}
relePin.low();
updateInterruttore(interruttore);
illuminazioneService.createIlluminazione(interruttore, on);
}
然后我们在客户端中记录请求状态码,即使它们是并发的,它们总是得到 200
【问题讨论】: