1. 程式人生 > >SpringCloud筆記(一)服務註冊與服務發現

SpringCloud筆記(一)服務註冊與服務發現

目錄

1、Spring Cloud概述

2、環境搭建

2.1 搭建註冊中心eureka-server

 pom.xml

application.yml

啟動類:

2.2 註冊服務提供者springcloud-producer

pom.xml

application.yml

Controller:

啟動類:

2.3 服務消費者 SpringCloud-Consumer

pom.xml

application.yml

Controller:

啟動類:

3、負載均衡測試

4、服務註冊與發現原理


1、Spring Cloud概述

Spring Cloud是一個基於Spring Boot實現的微服務架構開發工具。它為微服務架構中涉及的配置管理、服務治理、斷路器、只能路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式。

Spring Cloud包含了多個子專案:

Spring Cloud Config:配置管理工具,支援使用Git儲存配置內容,可以使用它搭建分散式配置中心。

Spring Cloud Netflix:核心元件,對多個Netflix OSS開源套件進行整合。

      Eureka:服務治理元件,包含服務註冊中心、服務註冊與發現機制的實現。

      Hystrix:容錯管理元件,實現斷路器模式,幫助服務依賴出現的延遲和未故障提供強大的容錯能力。

      Ribbon:客戶端負載均衡的服務呼叫元件。

      Feign:基於Ribbon和Hystrix的宣告式服務呼叫元件

      Zuul:閘道器元件,提供智慧路由、訪問過濾等功能。

Spring Cloud Bus:時間、訊息匯流排,用於傳播叢集中的狀態變化或事件,以觸發後續的處理,比如用來動態重新整理配置等。

Spring Cloud Consul:服務發現與配置管理工具。

Spring Cloud Stream:通過Redis、Rabbit或者Kafka實現的訊息微服務,通過簡單點的宣告式模型來發送和接收訊息。

Spring Cloud Sleuth: Spring Cloud應用的分散式跟蹤實現,可以完美整合Zipkin。

Spring Cloud Starters:Spring Cloud的基礎元件,它是基於Spring Boot風格專案的基礎依賴模組。

……

2、環境搭建

在此部落格中使用Eureka作為註冊中心,實現服務的註冊與發現,專案結構如下:

2.1 搭建註冊中心eureka-server

 pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lzj</groupId>
<artifactId>euraker-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>euraker-server</name>
<description>this is a register server</description>

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.M3</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>
</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>

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

application.yml

#埠號
server:
  port: 8100

eureka:
  instance:
    #註冊到本地地址
    hostname: 127.0.0.1

  client:
    serviceUrl:
      #客戶端訪問的路徑
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

    #自己就是註冊中心,不需要註冊自己
    register-with-eureka: false
    #自己就是註冊中心,不需要檢索自己
    fetch-registry: false


啟動類:

  @SpringBootApplication
  @EnableEurekaServer //開啟eurekaServer
  public class EurakerServerApplication {
    public static void main(String[] args) {                
        SpringApplication.run(EurakerServerApplication.class, args);
    }
}

此時將註冊中心執行起來,測試搭建是否成功。

通過訪問:http://localhost:8100 看到如下介面,則表示搭建成功,不過此時並沒有註冊任何服務。

 

2.2 註冊服務提供者springcloud-producer

pom.xml

    <!--pom檔案中主要部分:netflix-eureka-client-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
=        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

application.yml

spring:
  application:
    name: app-producer

server:
  port: 8000

eureka:
  client:
    service-url:
         defaultZone: http://localhost:8100/eureka/
    register-with-eureka: true
    fetch-registry: true

Controller:


  @RestController
  public class ProducerController {
 
    @Value("${server.port}")
    private String port;
 
    @RequestMapping("/getMember")
    public String getMember() {
        return "this is a member service" + port;
    }
}

啟動類:


 @SpringBootApplication 
 @EnableEurekaClient //啟動會員服務
  public class SpringcloudProducerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringcloudProducerApplication.class, args);
    }
}

當SpringCloud Producer啟動後,會在註冊中心看到有該服務名稱。

此時可以通過瀏覽器直接訪問該服務:http://localhost:8000/getMember

2.3 服務消費者 SpringCloud-Consumer

現在有了註冊中心,有了服務的提供者,現在再啟動一個服務消費者,在Spring Cloud-Consumer中通過RPC遠端呼叫技術呼叫SpringCloud-Producer中的服務(一個服務既可以當做提供者又可以當做消費者)。

pom.xml

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

application.yml

spring:
  application:
    name: app-consumer

server:
  port: 8001

eureka:
  client:
    service-url:
         defaultZone: http://localhost:8100/eureka/ #註冊中心地址
    register-with-eureka: true
    fetch-registry: true


Controller:

 @RestController
  public class OrderController {

   @Autowired

   private RestTemplate restTemplate;
 

   @RequestMapping("/getorder")

   public String getOrder() {
      // order 使用rpc 遠端呼叫技術 呼叫 會員服務restTemplate
      String memberUrl = "http://app-producer/getMember";
      String result = restTemplate.getForObject(memberUrl, String.class);
      System.out.println("會員服務呼叫訂單服務,result:" + result);
      return result;
   }
}

啟動類:

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

    @Bean
    @LoadBalanced  //讓RestTemplate在請求時擁有客戶端負載均衡的能力
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    //不加@LoadBalanced 將出現無法解析app-producer地址的錯誤:java.net.UnknownHostException
  }

在進行遠端呼叫時,採用了RestTemplate方式,這種方式底層採用的是Ribbon本地負載均衡,(還有一個Feign遠端呼叫技術更常用,在以後的部落格中會介紹到Feign客戶端呼叫方式)。當使用RestTemplate時,需要自己注入一個bean物件,並且在該物件上面加上@LoadBalance開啟本地負載均衡,否則會造成服務名稱無法解析的錯誤:java.net.UnknownHostException

當兩個服務都啟動時,此時註冊中心資訊如下:

現在訪問springcloud-consumet的getOrder介面,以此進行遠端呼叫。

瀏覽器訪問:http://localhost:8001/getorder

說明底層通過RestTemplate完成了遠端呼叫。

3、負載均衡測試

修改springcloud-producer的埠號為8002,重新再啟動一個,模擬一個服務的叢集。

可以看到APP-PRODUCER有兩個服務例項,分別執行在8000埠和8002埠。

當訪問http://localhost:8001/getorder時,Ribbon底層會自動實現負載均衡。

 

4、服務註冊與發現原理

a、首先啟動eureka註冊中心

b、啟動springcloud-producer或springcloud-consumer後,會將服務別名、服務所在的地址和埠號以鍵值對的形式註冊到eureka註冊中心,如:

key:APP-PRODUCER  value:127.0.0.1:8000, 127.0.0.1:8002

並且每隔一段時間傳送心跳包維持連線

c、當通過springcloud-consumer進行遠端呼叫時,首先通過服務別名(APP-PRODUCER)去註冊中心查詢對應的鍵,獲取對應的值(value:127.0.0.1:8000, 127.0.0.1:8002),當獲取到值的時候,首先快取在本地JVM中,並且快取的值預設每隔30s重新整理一次。之後通過本地負載均衡選取一個服務,底層通過HttpClient技術進行遠端呼叫。

專案原始碼:https://github.com/liuzhoujian/springcloud-eureka