Introduction to the

Spring Cloud provides the Hystrix fault-tolerant library to degrade a circuit-breaker configured method and temporarily invoke an alternate method when the service is unavailable. This article will create a product microservice, register with the Eureka service registry, and then use a Web client to access the/Products API to get a list of products and, in the event of a product service failure, invoke a local alternate method to degrade but deliver the service normally.

Based on the environment

  • JDK 1.8
  • Maven 3.3.9
  • IntelliJ 2018.1
  • Git

Program source code

Gitee yards cloud

Adding Products and Services

Create a new Maven project in intelliJ using the following configuration

  • groupId: cn.zxuqian
  • artifactId: productService

Then add the following code to pom.xml:

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.zxuqian</groupId>
    <artifactId>productService</artifactId>
    <version>1.0 the SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1. RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>
Copy the code

We continued to use spring-cloud-starter-Netflix-Eureka-client to automatically register the product service with the Eureka service. Spring-cloud-starter-config is then used to read the configuration file for the configuration service center. This project is just a simple Spring Web project.

Create the bootstrap.yml file under SRC /main/resources and add the following:

spring:
  application:
    name: product-service
  cloud:
    config:
      uri: http://localhost:8888
Copy the code

Create a product-service.yml file in the git repository in the configuration center and add the following configuration and commit:

server:
  port: 8081
Copy the code

This configuration specifies port 8081 for the product service. Next create the Application class and add the following code:

package cn.zxuqian;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class Application {
    public static void main(String[] args) { SpringApplication.run(Application.class, args); }}Copy the code

The @enableDiscoveryClient annotation will instruct Spring Cloud to automatically register this service with Eureka. Finally create cn. Zxuqian. Controllers. The ProductController controller, provide/products API, return to the sample data:

package cn.zxuqian.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @RequestMapping("/products")
    public String productList(a) {
        return "Coat, jacket, sweater, T-shirt."; }}Copy the code

Configure the Web client

Open the Web project we created earlier and add a new Hystrix dependency to pom.xml:

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

Then update the Application class code:

package cn.zxuqian;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public RestTemplate rest(RestTemplateBuilder builder) {
        returnbuilder.build(); }}Copy the code

You use the @enablecircuitbreaker to turn on the breaker functionality, then add a REST method and use the @Bean annotation. This is part of Spring dependency injection, and using the @Bean tag will tell you how to initialize such objects, such as in this case RestTemplateBuilder to create a RestTemplate object, which will be used later in a service that uses a circuit breaker.

Create cn. Zxuqian. Service. ProductService classes, and add the following code:

package cn.zxuqian.services;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@Service
public class ProductService {

    private final RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    public ProductService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @HystrixCommand(fallbackMethod = "backupProductList")
    public String productList(a) {
        List<ServiceInstance> instances = this.discoveryClient.getInstances("product-service");
        if(instances ! =null && instances.size() > 0) {
            return this.restTemplate.getForObject(instances.get(0).getUri() + "/products", String.class);
        }

        return "";
    }

    public String backupProductList(a) {
        return "Jacket, sweater."; }}Copy the code

The reason to create a Service class is because Hystrix can only be used in classes marked @Service or @Component so that the API provided by Spring Context can be used properly. I’ll explain this later when I dive into Spring. With the @HystrixCommand annotation, Hystrix will monitor the annotated method productList (the underlying proxy wrapper around the method for monitoring). Once the method’s errors accumulate to a certain threshold, the circuit breaker will be activated. All subsequent calls to the productList method will fail, and the fallbackMethod specified backupProductList() method will be temporarily called, and the circuit breaker will be closed when the service returns to normal. We also used DiscoveryClient in this class to find the URI address of the product service, using the value of the spring.application.name configuration item of the product service, Namely the product – service as to discoveryClient serviceID. GetInstances () method, and then returns a list, because at present we have only one product service start, so you just need to take the first instance uri address. We then use RestTemplate to access the API of the product service. Note that Spring’s constructor injection is used, meaning that the @Bean annotated method we used earlier will be used to initialize the RestTemplate variable without us having to manually initialize it. The RestTemplate class provides a getForObject() method to access other Rest apis and wrap the result as an object. The first argument is the URI address of the API to access, and the second argument is the type of the obtained result. So pass him string.class. The backupProductList() method returns the degraded product list information.

Finally create a controller cn. Zxuqian. Controllers. The ProductController and add the following code:

package cn.zxuqian.controllers;

import cn.zxuqian.services.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;

    @RequestMapping("/products")
    public String productList(a) {
        returnproductService.productList(); }}Copy the code

ProductService is used here to provide data for the /products path.

test

First, we use the spring-boot:run plug-in to start the configuration center service, config-server, then eureka-server, then product-Service, and finally the Web client. Wait a moment after eureka service registration to http://localhost:8080/products, under the condition of normal get coat, jackets, sweaters, t-shirts, as a result, then we close the product – service, then access to the same path, will be demoted after the results: Jacket, sweater

Welcome to my blog zxuqian.cn/spring-clou…