首頁 >Java >java教程 >spring cloud是什麼? spring cloud的使用介紹

spring cloud是什麼? spring cloud的使用介紹

不言
不言原創
2018-09-20 15:18:218517瀏覽

本篇文章帶給大家的內容是關於spring cloud是什麼? spring cloud的使用介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、什麼是Spring Cloud?

Spring提供了一系列工具,可以幫助開發人員迅速建構分散式系統中的公共元件(例如:設定管理,服務發現,斷路器,智慧路由,微代理,控制總線,一次性令牌,全域鎖,主節點選舉, 分散式 session, 叢集狀態)。協調分散式環境中各系統,為各類服務提供模板性配置。使用Spring Cloud, 開發人員可以建造實現了這些樣板的應用,並且在任何分佈式環境下都能工作得非常好,小到筆記型電腦, 大到資料中心和雲端平台。

Spring Cloud是基於Spring Boot的, 最適合用於管理Spring Boot創建的各個微服務應用。要管理分散式環境下的各個Spring Boot微服務,必然存在服務的註冊問題。所以我們先從服務的註冊談起。既然是註冊,必然有個管理註冊中心的伺服器,各個在Spring Cloud管理下的Spring Boot應用就是需要註冊的client。

Spring Cloud使用erureka server,  然後所有需要存取設定檔的應用程式都以一個erureka client註冊上去。 eureka是一個高可用的元件,它沒有後端緩存,每個實例註冊之後需要向註冊中心發送心跳,在預設情況下erureka server也是一個eureka client ,必須要指定一個 server。

1.建立Eureka Server

先建立一個spring boot的專案

pom檔

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

需要一個註解@EnableEurekaServer加在springboot工程的啟動類別上

@EnableEurekaServer
@SpringBootApplication
public class TestApplication {

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

eureka server的設定檔appication.yml

server:
  port: 8761

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

啟動eureka server,然後造訪http://localhost:8761, 介面如下, "No instances available" 表示無client註冊

2.建立一個Eureka Client

pom檔

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

使用@EnableEurekaClient註解顯示是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檔案的設定

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

最後啟動client,之後就可以在伺服器連接埠看​​到該client成功註冊

二、設定管理

Spring Cloud的解決方案是, 將這些設定檔放到版本管理伺服器裡面,Spring Cloud缺省設定使用GIT中。所有Web服務均從GIT中取得這些設定檔。由於GIT伺服器與特定Web伺服器之間不需要共享存儲, 只要網路可達就行,從而可以實現Web服務於配置資訊的存放位置的解耦。

2.1建立config Server

##pom檔案新加入了依賴關係

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

 @EnableConfigServer註解說明了一個Config Server。同樣我們使用@EnableEurekaClient將它註冊到服務中心。

Config server的設定檔appication.yml , 注意設定檔的url是GIT伺服器的倉庫位址, searchPaths設定檔所在的資料夾在倉庫中的路徑, 在server端不需要指定特定設定檔名, 因為具體的設定檔是什麼有應用(也就是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

啟動Config server,造訪http://localhost:8888/config-client-dev.properties就可以顯示設定檔內容

2.2建立

#config client

啟動檔案

 @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檔案

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

啟動config-client應用程式後,可以存取 http://locahost/8881/hello, 可以看到,應用程式本身並沒有直接配置hello的具體內容, 也沒指定具體配置文件,所欲這些都由spring cloud框架提交給config server了。

三、設定自動刷新

首先,在pom.xml中加入以下依賴。

spring-boot-starter-actuator是一套監控的功能,可以監控程式在執行時狀態,其中就包含/refresh的功能。

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

其次,開啟refresh機制, 需要在載入變數的類別上載入

@RefreshScope註解,其它程式碼可不做任何改變,那麼在客戶端執行/refresh的時候就會更新這類下面的變數值,包括透過config client從GIT取得的設定。

@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;
    }
}

但這種方式需要自己手動重新運行方法,才能看到更新後的資料

四、分散式環境下自動發現組態服務

將config-server註冊到服務中心

#將hello world的應用程式註冊到eureka 服務中心, 設定方法同前面一樣

修改設定文件,將config-server的URL硬編碼機制改成,透過服務中心根據名字自動發現機制

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即可对请求先进行筛选和过滤之后再路由到具体服务。

以上是spring cloud是什麼? spring cloud的使用介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn