如何在Spring中避免异步并行处理,或者如何调度web请求



给出以下代码,该代码在Spring Boot中以JSON形式接收带有web商店订单的请求。订单应移交给处理订单的方法processJsonOrder。在移交之后,web服务应该返回OK给客户端。processJsonOrder中的处理应该是异步的,不能阻塞返回到客户端。

@RestController
public class WebShopOrderController {
@Autowired
private OrderService orderService;
@PostMapping(value = "/wc-order")
public void getWcOrder(@RequestBody String jsonOrder, @RequestHeader Map<String, String> headers) {
log.info("order received");

// should be done async
processJsonOrder(jsonOrder);
return;
}
}

但是在processJsonOrder中处理的jsonOrder需要逐一处理。也许是通过队列,或者在Spring中有一个很好的解决方案。这个想法是当在processJsonOrder中执行订单时,jsonOrders正在等待。目前,当两个订单更新在几秒钟内到达时,由于处理jsonOrder的线程还没有到达提交点,因此processJsonOrder会将订单插入数据库两次。在orderService中有一些代码来检查数据库级别的重复,但这并不总是有帮助。

OrderService.java

@Service
public class OrderService {

@Async
@Transactional
public void processJsonOrder(WoocommerceOrder wcOrder) {
// performing business logic
}
}

我希望有一个优雅的解决方案,或者也许做processJson顺序异步是错误的方法。重要的是,调用客户端立即得到应答,但随后异步处理订单,但是一个接一个。

您试图对代码做的事情称为达到互斥以避免竞争条件-两个或多个进程或线程同时到达代码的关键段并试图读取和/或更新相同的数据块,这可能会导致错误或错误。在java中,有一个内置的特性来避免这种问题:synchronized关键字。

首先,在控制器上配置线程:

@RestController
public class WebShopOrderController {
@Autowired
private OrderService orderService;
@PostMapping(value = "/wc-order")
public void getWcOrder(@RequestBody String jsonOrder, @RequestHeader Map<String, String> headers) {
log.info("order received");
// Will be done async
new Thread(() -> processJsonOrder(jsonOrder)).start();
return;
}
}

然后,只需在@Service方法上使用synchronized关键字:

@Service
public class OrderService {

@Transactional
public synchronized void processJsonOrder(WoocommerceOrder wcOrder) {
// Only one Thread at a time will be allowed to enter this area.
// performing business logic
}
}

最新更新