Home  >  Article  >  Java  >  What is spring cloud? Introduction to the use of spring cloud

What is spring cloud? Introduction to the use of spring cloud

不言
不言Original
2018-09-20 15:18:218498browse

This article brings you what is spring cloud? The introduction to the use of spring cloud has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

1. What is Spring Cloud?

Spring provides a series of tools that can help developers quickly build common components in distributed systems (such as: configuration management, service discovery, circuit breakers, intelligent routing, micro-agents, Control bus, one-time token, global lock, master node election, distributed session, cluster status). Coordinate various systems in a distributed environment and provide template configurations for various services. Using Spring Cloud, developers can build applications that implement these templates and work well in any distributed environment, from laptops to data centers and cloud platforms.

Spring Cloud is based on Spring Boot and is most suitable for managing various microservice applications created by Spring Boot. To manage each Spring Boot microservice in a distributed environment, there must be a service registration problem. So let’s start with registration of the service. Since it is registration, there must be a server that manages the registration center. Each Spring Boot application under Spring Cloud management is the client that needs to be registered.

Spring Cloud uses erureka server, and then all applications that need to access the configuration file are registered as an erureka client. Eureka is a highly available component. It has no back-end cache. After each instance is registered, it needs to send a heartbeat to the registration center. By default, the erureka server is also an eureka client, and a server must be specified.

1. Create Eureka Server

First create a spring boot project

pom file

<?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>me.cn</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>test</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>10</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</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>

</project>

Requires an annotation @EnableEurekaServer Add to the startup class of the springboot project

@EnableEurekaServer
@SpringBootApplication
public class TestApplication {

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

eureka server's configuration file application.yml

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

Start the eureka server, and then visit http://localhost:8761, the interface is as follows, "No instances available" means no client registration

2. Create an Eureka Client

pom file

<?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>com.chry</groupId>
    <artifactId>test1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test1</name>
    <packaging>jar</packaging>
    <description>Demo Spring Boot Client</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

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

    <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>

        <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>Dalston.RC1</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/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>


</project>

Use the @EnableEurekaClient annotation to indicate that it is a client

@SpringBootApplication
@EnableEurekaClient
@RestController
public class Test1Application {

    public static void main(String[] args) {
        SpringApplication.run(Test1Application.class, args);
    }
    @Value("${server.port}")
     String port;
     @RequestMapping("/")
     public String home() {
                 return "hello world from port " + port;    }

}

yml file configuration

eureka:
     client:
         serviceUrl:
             defaultZone: http://localhost:8761/eureka/
server:
     port: 8762
spring:
     application:
         name: service-helloworld

Finally start the client, and then you can see the successful registration of the client on the server port

2. Configuration management

Spring Cloud’s solution is to put these configuration files in the version management server. Spring Cloud’s default configuration uses GIT. All web services get these configuration files from GIT. Since there is no need to share storage between the GIT server and the specific Web server, as long as the network is reachable, the Web service can be decoupled from the storage location of the configuration information.

2.1 Create config Server

pom file adds new dependencies

<dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-config-server</artifactId>
         </dependency>

The @EnableConfigServer annotation describes a Config Server. Similarly we use @EnableEurekaClient to register it with the service center.

Config server configuration file application.yml, note that the url of the configuration file is the warehouse address of the GIT server, searchPaths is the path of the folder where the configuration file is located in the warehouse, there is no need to specify a specific configuration file name on the server side , because the specific configuration file is determined by the application (that is, the client).

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/ning9/CRUD.git
          searchPaths: spring-cloud/helloworldConfig
  application:
    name: config-server

Start the Config server and access http://localhost:8888/config-client-dev.properties to display the configuration file content

2.2 Create config client

Startup file

 @SpringBootApplication
 @RestController
 public class ConfigClientApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ConfigClientApplication.class, args);
     }
 
     @Value("${hello}")
     String hello;
     @RequestMapping(value = "/hello")
     public String hello(){
         return hello;
     }
 }

yml file

spring:
    application:
      name: config-client
    cloud:
      config:
        label: master
        profile: dev
        uri: http://localhost:8888/
  server:
   port: 8881

After starting the config-client application, you can access http://locahost/8881/hello. You can see that the application itself does not The specific content of hello is directly configured, and no specific configuration file is specified. All these are submitted to the config server by the spring cloud framework.

3. Configure automatic refresh

First, add the following dependencies in pom.xml. spring-boot-starter-actuator is a set of monitoring functions that can monitor the running status of the program, including the /refresh function.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Secondly, to enable the refresh mechanism, you need to load the @RefreshScope annotation on the class that loads the variable. You can leave other code unchanged, then execute /refresh## on the client. #The variable values ​​below this class will be updated, including the configuration obtained from GIT through the config client.

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

    @Value("${hello}")
    String hello;
    @RequestMapping(value = "/hello")
    public String hello(){
        return hello;
    }
}

But this method requires you to manually rerun the method to see the updated data

4. Automatic discovery of configuration services in a distributed environment

Register config-server to the service center

Register the hello world application to the eureka service center, the configuration method is the same as before

Modify the configuration file and change the URL hard-coding mechanism of config-server to the automatic discovery mechanism based on the name through the service center

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/spring:
  application:
    name: config-client
  cloud:
    config:
      label: master
      profile: dev
      discovery:
        enabled: true
        service-id: config-server
management:
  security:
    enabled: falseserver:
   port: 8881

我们注释掉了硬编码的config-server的URL配置, 取而代之的是服务注册中心的地址http://localhost:8761/eureka/以及配置服务的名字“config-server”, 同时打开自动发现机制discovery.enable = true. 我们在运行一下hello world应用, 可以发现, GIT里面的内容依然可以访问。此时我们的hello world应用已经完全不知道配置服务的地址,也不知道配置的内容, 所有这些都通过服务注册中心自动发现。

五、客户端的负载均衡

Spring Cloud用Ribbon来实现两个Hello World服务的负载均衡

5.1创建ribbon服务

添加pom依赖

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

创建启动类ServiceRibbonApplication

@SpringBootApplication
 @EnableDiscoveryClient
 public class ServiceRibbonApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ServiceRibbonApplication.class, args);
     }
 
     @Bean
     @LoadBalanced
     RestTemplate restTemplate() {
         return new RestTemplate();
     }
 }

@EnableDiscoveryClient向服务中心注册,并且注册了一个叫restTemplate的bean。

@ LoadBalanced注册表明,这个restRemplate是需要做负载均衡的。

创建获取一个获取Hello内容的service类

 @Service
 public class HelloService {
     @Autowired RestTemplate restTemplate;
 
     public String getHelloContent() {
         return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
     }
 }

这里关键代码就是, restTemplate.getForObject方法会通过ribbon负载均衡机制, 自动选择一个Hello word服务,

这里的URL是“http://SERVICE-HELLOWORLD/",其中的SERVICE-HELLOWORLD是Hello world服务的名字,而注册到服务中心的有两个SERVICE-HELLOWORLD。 所以,这个调用本质是ribbon-service作为客户端根据负载均衡算法自主选择了一个作为服务端的SERVICE-HELLOWORLD服务。然后再访问选中的SERVICE-HELLOWORLD来执行真正的Hello world调用。

六、用声明式REST客户端Feign调用远端http服务

添加新的依赖

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

创建启动类,需要加上@EnableFeignClients注解以使用Feign, 使用@EnableDiscoveryClient开启服务自动发现

添加配置文件application.yml, 使用端口8902, 名字定义为service-feign, 并注册到eureka服务中心

定义Feign:一个用@FeignClient注解的接口类

@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入; 该接口通过value定义了需要调用的SERVICE-HELLOWORLD服务(通过服务中心自动发现机制会定位具体URL); @RequestMapping定义了Feign需要访问的SERVICE-HELLOWORLD服务的URL(本例中为根“/”)

@FeignClient(value = "SERVICE-HELLOWORLD")  
public interface HelloWorldService {
      @RequestMapping(value = "/",method = RequestMethod.GET)
     String sayHello();
 }

Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里

编写一个Controller。

注入之前通过@FeignClient定义生成的bean, 

sayHello()映射到http://localhost:8902/hello, 在这里,我修改了Hello World服务的映射,将根“/”, 修改成了“/hello”。

@RestController
  public class WebController {
     @Autowired HelloWorldService helloWorldFeignService;
     @RequestMapping(value = "/hello",method = RequestMethod.GET)
     public String sayHello(){
         return helloWorldFeignService.sayHello();
     }
 }

七、断路器

7.1在Ribbon应用中使用断路器

先添加依赖

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

在Spring Boot启动类上添加@EnableCircuitBreaker注解

用@HystrixCommand注解标注访问服务的方法

@Service
  public class HelloService {
      @Autowired RestTemplate restTemplate;
  
      @HystrixCommand(fallbackMethod = "serviceFailure")
      public String getHelloContent() {
          return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
      }
  
     public String serviceFailure() {
         return "hello world service is not available !";
     }
 }

@HystrixCommand注解定义了一个断路器,它封装了getHelloContant()方法, 当它访问的SERVICE-HELLOWORLD失败达到阀值后,将不会再调用SERVICE-HELLOWORLD, 取而代之的是返回由fallbackMethod定义的方法serviceFailure()。@HystrixCommand注解定义的fallbackMethod方法,需要特别注意的有两点:

第一,  fallbackMethod的返回值和参数类型需要和被@HystrixCommand注解的方法完全一致。否则会在运行时抛出异常。比如本例中,serviceFailure()的返回值和getHelloContant()方法的返回值都是String。

第二,  当底层服务失败后,fallbackMethod替换的不是整个被@HystrixCommand注解的方法(本例中的getHelloContant), 替换的只是通过restTemplate去访问的具体服务。可以从中的system输出看到, 即使失败,控制台输出里面依然会有“call SERVICE-HELLOWORLD”。

7.2在Feign应用中使用断路器

 用@FeignClient注解添加fallback类, 该类必须实现@FeignClient修饰的接口。

@FeignClient(name = "SERVICE-HELLOWORLD", fallback = HelloWorldServiceFailure.class) 
public interface HelloWorldService {
     @RequestMapping(value = "/", method = RequestMethod.GET)    
      public String sayHello();
 }

创建HelloWorldServiceFailure类, 必须实现被@FeignClient修饰的HelloWorldService接口。注意添加@Component或者@Service注解,在Spring容器中生成一个Bean

@Component
 public class HelloWorldServiceFailure implements HelloWorldService {
     @Override
     public String sayHello() {
         System.out.println("hello world service is not available !");
         return "hello world service is not available !";
     }
 }

在application.yml中添加如下配置:

feign:
   hystrix:
     enabled: true

八、路由网管zuul

创建新的工程添加新的依赖

b4b38e33757a6497aa8690936b905cc1
     05a8acc5c31084a4f61ade01873802caorg.springframework.cloud192ca2f7b8c770b01c8f81e6bdd5b947
    9bc4cbb67f66e148869423c0d27e5f90spring-cloud-starter-zuulb68fb17cb904a46b73e6272850323873
09a0e22e5aaafd848ae04665be625b91

 创建启动类: 使用@EnableZuulProxy注解

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

编写zuul服务配置:

简单配置两个路由, 一个路由到ribbon,一个路由到feign; 由于都注册到eureka服务中心,所以都用通过serviceId来发现服务具体地址, path是路由的地址映射关系

eureka:
      client:
          serviceUrl:
              defaultZone: http://localhost:8761/eureka/
  server:
      port: 8904
  spring:
      application:
          name: service-zuul
 zuul:
   routes:
     ribbo:
       path: /api-ribbon/**
       serviceId: service-ribbon
     feign:
       path: /api-feign/**
       serviceId: service-feign

这时启动zuul服务, 然后访问http://localhost:8904/api-ribbon可直接路由到http://localhost:8901/.  

http://localhost:8904/api-feign/hello可路由到http://localhost:8902/hello

zuul还提供了过滤功能, 只要实现接口ZuulFilter即可对请求先进行筛选和过滤之后再路由到具体服务。

The above is the detailed content of What is spring cloud? Introduction to the use of spring cloud. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn