Delivery Service
This article describes the fourth step in the process of extracting the Delivery Service
from the FTGO application
monolith.
The previous articles are as follows:
Delivery Service
After step 3, the Delivery Service
is deployed but unused.
The fourth step is to route production traffic to the Delivery Service
.
First, we must change the FTGO application
’s order management logic to invoke the service to schedule, and cancel deliveries.
This is accomplished by defining a DeliveryServiceProxy
class, which implements the DeliveryService
, and sends command messages to the Delivery Service.
Second, we must route some requests from the courier’s mobile application to the Delivery Service
instead of the FTGO application
This is accomplished by introducing an API gateway
that routes requests to either the FTGO application
or the Delivery Service
.
The following diagram shows the revised architecture.
The following diagram shows the new module structure:
There are two new modules:
ftgo-api-gateway
- implements the API Gatewayftgo-delivery-service-proxy
- contains the DeliveryServiceProxy
classLets look at each of the changes starting with the DeliveryServiceProxy
class.
DeliveryServiceProxy
classThe FTGO application’s order management logic invokes delivery management via the DeliveryService
interface.
The DeliveryServiceProxy
class, which is in the ftgo-delivery-service-proxy
module, implements that interface by sending command messages to the Delivery Service
using the Eventuate Tram Command API:
public class DeliveryServiceProxy implements DeliveryService {
@Override
public void scheduleDelivery(LocalDateTime readyBy, Long orderId, long restaurantId, Address deliveryAddress) {
String commandId = commandProducer.send(DeliveryServiceChannels.DELIVERY_SERVICE_CHANNEL,
new ScheduleDelivery(readyBy, orderId, restaurantId, deliveryAddress),
"Dont_Care",
Collections.emptyMap());
}
...
Let’s now look at how the @Bean
for the DeliveryServiceProxy
is configured.
We could simply define an @Bean
for the DeliveryServiceProxy
in one of the FTGO application
’s @Configuration
classes.
However, when extracting functionality into a service, it’s often useful to be able to switch back to the old implementation when unexpected errors occur.
In this particular example, we can use the Spring framework’s profile mechanism to implement a feature flag for toggling between the old and new implementations of delivery management.
There are two @Configuration
classes in the ftgo-delivery-service-proxy
module
The first configures the FTGO application
to use the DeliveryServiceProxy
.
It’s only enabled when the RemoteDeliveryService
profile is active.
@Configuration
@Import(TramCommandProducerConfiguration.class)
@Profile("RemoteDeliveryService")
public class DeliveryServiceRemoteConfiguration {
@Bean
public DeliveryService deliveryServiceProxy(CommandProducer commandProducer) {
return new DeliveryServiceProxy(commandProducer);
}
}
The second @Configuration
configures the FTGO application
to use the existing embedded delivery management logic.
It’s enabled when the RemoteDeliveryService
profile is not active.
@Configuration
@Import(DeliveryServiceWebConfiguration.class)
@Profile("!RemoteDeliveryService")
public class DeliveryServiceEmbeddedConfiguration {
}
Both @Configuration
classes are @Import
ed by FtgoApplicationMain
:
@Configuration
@EnableAutoConfiguration
@Import({
...
DeliveryServiceEmbeddedConfiguration.class,
DeliveryServiceRemoteConfiguration.class,
...
})
public class FtgoApplicationMain {
...
With these two @Configuration
classes defined, the FTGO application
will only use the Delivery Service
when the RemoteDeliveryService
profile is active.
We can, for example, activate the profile using -Dspring.profiles.active=RemoteDeliveryService
on the command line or by setting the SPRING_PROFILES_ACTIVE=RemoteDeliveryService
environment variable.
The API gateway
, which is implemented by the ftgo-api-gateway
module, routes requests to either the Delivery Service
or the FTGO application
.
Specifically, it routes all requests to the FTGO application
except for those handled by the Delivery Service
’s DeliveryController
.
The API gateway
is built using Spring Cloud API Gateway.
The ApiGatewayConfiguration
@Configuration
class defines a RouteLocator
@Bean
, which configures the routes.
@Configuration
@EnableConfigurationProperties({ApiGatewayDestinations.class})
public class ApiGatewayConfiguration {
@Bean
public RouteLocator routing(RouteLocatorBuilder builder, ApiGatewayDestinations apiGatewayDestinations) {
return builder.routes()
// route to Delivery Service - DeliveryController
.route(r -> r.path("/couriers/**/availability").uri(apiGatewayDestinations.getDeliveryServiceUrl()))
.route(r -> r.path("/orders/**/pickedup").uri(apiGatewayDestinations.getDeliveryServiceUrl()))
.route(r -> r.path("/orders/**/delivered").uri(apiGatewayDestinations.getDeliveryServiceUrl()))
// everything else goes to monolith
.route(r -> r.path("/**").uri(apiGatewayDestinations.getFtgoApplicationUrl()))
.build();
}
}
Because the FTGO application
can either use the old, embedded delivery management logic or the new Delivery Service
, there are two versions of the end to end tests.
monolith (./build-and-test-ftgo-monolith.sh) - deploys the FTGO application
along with the necessary infrastructure services and tests the monolith’s REST API.
microservices (./build-and-test-ftgo-microservices.sh) - deploys the FTGO application
, Delivery Service
and API Gateway
and make HTTP requests to the API Gateway.
These changes are in the extract-delivery-service-04-use-service
branch and consist of a single commit
Microservices.io is brought to you by Chris Richardson. Experienced software architect, author of POJOs in Action, the creator of the original CloudFoundry.com, and the author of Microservices patterns.
Chris helps clients around the world adopt the microservice architecture through consulting engagements, and training workshops.
Got a specific microservice architecture-related question? For example:
Consider signing up for a two hour, highly focussed, consulting session.
My virtual bootcamp, distributed data patterns in a microservice architecture, is now open for enrollment!
It covers the key distributed data management patterns including Saga, API Composition, and CQRS.
It consists of video lectures, code labs, and a weekly ask-me-anything video conference repeated in multiple timezones.
The regular price is $395/person but use coupon KGBJMRAM to sign up for $195 (valid until March 8th, 2023). There are deeper discounts for buying multiple seats.
Take a look at my Manning LiveProject that teaches you how to develop a service template and microservice chassis.
Chris offers numerous resources for learning the microservice architecture.
Chris teaches comprehensive workshops, training classes and bootcamps for executives, architects and developers to help your organization use microservices effectively.
Avoid the pitfalls of adopting microservices and learn essential topics, such as service decomposition and design and how to refactor a monolith to microservices.
Delivered in-person and remotely.
Want to see an example? Check out Chris Richardson's example applications. See code
Engage Chris to create a microservices adoption roadmap and help you define your microservice architecture,
Use the Eventuate.io platform to tackle distributed data management challenges in your microservices architecture.
Eventuate is Chris's latest startup. It makes it easy to use the Saga pattern to manage transactions and the CQRS pattern to implement queries.
Engage Chris to conduct an architectural assessment.
Note: tagging is work-in-process
anti-patterns · application api · application architecture · architecting · architecture documentation · assemblage · dark energy and dark matter · deployment · design-time coupling · development · devops · docker · glossary · hexagonal architecture · implementing commands · implementing queries · inter-service communication · loose coupling · microservice architecture · microservice chassis · microservices adoption · microservicesio updates · multi-architecture docker images · observability · pattern · refactoring to microservices · resilience · sagas · security · service api · service collaboration · service design · service discovery · service granularity · service template · software delivery metrics · success triangle · team topologies · transaction management · transactional messaging