Skip to content

A project that shows Spring Cloud Technology to build a Cloud Platform

Notifications You must be signed in to change notification settings

FWinkler79/SpringCloudPlatform

Repository files navigation

Spring Cloud Platform

Pre-Requisites

Installing Spring Cloud CLI

There are a variety of ways to install Spring Cloud CLI, and you can find all of them here.
The easiest way, however, is to use Homebrew (requires a Mac environment).

Using Homebrew simply execute these few commands:

$ brew tap pivotal/tap
$ brew install springboot

This installs the Spring Boot CLI. After that, you need to install the Spring Cloud CLI plugin like this:

$ spring install org.springframework.cloud:spring-cloud-cli:2.1.0.RELEASE

To check the installed Spring Boot CLI version and the available Spring Cloud services you can start up locally, run the following commands:

$ spring version      # print the version of the Spring Boot CLI
$ spring cloud --list # print the available services you can start with Spring Cloud CLI

To bring up a service via the CLI, you can type:

$ spring cloud eureka # bring up a Eureka service registry locally.

For more information see the Spring Cloud CLI documentation.

Starting or Deploying Zipkin Server

Many of the services of this project use Spring Cloud Sleuth with an integration with Zipkin to write trace logs in order to trace requests analyse latencies.

Trace logs generated by a service are sent to a Zipkin server instance expected to be running (by default) on http://localhost:9411/zipkin. The easiest way to run a Zipkin server is to use Docker:

docker run -p 9411:9411 --name zipkinServer openzipkin/zipkin

... or ...

./scripts/startZipkin.sh

This will pull and start a Zipkin server container and once it is started you can access its UI using the link http://localhost:9411/zipkin.

As services will be making requests and logging traces, you will see them in the Zipkin UI. This allows you not only to see which requests are being sent and received but also how long they took and if they were successful or not.

Note, that Spring Cloud Sleuth and Zipkin also work for message-based communication, e.g. using RabbitMQ. See the Spring Cloud Sleuth documentation for details.

See also:

Starting or Deploying Message Broker

docker run -d --hostname my-rabbit --name rabbitBroker -p 15672:15672 -p 5672:5672 rabbitmq:3-management

... or ...

./scripts/startRabbit.sh

Once started you can access its UI using http://localhost:15672/#/.
Username: guest Password: guest

Service Startup Order

Required startup order (ideally):

  1. Zipkin server
  2. RabbitMQ
  3. service-registry
  4. config-server instances
  5. services (i.e. service-registry clients)

For 1. - 3. the order does not really matter. They can be started in any order and will find one another. Services need to be started last, as they will require configuration for startup coming from the config-server.

Config Server

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Config Server
  • Zipkin Client
  • Eureka Discovery Client
  • Spring Boot Actuator
  • Cloud Bus (Adds spring-cloud-bus)
  • Spring for RabbitMQ (adds spring-boot-starter-amqp, and spring-cloud-stream-binder-rabbit for Spring Cloud Bus)

Project config-server is a Spring Boot application that acts as a central configuration server. It uses Spring Cloud Config Server to serve configurations that are stored in a GitHub repository.

  • Bootstraps its own configurations by loading them from GitHub.
  • Uses Zipkin / Sleuth to report tracing information.
  • Is a Eureka client, i.e. registers itself with service registry.
  • Services find / lookup config-server via Eureka.
  • Allows more than one config-server instances to run and be addressed by one logical service name.
  • config-server (and all its potential instances) need to start before any service that reads configuration is started. (See this Spring Cloud Config issue.)
  • Configs are loaded using the following URL pattern /{name}/{profile}/{label} where
  • Uses Spring Cloud Bus, RabbitMQ and Spring Cloud Config Monitor to expose an /monitor endpoint which can be registered as a GitHub WebHook. Every time the configuration changes in GitHub, GitHub sends an event to the /monitor endpoint. The controller behind the /monitor endpoint fires a refresh event via the Spring Cloud Bus (using RabbitMQ as the signalling layer), BUT: only to the service instances that are affected by the change in GitHub (based on Eureka service registry). Services refresh automatically with changes in the configurations being pushed to GitHub!
  • Exposes http://localhost:1111/actuator/bus-refresh endpoint, to refresh all services on the bus at once. See also: http://localhost:1111/actuator/bus-env where you could post key-value pairs to add to every service's environment. See also addressing of individual service instance.
  • Use http://smee.io to forward WebHook events to localhost.

You can see the configurations the server provides by opening its endpoint in a browser. For example, http://localhost:1111/reservation-service/master shows the configurations the reservation-service sees. With the URL http://localhost:1111/application/master you can see the configurations every application sees (the basic configurations). Note that the reservation-service in this example sees an layered view of its own configurations mixed with the basic configurations! Using http://localhost:1111/reservation-service/cloud/master will show the configurations reservation-service will see, if the cloud profile is active in the service (e.g. by setting spring.profiles.active=cloud in the reservation-service's environment).

Updating Configs

Update files, push to GitHub, then refresh services that need updated configs.

Actuator endpoints:

  • For debugging: /actuator/env and /actuator/health
  • For Refreshing: /actuator/refresh - POST only. Send empty POST request. Receive list of changed properties (delta) after refresh.

Note: Needs Rabbit MQ running!

Service Registry

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Eureka Server
  • Config Client
  • Zipkin Client
  • Spring Boot Actuator
  • Currently does not use configs from config-server but brings its own.
  • Startup is independent from config-server

Greetings Service

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Spring Web
  • Spring for RabbitMQ (adds spring-boot-starter-amqp, and spring-cloud-stream-binder-rabbit for Spring Cloud Bus)
  • Cloud Bus (Adds spring-cloud-bus)
  • Config Client
  • Zipkin Client
  • Eureka Discovery Client
  • Spring Boot Actuator

There is a greetings endpoint, that shows a greetings message that comes from the greetings-service.yml configuration in the Configs Repository. With Rabbit MQ running (./scripts/startRabbit.sh) and a connection to Smee.io established (./scripts/connectToSmee.sh), you can change the configs in the repo, and see how the message gets updated automatically (you need to refresh greetings endpoint).

Reservation Service

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Spring Reactive Web
  • Rest Repositories
  • Cloud Bus (Adds spring-cloud-bus)
  • Spring for RabbitMQ (adds spring-boot-starter-amqp, and spring-cloud-stream-binder-rabbit for Spring Cloud Bus)
  • Spring Data JPA
  • H2 Database
  • Config Client
  • Zipkin Client
  • Eureka Discovery Client
  • Spring Boot Actuator
  • RSocket
  • Lombok

Note that the service URL (http://localhost:2222/reservations?page=1&size=2&sort=reservationName,asc) contains parameters for sorting and paging - all out of the box with Spring Data. There is also a "search by name" endpoint available. E.g. http://localhost:2222/reservations/search/by-name?reservationName=Carl will return only the reservations whose name is "Carl".

The service provides its REST endpoints via WebFlux (i.e. in a reactive way). It also provides RSocket endpoints (see com.equalities.cloud.reservation.service.rsocket.RSocketEndpoints) which are called by Reservation Service Client via the Service Gateway. An RSocket endpoint to create reservations is exposed at route create-reservation, and incoming requests (including a reservation name) will trigger the persistence of a new Reservation object into an in-memory H2 database. Spring Data JPARepository is used for persistence, which is a blocking API. The code shows, how that blocking code can be turned into a (reactive) Mono and wrapped inside a transaction.

Reservation Service Client

Access in Browser Access via Postman (HTTP POST)

This project was created with Spring Starter using the following dependencies:

  • Spring Reactive Web
  • Cloud Bus (Adds spring-cloud-bus)
  • Spring for RabbitMQ (adds spring-boot-starter-amqp, and spring-cloud-stream-binder-rabbit for Spring Cloud Bus)
  • Config Client
  • Zipkin Client
  • Eureka Discovery Client
  • Spring Boot Actuator
  • RSocket
  • Lombok

Reservation service client provides Web endpoints (see WebEndpoints) as well as RSocket endpoints (see RSocketEndpoints). The RSocket endpoint is currently not used, but could be called by a browser using rsocket-js to communicate RSocket all the way from the frontend to the backend.

Reservation service client exposes a Web endpoint to retrieve a stream (Flux) of health status messages. This shows how easy it is with WebFlux to create long-living HTTP connections and stream back data from a service via HTTP.

❗️DEPRECATION WARNING: Spring Cloud RSocket has been archived. What is described below is no longer officially available. You can checkout the tag working-spring-cloud-rsocket of this repository to see a working version (however with ancient Spring Boot and Spring Cloud versions).

Another endpoint is exposed to create reservations via HTTP PUSH requests. The HTTP request is translated into an RSocket request, to call Reservation Service's RSocket endpoint and tell it to persist the reservation. Commnunication happens via the Service Gateway which acts as an RSocket broker that both Reservation Service and Reservation Service Client connect to.

To try this out, proceed as follows:

  1. start ZipKin (./scripts/startZipkin.sh)
  2. start RabbitMQ (./scripts/startRabbit.sh)
  3. start service-registry
  4. start config-service
  5. start service-gateway
  6. start reservation-service
  7. start reservation-service-client
  8. send a POST request to http.//localhost:9999/reservation/create/<any name you like> with an empty body.
  9. check that reservation was persisted by opening reservation-service's endpoint http://localhost:2222/reservations and confirm that your name is there.

Service Gateway

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Gateway
  • Spring Boot Actuator
  • Eureka Discovery Client
  • Config Client
  • Cloud Bus (Adds spring-cloud-bus)
  • Spring for RabbitMQ (adds spring-boot-starter-amqp, and spring-cloud-stream-binder-rabbit for Spring Cloud Bus)
  • Zipkin Client
  • Lombok

❗️DEPRECATION WARNING: Spring Cloud RSocket has been archived. What is described below is no longer officially available. You can checkout the tag working-spring-cloud-rsocket of this repository to see a working version (however with ancient Spring Boot and Spring Cloud versions).

And we manually added the RSocket gateway broker, which at the time of writing was in technical preview stage and not yet available via Spring starter.io:

<!-- No longer officially available -->
<!--
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-gateway-rsocket-broker</artifactId>
</dependency>
-->

Diagnostics Service

Access in Browser

This project was created with Spring Starter using the following dependencies:

  • Eureka Discovery Client
  • Zipkin Client
  • Spring Boot Starter Web
  • Spring Boot Actuator

Additionally references WebJars to provide static UI content.

Usage: http://localhost:8777/lookup/<serviceName> e.g. http://localhost:8777/lookup/config-server. The output will be the information that is returned by Eureka.

Technologies to use:

Appendix

Understanding Spring / Spring Boot / Spring Cloud Versioning

When you are developing with Spring, you will usually want to use the released versions. However, there may be times in which you will need to switch to a newer milestone, e.g. in case of errors in a release or if you are asked to try out a new fix the Spring teams have introduced.

Generally, the following version patterns are usually encountered with Spring / Spring Boot:

  1. major.minor.patch.RELEASE
  2. major.minor.patch.SRx (with x=[1..N))
  3. major.minor.patch.Mx (with x=[1..N))
  4. major.minor.patch.RCx (with x=[1..N))
  5. major.minor.patch.BUILD-SNAPSHOT

The version suffixes mean the following:

  • RELEASE - the (first) release and production-ready version of an artifact, e.g. 2.1.18.RELEASE
  • SRx - one of potentially multiple service releases, i.e. newer versions of a released artifact, e.g. containing critical patches. Example: 2.1.18.SR2
  • Mx - one of potentially many milestone releases, usually relevant if you already want to take a peek at the next version the Spring team is working on. E.g. 2.2.0.M6
  • RCx - one of potentially multiple release candidates. These are usually newer than any milestone, and constitute one of potentially multiple milestones that are considered for final release.
  • BUILD-SNAPSHOT - the (usually) latest snapshot versions of an artifact. Note, that we have experienced some release candidate versions being more up to date than the BUILD-SNAPSHOTs!

The general rule of thumb is:

  1. If you intend to stay on the safe release path, prefer service release (SRx) versions over release (RELEASE) versions. And pick the one with the highest number, e.g. SR4 rather than SR3.
  2. If you intend to peek into the next version coming, prefer release candidate (RCx) versions over milestone (Mx) versions. And pick the one with the highest number, e.g. RC2 over RC1 over M6.

Spring and Spring Boot usually use numbers for versions. For Spring Cloud, usually, no major.minor.patch versions are used, but names - e.g. those of British towns - in alphabetically increasing order. For example, at the time of writing, the latest release of Spring Cloud is the Greenwhich release, with Hoxton milestones available as the next release is being prepared. Predecessors of Greenwhich are Angel, Brighton, Camden, Dalston, Edgware, and Finchley - you get the idea. For Spring cloud the same version suffixes apply as stated above.

If you intend to use milestone or snapshot versions, you will have to add the following repository configurations to your Maven pom.xml for the dependencies to be resolved properly:

For Milestones:

<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
  </repository>
</repositories>
<pluginRepositories>
  <pluginRepository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
  </pluginRepository>
</pluginRepositories>

For SNAPSHOTs:

<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Snapshots</name>
    <url>https://repo.spring.io/snapshot</url>
  </repository>
</repositories>
<pluginRepositories>
  <pluginRepository>
    <id>spring-milestones</id>
    <name>Spring Snapshots</name>
    <url>https://repo.spring.io/snapshot</url>
  </pluginRepository>
</pluginRepositories>

The milestone repository links given above will contain also releases and service releases. Thus, you will also be able to resolve .RELEASE versions while pointing to the milestones repository. In case you only want to see the milestones and release candidates you can use the following URLs instead:

❗️Note: In case you are working from behind a Maven mirror (e.g. Sonatype Nexus) that does not contain Spring milestones and snapshots, you will need to make sure (in you Maven settings.xml) that Maven by-passes the mirror when it tries to resolve the milestone or snapshot Spring dependencies.

References

Spring Cloud

RSocket

Spring Boot RSocket Blog Series (Excellent!)

Reactive Programming

Distributed Tracing & Metrics

About

A project that shows Spring Cloud Technology to build a Cloud Platform

Resources

Stars

Watchers

Forks

Packages

No packages published