Asynchronous programming is not a new pattern for Enterprise developers. However, when used in combination with the BulkHead policy, you can achieve a powerful fault tolerance pattern for your microservices. In a nutshell, if you annotate a method with @Asynchronous, it will be executed asynchronously on a separate thread.
In the following example, we are performing some logic in the createOrder method, which spins off some debugging in a separate thread by means of the writeSomeLogging method, which returns a CompletableFuture instance:
public void createOrder(Orders order, Customer c) {
order.setCustomer(c);
entityManager.persist(order);
writeSomeLogging(order.getItem());
}
@Asynchronous
private Future writeSomeLogging(String item) {
LOGGER.info("New Customer order at: "+new java.util.Date());
LOGGER.info("Item: {}", item);
return CompletableFuture.completedFuture("ok");
}
When @Bulkhead is used with @Asynchronous, the thread pool isolation approach will be used. The thread pool approach allows us to configure the maximum concurrent requests together with a certain queue size, just like a semaphore. Here is the updated example, which includes the @Bulkhead policy:
// maximum 5 concurrent requests allowed, maximum 10 requests allowed in the waiting queue
@Asynchronous
@Bulkhead(value = 5, waitingTaskQueue = 10)
private Future writeSomeLogging(String item) {
LOGGER.info("New Customer order at: "+new java.util.Date());
LOGGER.info("Item: {}", item);
return CompletableFuture.completedFuture("ok");
}
That was a whirlwind tour of the fault tolerance policies that are available in the MicroProfile API. Let's move on to the next section, which is about capturing service metrics.