Reader small image

You're reading from  Microservices with Spring Boot 3 and Spring Cloud, Third Edition - Third Edition

Product typeBook
Published inAug 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781805128694
Edition3rd Edition
Languages
Right arrow
Author (1)
Magnus Larsson
Magnus Larsson
author image
Magnus Larsson

Magnus Larsson, an IT industry veteran since 1986, has consulted for major Swedish firms like Volvo, Ericsson, and AstraZeneca. Despite past struggles with distributed systems, today's open-source tools like Spring Cloud, Kubernetes, and Istio offer effective solutions. For the past eight years, Magnus has been helping customers use these tools and shared insights through presentations and blog posts.
Read more about Magnus Larsson

Right arrow

Technical requirements

For instructions on how to install tools used in this book and how to access the source code for this book, see:

  • Chapter 21 for macOS
  • Chapter 22 for Windows

The code examples in this chapter all come from the source code in $BOOK_HOME/Chapter07.If you want to view the changes applied to the source code in this chapter, that is, see what it takes to make the microservices reactive, you can compare it with the source code for Chapter 6, Adding Persistence. You can use your favorite diff tool and compare the two folders, that is, $BOOK_HOME/Chapter06 and $BOOK_HOME/Chapter07.

Choosing between non-blocking synchronous APIs and event-driven asynchronous services

When developing reactive microservices, it is not always obvious when to use non-blocking synchronous APIs and when to use event-driven asynchronous services. In general, to make a microservice robust and scalable, it is important to make it as autonomous as possible, for example, by minimizing its runtime dependencies. This is also known as loose coupling. Therefore, asynchronous message passing of events is preferable over synchronous APIs. This is because the microservice will only depend on access to the messaging system at runtime, instead of being dependent on synchronous access to a number of other microservices.There are, however, a number of cases where synchronous APIs could be favorable. For example:

  • For read operations where an end user is waiting for a response
  • Where the client platforms are more suitable for consuming synchronous APIs, for example, mobile apps or SPA web applications
  • Where...

Developing non-blocking synchronous REST APIs

In this section, we will learn how to develop non-blocking versions of the read APIs. The composite service will make reactive, that is, non-blocking, calls in parallel to the three core services. When the composite service has received responses from all of the core services, it will create a composite response and send it back to the caller. This is illustrated in the following diagram:

Figure 7.2: The getCompositeProduct part of the landscape

In this section, we will cover the following:

  • An introduction to Project Reactor
  • Non-blocking persistence using Spring Data for MongoDB
  • Non-blocking REST APIs in the core services, including how to handle blocking code for the JPA-based persistence layer
  • Non-blocking REST APIs in the composite service

An introduction to Project Reactor

As we mentioned in the Spring WebFlux section in Chapter 2, Introduction to Spring Boot, the reactive support in Spring 5 is based on Project Reactor (https://projectreactor...

Developing event-driven asynchronous services

In this section, we will learn how to develop event-driven and asynchronous versions of the create and delete services. The composite service will publish create and delete events on each core service topic and then return an OK response back to the caller without waiting for processing to take place in the core services. This is illustrated in the following diagram:

Figure 7.7: The createCompositeProduct and deleteCompositeProduct parts of the landscape

We will cover the following topics:

  • Handling challenges with messaging
  • Defining topics and events
  • Changes in Gradle build files
  • Consuming events in the core services
  • Publishing events in the composite service

Handling challenges with messaging

To implement the event-driven create and delete services, we will use Spring Cloud Stream. In Chapter 2, Introduction to Spring Boot, we have already seen how easy it is to publish and consume messages on a topic using Spring Cloud Stream. The programming...

Running manual tests of the reactive microservice landscape

Now, we have fully reactive microservices, both in terms of non-blocking synchronous REST APIs and event-driven asynchronous services. Let's try them out!We will learn how to run tests using both RabbitMQ and Kafka as the message broker. Since RabbitMQ can be used both with and without partitions, we will test both cases. Three different configurations will be used, each defined in a separate Docker Compose file:

  • Using RabbitMQ without the use of partitions
  • Using RabbitMQ with two partitions per topic
  • Using Kafka with two partitions per topic

However, before testing these three configurations, we need to add two features to be able to test the asynchronous processing:

  • Saving events for later inspection when using RabbitMQ
  • A health API that can be used to monitor the state of the microservice landscape

Saving events

After running some tests on event-driven asynchronous services, it might be of interest to see what events...

Running automated tests of the reactive microservice landscape

To be able to run tests of the reactive microservice landscape automatically instead of manually, the automated test-em-all.bash test script has been enhanced. The most important changes are as follows:

  • The script uses the new health endpoint to know when the microservice landscape is operational, as shown here:
waitForService curl http://$HOST:$PORT/actuator/health
  • The script has a new waitForMessageProcessing() function, which is called after the test data is set up. Its purpose is simply to wait for the creation of the test data to be completed by the asynchronous create services.

To use the test script to automatically run the tests with RabbitMQ and Kafka, perform the following steps:

  1. Run the tests using the default Docker Compose file, that is, with RabbitMQ without partitions, with the following commands:
unset COMPOSE_FILE
./test-em-all.bash start stop
  1. Run the tests for RabbitMQ with two partitions per topic...

Summary

In this chapter, we have seen how we can develop reactive microservices!Using Spring WebFlux and Spring WebClient, we can develop non-blocking synchronous APIs that can handle incoming HTTP requests and send outgoing HTTP requests without blocking any threads. Using Spring Data's reactive support for MongoDB, we can also access MongoDB databases in a non-blocking way, that is, without blocking any threads while waiting for responses from the database. Spring WebFlux, Spring WebClient, and Spring Data rely on Project Reactor to provide their reactive and non-blocking features. When we must use blocking code, for example, when using Spring Data for JPA, we can encapsulate the processing of the blocking code by scheduling the processing of it in a dedicated thread pool.We have also seen how Spring Data Stream can be used to develop event-driven asynchronous services that work on both RabbitMQ and Kafka as messaging systems without requiring any changes in the code. By doing...

Questions

  1. Why is it important to know how to develop reactive microservices?
  2. How do you choose between non-blocking synchronous APIs and event/message-driven asynchronous services?
  3. What makes an event different from a message?
  4. Name some challenges with message-driven asynchronous services. How do we handle them?
  5. Why is the following test not failing?
@Test
void testStepVerifier() {
  StepVerifier.create(Flux.just(1, 2, 3, 4)
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .log())
    .expectNext(4, 8, 12);
}

First, ensure that the test fails. Next, correct the test so that it succeeds.

  1. What are the challenges of writing tests with reactive code using JUnit, and how can we handle them?

Summary

In this chapter, we saw how Spring Cloud has evolved from being rather Netflix OSS-centric to having a much larger scope as of today, used together with tools including Resilience4j and Micrometer Tracing. We also introduced how components from the latest release of Spring Cloud 2022 can be used to implement some of the design patterns we described in Chapter 1, Introduction to Microservices, in the Design patterns for microservices section. These design patterns are required to make a landscape of cooperating microservices production ready.

Head over to the next chapter to see how we can implement service discovery using Netflix Eureka and Spring Cloud LoadBalancer!

Questions

  1. What is the purpose of Netflix Eureka?
  2. What are the main features of Spring Cloud Gateway?
  3. What backends are supported by Spring Cloud Config?
  4. What are the capabilities that Resilience4j provides?
  5. What are the concepts of trace trees and spans used for in distributed tracing, and what is the paper called that originally defined them?
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Microservices with Spring Boot 3 and Spring Cloud, Third Edition - Third Edition
Published in: Aug 2023Publisher: PacktISBN-13: 9781805128694
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Magnus Larsson

Magnus Larsson, an IT industry veteran since 1986, has consulted for major Swedish firms like Volvo, Ericsson, and AstraZeneca. Despite past struggles with distributed systems, today's open-source tools like Spring Cloud, Kubernetes, and Istio offer effective solutions. For the past eight years, Magnus has been helping customers use these tools and shared insights through presentations and blog posts.
Read more about Magnus Larsson