List of Figures
Chapter 1. Welcome to the cloud, Spring
Figure 1.1. Monolithic applications force multiple development teams to artificially synchronize their delivery because their
code needs to be built, tested, and deployed as an entire unit.
Figure 1.2. Using a microservice architecture our CRM application would be decomposed into a set of microservices completely
independent of each other, allowing each development team to move at their own pace.
Figure 1.3. Spring Boot abstracts away the common REST microservice task (routing to business logic, parsing HTTP parameters
from the URL, mapping JSON to/from Java Objects), and lets the developer focus on the business logic for the service.
Figure 1.4. Your Spring Boot service will communicate the endpoints exposed and the port of the service via the console.
Figure 1.5. The response from the /hello endpoint shows the data you’ve requested represented as a JSON payload.
Figure 1.6. The different cloud computing models come down to who’s responsible for what: the cloud vendor or you.
Figure 1.7. Microservices are more than the business logic. You need to think about the environment where the services are
going to run and how the services will scale and be resilient.
Figure 1.8. When designing your microservice, you have to think about how the service will be consumed and communicated with.
Figure 1.9. Service discovery and routing are key parts of any large-scale microservice application.
Figure 1.10. With microservices, you must protect the service caller from a poorly behaving service. Remember, a slow or down
service can cause disruptions beyond the immediate service.
Figure 1.11. Using a token-based security scheme, you can implement service authentication and authorization without passing
around client credentials.
Figure 1.12. A well-thought-out logging and tracing strategy makes debugging transactions across multiple services manageable.
Figure 1.13. You want the deployment of the microservice and the server it’s running on to be one atomic artifact that’s deployed
as a whole between environments.
Figure 1.14. You can map the technologies you’re going to use directly to the microservice patterns we’ve explored so far
in this chapter.
Chapter 2. Building microservices with Spring Boot
Figure 2.1. Interview the EagleEye users, and understand how they do their day-to-day work.
Figure 2.2. A simplified EagleEye data model
Figure 2.3. You use the data model as the basis for decomposing a monolithic application into microservices.
Figure 2.4. The licensing service starting successfully
Figure 2.5. Your licensing service being called with POSTMAN
Figure 2.6. When a microservice starts up, it goes through multiple steps in its lifecycle.
Figure 2.7. In the Service Assembly step, source code is compiled and packaged with its runtime engine.
Figure 2.8. As a service starts (boot straps), its reads its configuration from a central repository.
Figure 2.9. A service discovery agent abstracts away the physical location of a service.
Figure 2.10. The service discovery agent uses the exposes health URL to check microservice health.
Figure 2.11. A health check on each service instance allows monitoring tools to determine if the service instance is running.
Chapter 3. Controlling your configuration with Spring Cloud configuration server
Figure 3.1. The application configuration data is read during the service bootstrapping phase.
Figure 3.2. Configuration management conceptual architecture
Figure 3.3. Spring Cloud configuration exposes environment-specific properties as HTTP-based endpoints.
Figure 3.4. Retrieving default configuration information for the licensing service
Figure 3.5. Retrieving configuration information for the licensing service using the dev profile
Figure 3.6. Retrieving configuration information using the dev profile
Figure 3.7. The configuration the licensing service loads can be checked by calling the /env endpoint.
Figure 3.8. Using the /encrypt endpoint you can encrypt values.
Figure 3.9. While the spring.datasource.password is encrypted in the property file, it’s decrypted when the configuration
for the licensing service is retrieved. This is still problematic.
Figure 3.10. With client-side decryption turned on, sensitive properties will no longer be returned in plain text from the
Spring Cloud Config REST call. Instead, the property will be decrypted by the calling service when it loads its properties
from Spring Cloud Config.
Chapter 4. On service discovery
Figure 4.1. A traditional service location resolution model using DNS and a load balancer
Figure 4.2. As service instances are added/removed, they will update the service discovery agent and become available to process
user requests.
Figure 4.3. Client-side load balancing caches the location of the services so that the service client doesn’t have to contact
service discovery on every call.
Figure 4.4. By implementing client-side caching and Eureka with the licensing and organization services, you can lessen the
load on the Eureka servers and improve client stability if Eureka becomes unavailable.
Figure 4.5. Calling the Eureka REST API to see the organization will show the IP address of the service instances registered
in Eureka, along with the service status.
Figure 4.6. Calling the Eureka REST API with the results being JSON
Chapter 5. When bad things happen: client resiliency patterns with Spring Cloud and Netflix Hystrix
Figure 5.1. The four client resiliency patterns act as a protective buffer between a service consumer and the service.
Figure 5.2. An application is a graph of interconnected dependencies. If you don’t manage the remote calls between these,
one poorly behaving remote resource can bring down all the services in the graph.
Figure 5.3. The circuit breaker trips and allows a misbehaving service call to fail quickly and gracefully.
Figure 5.4. Hystrix sits between each remote resource call and protects the client. It doesn’t matter if the remote resource
call is a database call or a REST-based service call.
Figure 5.5. A HystrixRuntimeException is thrown when a remote call takes too long.
Figure 5.6. Your service invocation using a Hystrix fallback
Figure 5.7. Default Hystrix thread pool shared across multiple resource types
Figure 5.8. Hystrix command tied to segregated thread pools
Figure 5.9. Hystrix goes through a series of checks to determine whether or not to trip the circuit breaker.
Figure 5.10. Adding a correlation ID to the licensing service call’s HTTP header
Chapter 6. Service routing with Spring Cloud and Zuul
Figure 6.1. Without a services gateway, the service client will call distinct endpoints for each service.
Figure 6.2. The service gateway sits between the service client and the corresponding service instances. All service calls
(both internal-facing and external) should flow through the service gateway.
Figure 6.3. Zuul will use the organizationservice application name to map requests to organization service instances.
Figure 6.4. Each service that’s mapped in Eureka will now be mapped as a Zuul route.
Figure 6.5. The results of the Zuul /routes call with a manual mapping of the organization service
Figure 6.6. Only one organization service is now defined in Zuul.
Figure 6.7. Using a prefix, Zuul will map a /api prefix to every service it manages.
Figure 6.8. Your routes in Zuul now have an /api prefix.
Figure 6.9. You’ve now mapped a static route to your licensing service.
Figure 6.10. You now see that the /api/licensestatic now maps to a service ID called licensestatic
Figure 6.11. The pre-, route, and post filters form a pipeline in which a client request flows through. As a request comes
into Zuul, these filters can manipulate the incoming request.
Figure 6.12. Zuul filters provide centralized tracking of service calls, logging, and dynamic routing. Zuul filters allows
you to enforce custom rules and policies against microservice calls.
Figure 6.13. A set of common classes are used so that the correlation ID can be propagated to downstream service calls.
Figure 6.14. The tmx-correlation-id has been added to the response headers sent back to the service client.
Figure 6.15. The flow of a call to the organization service through the SpecialRoutesFilter
Figure 6.16. When you hit the alternative organization service, you see NEW prepended to the contactName.
Chapter 7. Securing your microservices
Figure 7.1. OAuth2 allows a user to authenticate without constantly having to present credentials.
Figure 7.2. Setting up basic authentication using the application key and secret
Figure 7.3. When requesting a OAuth2 token, the user’s credentials are passed in as HTTP form Parameters to the /auth/oauth/token
endpoint.
Figure 7.4. Payload returned after a successful client credential validation
Figure 7.5. Looking up user information based on the issued OAuth2 token
Figure 7.6. Trying to call the organization service will result in a failed call.
Figure 7.7. Passing in the OAuth2 access token on the call to the organization service
Figure 7.8. The OAuth2 token has to be carried throughout the entire call chain.
Figure 7.9. The access and refresh tokens from your authentication call are now JWT tokens.
Figure 7.10. Using http://jswebtoken.io allows you to decode the contents.
Figure 7.11. An example of extending the JWT token with a organizationId
Figure 7.12. The Zuul server parses out the organization ID from the JWT token as it passes through.
Figure 7.13. A microservice security architecture is more than implementing OAuth2.
Chapter 8. Event-driven architecture with Spring Cloud Stream
Figure 8.1. In a synchronous request-response model, tightly coupled services introduce complexity and brittleness.
Figure 8.2. As organization state changes, messages will be written to a message queue that sits between the two services.
Figure 8.3. As a message is published and consumed, it flows through a series of Spring Cloud Stream components that abstract
away the underlying messaging platform.
Figure 8.4. When organization service data changes it will publish a message to Kafka.
Figure 8.5. When a message comes into the Kafka orgChangeTopic, the licensing service will respond.
Figure 8.6. The consumer group guarantees a message will only be processed once by a group of service instances.
Figure 8.7. Updating the contact phone number using the organization service
Figure 8.8. The console shows the message from the organization service being sent and then received.
Chapter 9. Distributed tracing with Spring Cloud Sleuth and Zipkin
Figure 9.1. Spring Cloud Sleuth adds four pieces of tracing information to each log entry written by your service. This data
helps tie together service calls for a user’s request.
Figure 9.2. With multiple services involved in a transaction, you can see that they share the same trace ID.
Figure 9.3. The combination of aggregated logs and a unique transaction ID across service log entries makes debugging distributed
transactions more manageable.
Figure 9.4. Using native Docker capabilities, logspot, and Papertrail allows you to quickly implement a unified logging architecture.
Figure 9.5. To begin, create an account on Papertrail.
Figure 9.6. Next choose how you’re going to send log data to Papertrail.
Figure 9.7. Papertrail uses Syslog as one of the mechanisms for sending data to it.
Figure 9.8. With the Logspout Docker container defined, data written to each container’s standard out will be sent to Papertrail.
Figure 9.9. The trace ID allows you to filter all log entries related to that single transaction.
Figure 9.10. With the Spring Cloud Sleuth trace ID returned, you can easily query Papertrail for the logs.
Figure 9.11. The Zipkin query screen lets you select the service you want to trace on, along with some basic query filters.
Figure 9.12. Zipkin allows you to drill down and see the amount of time each span in a transaction takes.
Figure 9.13. Clicking on an individual span gives further details on call timing and the details of the HTTP call.
Figure 9.14. Viewing the details of a trace of how the licensing service call flows from Zuul to the licensing service and
then through to the organization service
Figure 9.15. With the trace ID returned in the HTTP Response tmx-correlation-id field you can easily find the transaction
you’re looking for.
Figure 9.16. Spring Cloud Sleuth will automatically trace the publication and receipt of messages on Spring message channels.
Figure 9.17. You’re looking for the licensing service invocation where a Kafka message is received.
Figure 9.18. Using Zipkin you can see the Kafka message being published by the organization service.
Figure 9.19. With the custom spans defined, they’ll now show up in the transaction trace.
Chapter 10. Deploying your microservices
Figure 10.1. By using Docker, all your services can be deployed to a cloud provider such as Amazon ECS.
Figure 10.2. Selecting whether the database is going to be a production database or a test database
Figure 10.3. Setting up the basic database configuration
Figure 10.4. Setting up the security group, port, and backup options for the RDS database
Figure 10.5. Your created Amazon RDS/PostgreSQL database
Figure 10.6. With a few clicks you can set up a Redis cluster whose infrastructure is managed by Amazon.
Figure 10.7. The Redis endpoint is the key piece of information your services need to connect to Redis.
Figure 10.8. ECS offers a wizard to bootstrap a new service container. You’re not going to use it.
Figure 10.9. Starting the process of creating an ECS cluster
Figure 10.10. In the “Create Cluster” screen size the EC2 instances used to host the Docker cluster.
Figure 10.11. Once the servers are set up, configure the network/AWS security groups used to access them.
Figure 10.12. Configuring the Container IAM role
Figure 10.13. The ECS cluster up and running
Figure 10.14. Checking the status of the deployed services
Figure 10.15. Each component in the build and deployment pipeline automates a task that would have been manually done.
Figure 10.16. Technologies used in the EagleEye build
Figure 10.17. The concrete steps undertaken by the .travis.yml file to build and deploy your software
Figure 10.18. Encrypted Travis environment variables are placed directly in the .travis.yml file.
Appendix A. Running a cloud on your desktop
Figure A.1. The GitHub UI allows you to download a project as a zip file.
Figure A.2. All output from the started Docker containers is written to standard out.
Appendix B. OAuth2 grant types
Figure B.1. The OAuth2 service determines if the user accessing the service is an authenticated user.
Figure B.2. The client credential grant is for “no-user-involved” application authentication and authorization.
Figure B.3. The authentication code grant allows applications to share data without exposing user credentials.
Figure B.4. The implicit grant is used in a browser-based Single-Page Application (SPA) JavaScript application.
Figure B.5. The refresh token flow allows an application to get a new access token without forcing the user to re-authenticate.