1. 程式人生 > >Spring Cloud學習---服務註冊與發現(Eureka)

Spring Cloud學習---服務註冊與發現(Eureka)

本博目錄:

一、 服務註冊與發現簡介

如何使用Spring Cloud搭建服務註冊與發現模組。

這裡我們會用到Spring Cloud Netflix,該專案是Spring Cloud的子專案之一,Eureka是Spring Cloud Netflix的一個子模組,也是核心模組之一。用於雲端服務發現,一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。通過一些簡單的註解,開發者就可以快速的在應用中使用Eureka。

Eureka 原理,如圖所示:

Eureka架構
由圖可知,Eureka包括兩個元件:Eureka Server 和Eureka Client

Eureka Server:提供服務發現的能力,客戶端微服務啟動時,會向Eureka Server註冊自己的資訊,EurekaServer 會儲存這些資訊。

Eureka Client:是一個Java客戶端,和Eureka Server 進行互動。

注:微服務啟動後,會週期性(30秒)向Eureka Server 傳送心跳以續約自己的“租期”,如果Eureka Server在一定時間之內沒有接收到某個服務的心跳,EurekaServer會登出該例項(90秒之內),綜上,Eureka通過心跳檢測。客戶端快取等機制,提高了系統的靈活性、可伸縮性。

二、編寫 Eureka Server (服務註冊中心)

建立一個基礎的Spring Boot工程,並在pom.xml中引入需要的依賴:

   <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
   </dependency>
   <dependencyManagement>
        <dependencies>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

通過@EnableEurekaServer註解啟動一個服務註冊中心,在Spring Boot應用啟動類中新增這個註解就能開啟此功能,如下:

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerDemoApplication {

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

在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,只需要在application.properties中增加如下配置:

server.port=8671
## 是否將自己註冊到Eureka Server 預設為true
eureka.client.register-with-eureka=false
## 是否從Eureka Server 獲取註冊資訊,預設為true
eureka.client.fetch-registry=false
## 與Eureka server 互動的地址,查詢服務和註冊服務都需要這個地址,多個地址使用“,”分割
eureka.client.service-url.defaultZone=http://localhost:8671/eureka/

三、 Eureka Client (服務提供者)

首先,建立一個基本的Spring Boot應用,在pom.xml中,加入如下配置:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

在主類中通過加上@EnableDiscoveryClient註解,該註解能啟用Eureka中的DiscoveryClient實現,才能實現Controller中對服務資訊的輸出。


@EnableDiscoveryClient
@SpringBootApplication
public class EurekaClientDemoApplication {

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

application.properties專案配置:

##指定註冊到Eureka Server上的應用名稱
spring.application.name=compute-service
server.port=8672
eureka.client.serviceUrl.defaultZone=http://localhost:8671/eureka/

四、 為Eureka提供使用者認證

在之前的例子中,Eureka Server 是允許匿名登入的。新增spring-boot-starter-security的依賴,使得Eureka Server需要登入才能訪問
在pom檔案中新增如下配置:

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

配置檔案中新增:

//開啟基於HTTP basic的認證
security.basic.enabled=true
//登入賬號和密碼
security.user.name=chaole
security.user.password=chao1111

啟動eureka Server ,如圖輸入賬號和密碼即可登入

這裡寫圖片描述

五、 Eureka自我保護模式

Eureka Server 自我保護模式介面

預設情況下,如果Eureka Server在一定時間內沒有接收到某個微服務例項的心跳,Eureka Server將會登出該例項(預設90秒)。但是當網路分割槽故障發生時,微服務與Eureka Server之間無法正常通訊,這就可能變得非常危險了—-因為微服務本身是健康的,此時本不應該登出這個微服務。

Eureka Server通過“自我保護模式”來解決這個問題—-當Eureka Server節點在短時間內丟失過多客戶端時(可能發生了網路分割槽故障),那麼這個節點就會進入自我保護模式。一旦進入該模式,Eureka Server就會保護服務登錄檔中的資訊,不再刪除服務登錄檔中的資料(也就是不會登出任何微服務)。當網路故障恢復後,該Eureka Server節點會自動退出自我保護模式。

自我保護模式是一種對網路異常的安全保護措施。使用自我保護模式,而已讓Eureka叢集更加的健壯、穩定。

在Spring Cloud中,可以使用eureka.server.enable-self-preservation=false來禁用自我保護模式
—- — —— —— —- —– —–可參考《Spring cloud 與 docker 微服務架構實戰》

六、 帶你出坑

在編寫Eureka Server 時,出現了以下錯誤

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.swc.EurekaServerDemoApplication]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.eureka.server.EurekaServerConfiguration
    at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:616) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:299) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at com.swc.EurekaServerDemoApplication.main(EurekaServerDemoApplication.java:12) [classes/:na]
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.eureka.server.EurekaServerConfiguration
    at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.retrieveBeanMethodMetadata(ConfigurationClassParser.java:380) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:314) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:606) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    ... 17 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/FilterRegistrationBean
    at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_131]
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_131]
    at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_131]
    at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    ... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistrationBean
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_131]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_131]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_131]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_131]
    ... 25 common frames omitted

最終才發現,是在pom檔案中,spring cloud 的版本有誤,我引入的版本是
這裡寫圖片描述
這個版本對應的spring boot 版本 是 1.3.5.RELEASE 但我的spring boot 版本是1.5.7.RELEASE,最後修改springcloud版本到 Camden.SR6 即可。
這裡寫圖片描述