SpringCloud from entry to proficiency: actual combat

SpringCloud is a microservice architecture development tool based on the Spring framework, which has become one of the mainstream solutions for the current microservice architecture development. Compared with the traditional architecture, SpringCloud can better solve problems such as business splitting, scalability, high availability, and multi-tenancy. Therefore, learning Spring Cloud has become one of the essential skills for Java engineers today.

This article will explain in detail the relevant knowledge of Spring Cloud, including but not limited to:

  1. Introduction to Spring Cloud
  2. Build a microservice architecture
  3. Service Registry—Eureka
  4. Service provider—Provider
  5. Service consumers—Consumer
  6. Use of RestTemplate
  7. Ribbon use
  8. Use of Feign
  9. Use of Hystrix
    1. Use of Zuul

1. Introduction to Spring Cloud

First of all, we need to know that SpringCloud is not a specific technology, but a distributed microservice framework, mainly based on Spring Boot, with the purpose of quickly building a one-stop solution collection for distributed systems.

SpringCloud was proposed and open sourced by Netflix. It is based on the Spring Boot framework and integrates many common microservice components.

2. Build a microservice architecture

SpringCloud's microservice architecture includes multiple microservice components, the most commonly used of which are Eureka, Feign, Hystrix, Zuul, etc. Let's take a look at the functions and characteristics of these components.

  1. Eureka

Eureka is a REST-based service registration and discovery component whose core is developed by Netflix. It provides service registration and discovery functions, acts as a service registry, and implements service governance in the microservice architecture.

Eureka has the following two roles:

  • Eureka Server: A server that provides service registration and discovery functions
  • Eureka Client: As a service provider or service consumer, a Java application registers the services it provides or consumes with the registry when the application starts

In Eureka, it is necessary to integrate Eureka Client components in service providers and service consumers respectively to realize service registration and discovery.

Advantages of Eureka:

  • Eureka supports multiple registry configurations
  • Service registry supports self-preservation and health checks
  • Support flexible service discovery methods

Disadvantages of Eureka:

  • Service discovery is slow
  • Does not support load balancing
  1. Feign

Feign is a declarative REST client that can define request parameters, request content and return values ​​through annotations and interfaces, thus simplifying the development cost of using REST API.

Main features of Feign:

  • Realized based on interface, realized through annotation
  • Integrated with Ribbon to support load balancing
  • Support Hystrix for service downgrade

Advantages of Feign:

  • Interface programming simplifies the development of HTTP requests
  • Closely integrated with Spring Cloud, more convenient to use
  • Support multiple encoding formats: such as: JSON, XML, etc.
  • Support multiple HTTP request methods: GET, POST, PUT, DELETE, etc.

Disadvantages of Feign:

  • Complex HTTP requests are not supported
  • thread unsafe
  1. Hystrix

Hystrix is ​​a latency and fault tolerance library developed by Netflix that aims to make complex distributed systems more resilient by isolating dependencies (for example, through the circuit breaker pattern).

Key features of Hystrix:

  • Support request caching and request merging mechanism
  • Support delay and fuse mechanism
  • Integrates Hystrix Dashboard to provide a friendly monitoring interface

Advantages of Hystrix:

  • Support request caching mechanism and request merging mechanism
  • Provide fuse protection mechanism to reduce the risk of business failure
  • Supports near real-time viewing of performance indicators and configuration information
  • Supports manual and automatic implementation of downgrade strategies

Disadvantages of Hystrix:

  • The multi-request retry mechanism will increase the client's responsibility
  • Need to provide performance monitoring for the entire microservice architecture
  1. Zuul

Zuul is a JVM-based router and server-side load balancer developed by Netflix, which provides a unified entrance for client requests.

Key features of Zuul:

  • Support global filter and local filter
  • Requests can be routed and forwarded
  • Support request current limit and specified number of requests

Advantages of Zuul:

  • Based on JVM implementation, better performance
  • Can provide support for marginalization of services
  • Complex route matching is possible
  • Customized functions can be customized to meet needs

Disadvantages of Zuul:

  • Added additional complexity due to service edge support

3. Service Registration Center—Eureka

Next, we will use a simple example to understand how to implement service registration and discovery through Eureka.

  1. add dependencies

Add the following dependencies to the pom.xml file:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
    <version>1.5.6.RELEASE</version>
</dependency>
  1. Write a configuration file

Add the following configuration to the application.yml file:

# 服务名
spring.application.name=server-center
# 注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
# 关闭服务自己的注册
eureka.client.register-with-eureka=false
# 关闭服务自己的fetch-registry=false
  1. Start Eureka Server

Add the @EnableEurekaServer annotation to the startup class of SpringBootApplication to indicate that the current application is an Eureka Server instance.

@SpringBootApplication  
@EnableEurekaServer  
public class EurekaServerApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(EurekaServerApplication.class, args);  
    }  
}
  1. Start the service provider

Add the @EnableDiscoveryClient annotation to the startup class of the service provider to indicate that the current application is an Eureka Client instance.

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
  1. Start the service consumer

Add the @EnableDiscoveryClient annotation to the startup class of the service consumer to indicate that the current application is an Eureka Client instance.

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
  1. Test service registration and discovery

Implement a simple service in the service provider and register it with Eureka Server, where the @RestController annotation indicates that the class can handle REST requests.

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello World!";
    }
}

Use RestTemplate in the service consumer to call the service provider, where the @LoadBalanced annotation indicates that multiple service provider instances are called using load balancing.

@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/hello")
    public String hello() {
        return restTemplate.getForObject("http://provider-service/hello", String.class);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Start Eureka Server, service provider and service consumer, and visit http://localhost:8761/ in the browser, you can see that the service provider and consumer have been successfully registered to Eureka Server. At the same time, the result of invoking the service provider can be seen in the console of the service consumer.

4. Service provider—Provider

In the microservice architecture, the main role of the service provider is to provide the service interface and implement it.

  1. add dependencies

Add the following dependencies to the pom.xml file:

<!-- 服务注册到Eureka Server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. Write a configuration file

Add the following configuration to the application.yml file:

# 服务名
spring.application.name=provider-service
# 注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
# 关闭服务自己的注册
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
  1. Write service implementation class

In the service implementation class, add @Service annotation to indicate that the class is a Spring Bean, and add @RequestMapping annotation and @GetMapping annotation to the class to indicate the URL path and request method of the service interface respectively.

@Service
@RequestMapping("/hello")
public class HelloServiceImpl implements HelloService {
    @Override
    @GetMapping
    public String hello() {
        return "Hello World!";
    }
}
  1. registration service

Add the @EnableDiscoveryClient annotation to the service startup class to indicate that the service is an instance of Eureka Client and registered with Eureka Server.

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

5. Serving consumers—Consumer

In the microservice architecture, the main role of the service consumer is to call the service interface and process the service result.

  1. add dependencies

Add the following dependencies to the pom.xml file:

<!-- 使用Ribbon进行负载均衡 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- 使用Feign进行服务调用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. Write a configuration file

Add the following configuration to the application.yml file:

# 服务名
spring.application.name=consumer-service
# 注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
# 使用Ribbon进行负载均衡
provider-service.ribbon.listOfServers=http://localhost:8081,http://localhost:8082
# 关闭服务自己的注册
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
  1. Use the RestTemplate to call the service

Where the service is called, use the RestTemplate to make an HTTP request and specify the URL path of the service.

@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/hello")
    public String hello() {
        return restTemplate.getForObject("http://provider-service/hello", String.class);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Among them, the @LoadBalanced annotation indicates that multiple service provider instances are called using load balancing.

  1. Service calls using Feign

Define a service interface and add the @GetMapping annotation to the method to indicate the request path and request method processed by the method.

@FeignClient(name = "provider-service")
public interface HelloService {
    @GetMapping("/hello")
    String hello();
}

Where the service is called, use @Autowire to inject the service interface and call the methods in it.

@RestController
public class ConsumerController {
    @Autowired
    private HelloService helloService;
    @GetMapping("/hello")
    public String hello() {
        return helloService.hello();
    }
}

Six, the use of RestTemplate

RestTemplate is a simple RESTful service template that can be used to send HTTP requests and process the response results.

  1. add dependencies

Add the following dependencies to the pom.xml file:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. send HTTP request

RestTemplate mainly provides the following HTTP methods:

  • GET: get resources
  • POST: create resource
  • PUT: update resource
  • DELETE: delete resource

Send a GET request and get the response result:

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);

Send a POST request and pass parameters:

RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("name", "张三");
params.add("age", "20");

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);

String result = restTemplate.postForObject(url, requestEntity, String.class);
  1. Handle the response result

RestTemplate can convert response results into various types of objects, such as strings, byte arrays, input streams, JSON objects, XML documents, etc.

Get the string representation of the response result:

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);

Get the byte array of the response result:

RestTemplate restTemplate = new RestTemplate();
byte[] result = restTemplate.getForObject(url, byte[].class);

Get the input stream of the response result:

RestTemplate restTemplate = new RestTemplate();
InputStream result = restTemplate.getForObject(url, InputStream.class);

Get the JSON object of the response result:

RestTemplate restTemplate = new RestTemplate();
JSONObject result = restTemplate.getForObject(url, JSONObject.class);

Get the XML document of the response result:

RestTemplate restTemplate = new RestTemplate();
Document result = restTemplate.getForObject(url, Document.class);

Seven, the use of Ribbon

Ribbon is a popular UI library, which provides rich UI controls and layouts, which can help us quickly create modern interfaces. Let's introduce the use of Ribbon:

  1. Import Ribbon library: Ribbon can be used by adding Ribbon's dependency library to the project. For example, if using Maven, you can add the following dependencies in pom.xml:
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>ribbon</artifactId>
    <version>2.0.1</version>
</dependency>
  1. Create a Ribbon control: Ribbon contains a variety of controls, such as buttons, labels, text boxes, and so on. Create them by adding the code for the Ribbon control in the XML layout file. For example, the following code creates a Ribbon control with a label and a button:
<ribbon:Ribbon>
    <ribbon:RibbonTab>
        <ribbon:RibbonGroup>
            <ribbon:RibbonLabel text="Hello, Ribbon!" />
            <ribbon:RibbonButton text="Click me!" />
        </ribbon:RibbonGroup>
    </ribbon:RibbonTab>
</ribbon:Ribbon>
  1. Set the Ribbon theme: Ribbon has a variety of themes, you can change the appearance of the Ribbon by setting the theme. For example, the following code sets the Ribbon's theme to "Office 2016":
<ribbon:Ribbon styleClass="office-2016">
    ...
</ribbon:Ribbon>
  1. Handling Ribbon events: Like other UI libraries, Ribbon controls can also trigger events. For example, when a button is clicked, related actions can be performed. Here is an example of handling button click events:
RibbonButton button = ...; // 获取RibbonButton控件实例
button.setOnAction(event -> {
    
    
    // 处理按钮点击事件
});

Eight, the use of Feign

Feign is a declarative HTTP client that makes writing HTTP clients easier. When using Feign, we only need to define an interface and add annotations on it, and Feign will automatically generate the implementation for us.

Here are the basic steps to use Feign:

  1. add dependencies

Add Feign-related dependencies to the project, as follows:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. Create Feign client interface

Before using Feign, we need to create a Feign client interface. Add annotations to this interface @FeignClientto specify the service name:

@FeignClient(name = "service-name")
public interface ServiceClient {
    
    
    //...
}

In this interface, we can define the service interface methods that need to be called.

  1. implement the interface method

After defining the Feign client interface, we need to implement the methods in it. The Feign client will generate an HTTP request according to the definition of the interface method, and convert the result into the object we need.

@FeignClient(name = "service-name")
public interface ServiceClient {
    
    
    @GetMapping("/user/{id}")
    User getUserById(@PathVariable Long id);
}

In this example, we define an getUserByIdinterface method named , which GETgets the user information of the specified id through an HTTP request.

  1. Inject Feign client

The last step is to inject the Feign client into our code so we can call the service through it. Through @Autowiredannotations, we can inject the Feign client into a service class:

@Service
public class UserService {
    
    
    @Autowired
    private ServiceClient serviceClient;
    
    public User getUserById(Long id) {
    
    
        return serviceClient.getUserById(id);
    }
}

In this example, we inject the Feign client into UserService and call getUserByIdthe interface method in it.

9. Using Hystrix

Hystrix is ​​a library for handling failure and latency in distributed systems. When building a distributed system, various failures and failure scenarios must be considered. Hystrix provides a simple yet powerful way to handle these issues by wrapping each remote call in a circuit-breakable, degradable, cacheable wrapper.

Protecting your application from failures and delays is easy with Hystrix. It provides a powerful control mechanism to configure, monitor and manage calls to remote dependencies in the application. Here are some steps to use Hystrix:

  1. Configure Hystrix

Before using Hystrix, Hystrix must be configured. You can configure Hystrix using Spring Cloud Hystrix or by manually writing Hystrix configuration classes.

  1. Define Hystrix commands

When using Hystrix, you need to define a Hystrix command. A Hystrix command is a wrapper for performing remote calls. You can wrap all remote calls in Hystrix commands.

  1. Use the Hystrix command

Using Hystrix commands is very simple. You just need to call the execute() method of the Hystrix command, providing parameters if necessary. Hystrix automatically handles failure and latency situations and returns appropriate results.

  1. Define Hystrix fuse

A Hystrix circuit breaker is a mechanism for automatically disconnecting faulty or delayed services. You can define a Hystrix circuit breaker to control calls to remote dependencies. If the number of calls exceeds a certain threshold, Hystrix will automatically disconnect the call and trigger the fuse.

  1. Monitor Hystrix

Hystrix provides some monitoring tools that can help you monitor and manage your application. You can use the Hystrix Dashboard to monitor your Hystrix commands and circuit breakers and view detailed information about each command and circuit breaker.

Chapter 10 Use of Zuul

Zuul is a microservice gateway framework open sourced by Netflix, which can handle a series of problems such as request routing, load balancing, service degradation, and circuit breaker. In the microservice architecture, Zuul can be used as an edge service to control the access of microservices, and it can also be used as a centralized service management platform to realize a unified entrance of services.

When using Zuul, we need to introduce Zuul's dependencies in pom.xml first:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

@EnableZuulProxyNext, we need to use annotations to enable Zuul's proxy function in the startup class of the application :

@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication {
    
    

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

}

Configuring Zuul's routing rules is very simple, just add the following configuration to the application's configuration file:

zuul:
  routes:
    service1:
      path: /service1/**
      serviceId: service1
    service2:
      path: /service2/**
      serviceId: service2

In this example, we route requests with request paths starting with /service1/**and to services named and respectively. The name of this service is the registered name in the service registry./service2/**service1service2

Zuul also supports some advanced functions, such as service load balancing, service degradation and fuse. We can use Ribbon to achieve load balancing of services, and Hystrix to achieve service degradation and fusing. For the specific usage of these functions, please refer to the Spring Cloud documentation.

Guess you like

Origin blog.csdn.net/canshanyin/article/details/130571809