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.