It has been a long time since I updated the series of articles on Spring Cloud Building microservices Architecture. Since I started writing about Spring Cloud, I have received a lot of reading and recognition, as well as some criticism, including some pertinent comments and in-depth questions. It’s also an opportunity for me to improve, and I’d like to thank all the readers who follow my blog.

The series of articles has not been continuously maintained and updated since most of the previous efforts were spent on writing the book “Spring Cloud Microservices In Action”. Due to the lengthy writing process and cumbersome publishing process, the book was already behind the current edition when it came out. Although some notes for updating the version have been added in the book, the process of understanding is not accomplished overnight, but always discovered slowly with the deepening of practice. So I decided to rewrite the series, on the one hand updating the Spring Cloud version to Dalston, on the other hand reorganizing the content and adding some important components that I hadn’t written about before. I hope this series will help you get started quickly if you are ready to use Spring Cloud. At the same time, it is also a supplement to the latest version of the book “Spring Cloud Micro-service Practice”.





Spring Cloud profile

Spring Cloud is a Cloud application development tool based on Spring Boot implementation. It provides an easy way to develop operations such as configuration management, service discovery, circuit breakers, intelligent routing, microproxy, control bus, global locking, decision campaigning, distributed session, and cluster state management in JVM-based cloud application development.

Spring Cloud contains several sub-projects (for different open source products involved in distributed systems), such as: Spring Cloud Config, Spring Cloud Netflix, Spring Cloud0 CloudFoundry, Spring Cloud AWS, Spring Cloud Security, Spring Cloud Commons, Spring Cloud Zookeeper, and Spring Cloud CLI.

Microservices Architecture

“Micro-service architecture” has been so hot in recent years that open source products related to micro-service architecture have been repeatedly mentioned (such as Netflix and Dubbo), and Spring Cloud has also attracted the attention of architects and developers due to the strong popularity and influence of Spring community.

So what is a “microservices architecture”? To put it simply, microservice architecture is to vertically divide a complete application from data storage into multiple different services. Each service can be independently deployed, maintained, and extended. Services can be called to each other through ways such as RESTful apis.

For “micro-service architecture”, you can find many relevant introductions and research articles on the Internet to learn and understand. You can also read Microservices by Martin Fowler, the original author, without further introduction or description.


Service governance

After a brief introduction to Spring Cloud and microservices architecture, let’s return to the main point of this article on how to use Spring Cloud to implement service governance.

Because Spring Cloud provides an abstract interface for service governance, Spring Cloud applications can support many different service governance frameworks, such as Netflix Eureka, Consul, and Zookeeper. With the Spring Cloud service governance abstraction layer, we can seamlessly switch service governance implementations without affecting any other logic for service registration, service discovery, service invocation, etc.

So let’s take a look at the benefits of Spring Cloud’s layer of abstraction by introducing two implementations of service governance.

Spring Cloud Eureka

First, let’s try to implement service governance using Spring Cloud Eureka.

Spring Cloud Eureka is a service governance module under Spring Cloud Netflix project. The Spring Cloud Netflix project is one of the sub-projects of Spring Cloud. The main content is the packaging of a series of open source products of Netflix, and it provides self-configurable Netflix OSS integration for Spring Boot applications. With a few simple annotations, developers can quickly configure common modules in their applications and build large distributed systems. Its main modules include: Service discovery (Eureka), circuit breaker (Hystrix), Intelligent Routing (Zuul), client load balancing (Ribbon), etc.

Let’s take a concrete look at how to implement service governance using Spring Cloud Eureka.

Creating a Service Registry

Create a basic Spring Boot project, call it Eureka-Server, and introduce the required dependencies in POM.xml:

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope>  </dependency> </dependencies> </dependencyManagement>Copy the code

Start a service registry with the @enableeurekaserver annotation to provide conversations to other applications. This step is as simple as adding this annotation to a normal Spring Boot application to enable this function, as shown in the following example:

@EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class) .web(true).run(args); }}Copy the code

By default, the service registry also attempts to register itself as a client, so we need to disable its client registration behavior by adding the following information to the application.properties configuration file:

spring.application.name=eureka-server
server.port=1001
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Copy the code

To distinguish it from the services to be registered later, the port of the service registry is set to 1001 via the server.port property. After starting the project, visit: http://localhost:1001/ and you will see the following page where no services have been found.

&amp; amp; amp; amp; lt; img src=”https://pic3.zhimg.com/v2-4deb7c8b4ca1939f2d58e620800186da_b.png” data-rawwidth=”1241″ data-rawheight=”1138″ class=”origin_image zh-lightbox-thumb” width=”1241″ data-original=”https://pic3.zhimg.com/v2-4deb7c8b4ca1939f2d58e620800186da_r.png”&amp; amp; amp; amp; gt;

Creating a “Service Provider”

Now we create a client that provides the service and register ourselves with the service registry. This article focuses on registration and discovery of services, so we might as well try to provide an interface in the service provider to get all the current service information.

First, create a basic Spring Boot application. Named eureka-client, add the following configuration to pom. XML:

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> < version > 1.5.4. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope>  </dependency> </dependencies> </dependencyManagement>Copy the code

Second, implement/DC request processing interface, and print service instance content in log through DiscoveryClient object.

@RestController public class DcController { @Autowired DiscoveryClient discoveryClient; @GetMapping("/dc") public String dc() { String services = "Services: " + discoveryClient.getServices(); System.out.println(services); return services; }}Copy the code

Finally, by adding @enableDiscoveryClient annotation to the application main class, this annotation can activate DiscoveryClient implementation in Eureka, so as to realize the output of service information in Controller.

@EnableDiscoveryClient @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder( ComputeServiceApplication.class) .web(true).run(args); }}Copy the code

After completing the implementation of the service content, we will continue to do some configuration work on application.properties, as follows:

spring.application.name=eureka-client
server.port=2001
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Copy the code

With the spring.application.name attribute, we can specify the name of the microservice that will be used only for subsequent calls to the service. Eureka. Client. ServiceUrl. DefaultZone properties corresponding to the service registry configuration content, specify the location of the service registry. To test the distinction between service providers and service registries on the local machine, set different ports using the server.port property.

After starting the project, visit again: http://localhost:1001/. As shown below, the service we defined was successfully registered.

&amp; amp; amp; amp; lt; img src=”https://pic4.zhimg.com/v2-cdd2e087cafd49cb0e4fd87517d398c7_b.png” data-rawwidth=”1235″ data-rawheight=”173″ class=”origin_image zh-lightbox-thumb” width=”1235″ data-original=”https://pic4.zhimg.com/v2-cdd2e087cafd49cb0e4fd87517d398c7_r.png”&amp; amp; amp; amp; gt; Of course, we can also get the current list of services by accessing the/DC interface provided by the Eureka-Client service directly by accessing:


http://localhost:2001/dc, we can get the following output return:

Services: [eureka-client]
Copy the code

Eureka-client in square brackets is a list of all services that are retrieved from eureka’s implementation through the DiscoveryClient interface defined by Spring Cloud. Because Spring Cloud abstracts the service discovery layer so well, we can seamlessly switch from Eureka’s service governance system to Consul’s service governance system.

Spring Cloud Consul

The Spring Cloud Consul project is a service governance implementation for Consul. Consul is a distributed, highly available system that contains multiple components, but as a whole provides tools for service discovery and service configuration for our infrastructure in a microservices architecture. It contains the following features:

  • Service discovery
  • Health check
  • The Key/Value store
  • Multi-data center

Thanks to the Spring Cloud Consul project, we can easily register Spring Boot-based microservice applications on Consul and implement service governance in microservice architecture.

Based on our previously implemented Eureka-based example (Eureka-client), how do we register our previously implemented service provider on Consul? The method is very simple, we just need to change the eureka dependency in pom.xml to the following dependency:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId>  </dependency>Copy the code

Then modify application.properites and add the configuration information required by consul, for example :(the following configuration is the default)

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
Copy the code

This completes the transformation of Eureka-Client into a service provider based on Consul service governance. As mentioned earlier, DiscoveryClient is an abstraction of Eureka Consul service governance implemented by Spring Cloud. Therefore, the implementation details of Eureka Consul service governance can be masked. We do not need to make any changes to our application, just introduce different service governance dependencies. And configuring the relevant configuration properties makes it easy to integrate microservices into Spring Cloud’s various service governance frameworks.

Here’s what you can try to get Consul’s service provider up and running. Don’t you need to create a server like Eureka-Server? Consul provides its own server, so we don’t need to create a service registry like we did when implementing Eureka. Instead, we can download Consul’s server application and use it.

Consul can be started in development mode with the following command:

$consul agent -dev ==> Starting Consul agent... ==> Starting Consul agent RPC... ==> Consul agent running! Version: 'v0.7.2' Node name: 'Lenovo-zhaiyc' Datacenter: 'dC1' Server: true (bootstrap: false) Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400) Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302) Gossip: encrypt false, RPC-TLS: false, TLS-Incoming: false Atlas: <disabled> ==> Log data will now stream in as it occurs: 2017/06/22 07:50:54 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:127.0.0.1:8300 Address:127.0.0.1:8300}] 2017/06/22 07:50:54 [INFO] raft: Node at 127.0.0.1:8300 [Follower] entering Follower state ("") 2017/06/22 07:50:54 [INFO] serf: EventMemberJoin: Lenovo-zhaiyc 127.0.0.1 2017/06/22 07:50:54 [INFO] Consul: Adding LAN Server Lenovo-Zhaiyc (Addr: TCP /127.0.0.1:8300) (DC: dC1) 2017/06/22 07:50:54 [INFO] serf: EventMemberJoin: Lnvg-zhaiyc.dc1 127.0.0.1 2017/06/22 07:50:54 [INFO] Consul: Adding WAN Server Lnvg-zhaiyc.dc1 (Addr: TCP /127.0.0.1:8300) (DC: DC1) 2017/06/22 07:51:01 [ERR] Agent: Failed to sync remote state: No cluster leader 2017/06/22 07:51:02 [WARN] raft: Heartbeat timeout from "" reached, starting election 2017/06/22 07:51:02 [INFO] raft: Node at 127.0.0.1:8300 [Candidate] entering Candidate state in term 2 2017/06/22 07:51:02 [DEBUG] raft: Votes needed: 1 2017/06/22 07:51:02 [DEBUG] Raft: Vote granted from 127.0.0.1:8300 in term 2. Tally: 1 2017/06/22 07:51:02 [INFO] raft: Election won. Tally: 1 2017/06/22 07:51:02 [INFO] raft: Node at 127.0.0.1:8300 [Leader] entering Leader state 2017/06/22 07:51:02 [INFO] consul: cluster leadership acquired 2017/06/22 07:51:02 [INFO] consul: New leader elected: Lenovo-zhaiyc 2017/06/22 07:51:02 [DEBUG] consul: reset tombstone GC to index 3 2017/06/22 07:51:02 [INFO] consul: member 'Lenovo-zhaiyc' joined, marking health alive 2017/06/22 07:51:02 [INFO] agent: Synced service 'consul' 2017/06/22 07:51:02 [DEBUG] agent: Node info in syncCopy the code

After consul server is started, we will start the modified Consul service provider. Consul, like Eureka, provides a simple UI interface to view service registrations:

&amp; amp; amp; amp; lt; img src=”https://pic4.zhimg.com/v2-195faa9a40434cb7818555014facccdf_b.png” data-rawwidth=”1189″ data-rawheight=”570″ class=”origin_image zh-lightbox-thumb” width=”1189″ data-original=”https://pic4.zhimg.com/v2-195faa9a40434cb7818555014facccdf_r.png”&amp; amp; amp; amp; gt; For more information on Consul’s guidelines, you can check out the official documentation:


Consul by HashiCorp

Stay tuned for more Spring Cloud updates on my blog or in Spring Cloud Microservices In Action.

Code sample

The sample project is a reworking of the SpringCloud-Learning project that was previously created on Code Cloud and GitHub. Examples of Brixton and Dalston being distinguished by different directories.

  • Code cloud: Click to view
  • GitHub: Check it out

Details of the project are as follows:

  • Eureka’s service registry: Eureka-Server
  • Eureka service provider: Eureka-Client
  • Consul’s service provider: Consul-client

The original:Spring Cloud building microservices Architecture: Service Registration and Discovery (Eureka, Consul) Dalston edition