This simple project demonstrates the use of Spring Cloud Services ('SCS') in PCF using Spring Boot microservice applications.
It contains two Spring Boot microservices:
- The
cover-client
a RESTful microservice which depends on... - The
cover-service
another RESTful microservice.
Between them, these services use all three components of the Spring Cloud Services tile for Pivotal Cloud Foundry. Highlights include...
- The
cover-client
uses the Eureka (Registry) to discover thecover-service
. - The
cover-client
uses Hystrix (Service Breaker) to protect itself from the loss of thecover-service
. - The
cover-service
uses Spring Cloud Config to get the list of "insurance covers" it provides.
I assume that you have already setup PCF and the CF Cli and have the Spring Cloud Services available to you in the marketplace. If you don't have PCF or don't have the necessary Spring Cloud Services installed, try using PCF Dev but remember to start PCF Dev with Spring Cloud Services available using
cf dev start -s scs
(you'll need at least 8GB of free RAM to do this and you may have to tweak the manifest).
-
Clone this repository into a folder. Make this folder your current folder in your terminal or command line.
-
Login to PCF and check the marketplace to make sure that the Spring Cloud Services are available to you as follows...
$ cf marketplace p-circuit-breaker-dashboard standard Circuit Breaker Dashboard for Spring Cloud Applications p-config-server standard Config Server for Spring Cloud Applications p-service-registry standard Service Registry for Spring Cloud Applications
-
If the required SCS services are available in the marketplace, you can now go ahead and provision these services using the setup-services.sh script provided (windows users may need to add a non bash equivalent).
$ ./setup-services.sh
If you decide not to use the script and provision them by hand, be aware that the Config server needs a JSON file containing the location of the Git repository that holds the application configuration for the microservices.
You'll have to wait a few minutes while PCF provisions the services you've asked for. Check the status of the services periodically using the following command...
$ cf services
When the SCS services have been provisioned, your output form this command should look similar to that shown below. Note that services called
breaker
,registry
,rabbit
andconfig
have been added to your list of services in PCF.name service plan bound apps last operation breaker p-circuit-breaker-dashboard standard covers-consumer create succeeded registry p-service-registry standard covers-consumer, covers-service, create succeeded config p-config-server standard covers-service create succeeded rabbit p-rabbitmq standard covers-zipkin, covers-service... create succeeded
-
You can now build and push the demo Spring Boot microservices to PCF as follows.
$ ./gradlew clean assemble $ cf push
Both a
gradlew
command for building the microservices and amanifest.yml
describing the microservices has been provided for you.
Once the SCS services have been provisioned and the apps you build have been bound and deployed to PCF, you're ready to examine the power of their combined features with this microservice architecture.
To test the microservice apps you can use a simple curl
to send requests to the cover-client
microservice. The following command does this repeatedly every second...
$ while true; do sleep 1; curl cover-client.<your-pcf-domain-name>/mycovers; echo -e '\n'$(date); done
If you're more familiar with JMeter, you may prefer to use the JMeter project I've included in the root folder to automate the sending of these requests (but remember to reconfigure the JMeter project to use your PCF endpoint URI's).
When everything is working (i.e. when the cover-client
microservice can see and talk to the cover-service
microservice) you'll see output similar to that shown below...
No Cover, Auto Cover, Home Cover, Duvet Cover
Thu 24 Nov 2016 10:58:15 GMT
The types of insurance cover available (No Cover, Auto Cover, Home Cover, Duvet Cover) comes from a configuration property sourced from the SCS Config Service.
There is a random exception that will occasionally cause the circuit breaker to trip. When the fault occurs you'll see...
No Cover
Thu 24 Nov 2016 10:58:14 GMT
This is the cover-client
using a fallback method to provide a reduced set of covers because it thinks the cover-service
is unavailable.
-
The config of the microservices is fully externalised (12factor style) and can be refreshed at any time without having to restart the application. If the config changes in Git here, the changes can be applied while the service is still running simply by calling the
/refresh
endpoint. This endpoint is automatically added by Spring Boot.$ curl -X POST -d "" cover-service.<your-pcf-domain-name>/refresh
This is standard Spring Cloud Config functionality. What's special about this is that if you have 100 running service instances, a single POST to
/refresh
on just one of those instances is all you need to refresh the configuration for all 100 running instances without restarting. Pretty neat hah? -
The location of other services is discovered via a registry of logical names. As an example of this, the
cover-client
is using a logical name to discover a reference to thecover-service
using the registry. There are no hard-coded endpoints.URI uri = URI.create("//COVERS-SERVICE/covers");
This is standard Spring Cloud Registry functionality. What's also cool about this is that the microservices automatically register themselves with the registry when they boot. There is no complicated configuration other than the
@EnableDiscoveryClient
annotation in the application class. The registry server's contact details come from theenvironment properties
that PCF automatically provides at startup as part of the service binding. -
Service-to-service calls are resilient and have useful fallbacks that can help prevent cascading exceptions. As an example, there is a circuit breaker protecting the service calls between the
cover-client
and thecover-service
. This circuit breaker is artificially triggered from time to time in order to show the breaker in operation (as you can see if you open the code from theCoverService.java
class).@HystrixCommand(fallbackMethod = "getCoversFallbackMethod") public String getCovers() {...}
The method 'getCoversFallbackMethod()' contsins a simple fallback that returns
No Covers
public String getCoversFallbackMethod() { return "No Cover"; }
-
Both of the microservices are configured to use Sleuth. When on the classpath, Sleuth automatically adds trace information to the log messages of Spring Boot applications...
INFO [covers-service,2850d9e30f986e35,3e79aa27ebf9f9e3,true] 13 --- [io-8080-exec-10]
Sleuth is configured to send these messages to the Zipkin server via a RabbitMQ based message stream. This allows the Zipkin server to paint a clear and overarching picture of all the service calls between all the microservices in the project. It can even diagram these interactions for you to aid your understanding your microservice communications.
When you provisioned the services, SCS made the following UI consoles available to you...
- RabbitMQ (RabbitMQ Console)
- Service Registry (Eureka Dashboard)
- Circuit Breaker (Hystrix Dashboard)
You can get to these consoles by following the Services(x) -> [Your Service Name] > Manage
link in the PCF Apps Manager application.
Zipkin is not part of the SCS tile, but it also provides a UI for searching for traces which you can get to by opening the app in your browser using the link provided in the PCF Apps Manager.
Ben Wilcock works for Pivotal as a Cloud Solutions Architect. Ben has a passion for microservices, cloud and mobile applications and helps Pivotal's Cloud Foundry customers to become more responsive, innovate faster and gain greater returns from their software investments. Ben is also a respected technology blogger who's articles have featured in DZone, Java Code Geeks, InfoQ and more.