Spring Cloud Netflix整合Eureka

Spring-Cloud Euraka是Spring Cloud集合中一個組件,它是對Euraka的集成,用於服務註冊和發現。Eureka是Netflix中的一個開源框架。它和 zookeeper、Consul同樣,都是用於服務註冊管理的,一樣,Spring-Cloud 還集成了Zookeeper和Consul。html

搭建eureka服務註冊中心

引入如下依賴

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 最新版的 eureka 服務端包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <!-- SpringCloud依賴,起到管理版本的做用 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

Spring Cloud 和 Spring Boot 之間版本對應關係

Release Train Boot Version
2020.0.x aka Ilford 2.4.x
Hoxton 2.2.x, 2.3.x (Starting with SR5)
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

在啓動類上添加@EnableEurekaServer註解,代表這是一個Eureka服務端

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {

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

}

在application.properties中添加一些配置

server.port=8080
spring.application.name=Eureka-Server
# 指定了Eureka服務端的IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false
# eureka.client.register-with-eureka=false
# 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false
# eureka.client.fetch-registry=false
# 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8081
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
# 用於定義服務續約任務的調用間隔時間,默認30秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5

配置完畢後啓動服務,訪問http://localhost:8080/

因爲尚未Eureka客戶端將服務註冊進來,因此Instances currently registered with Eureka列表是空的java

搭建provider服務提供者

引入如下依賴

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
        </dependency>
    </dependencies>
    <!-- SpringCloud依賴,起到管理版本的做用 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在啓動類上加@EnableDiscoveryClient註解,代表這是一個Eureka客戶端

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudProviderApplication {

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

}

接着編寫一個TestController,對外提供一些REST服務

@RestController
public class TestController {
    @GetMapping("/hello")
    public String hello() {
        return "hello world";
    }
}

在application.properties中添加一些配置

# 指定了服務的端口爲8081
server.port=8082
# 指定服務名稱爲Server-Provider,後續服務消費者要獲取上面TestController中接口的時候會用到這個服務名
spring.application.name=Server-Provider
# 雖然這兩個配置的默認值就是true,但這裏仍是顯式配置下,使Eureka客戶端的功能更爲直觀(即向服務端註冊服務並定時從服務端獲取服務緩存到本地)
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
# 指定Eureka服務端的地址,這裏爲上面定義的Eureka服務端地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/
# 訪問路徑能夠顯示IP地址
eureka.instance.prefer-ip-address=true

配置好後,啓動Eureka-Client,能夠從控制檯中看到註冊成功的消息

Registered Applications size is zero : true
Application version is -1: true
Getting all instance registry info from the eureka server
The response status is 200
Starting heartbeat executor: renew interval is: 30
InstanceInfoReplicator onDemand update allowed rate per min is 4
Discovery Client initialized at timestamp 1611244216061 with initial instances count: 0
Registering application SERVER-PROVIDER with eureka with status UP
Saw local status change event StatusChangeEvent [timestamp=1611244216076, current=UP, previous=STARTING]
DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081: registering service...
Tomcat started on port(s): 8081 (http) with context path ''
Updating port to 8081
DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081 - registration status: 204

再次訪問http://localhost:8082/,可看到服務列表裏已經出現了名字爲Server-providerde服務了

UP表示在線的意思(若是Eureka客戶端正常關閉,那麼這裏的狀態將變爲DOWN),點擊後面的連接http://192.168.68.233:8081/actuator/info將訪問該服務的/info接口:git

{"app":{"name":"Server-Provider"}}

這時候關閉Eureka客戶端,再次刷新http://localhost:8080/github

可看到雖然Eureka客戶端已經關閉了,可是Eureka服務端頁面的服務服務列表中依然還有該服務,而且頁面紅色文字提示web

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

大體意思是Eureka已經進入了保護模式。微服務在部署以後可能因爲網絡問題形成Eureka客戶端沒法成功的發送心跳給Eureka服務端,這時候Eureka服務端認定Eureka客戶端已經掛掉了,雖然實際上Eureka客戶端還在正常的運行着。而保護模式就是爲了解決這個問題,即當Eureka服務端在短期內同時丟失了過多的Eureka客戶端時,Eureka服務端會進入保護模式,不去剔除這些客戶端。由於咱們這裏只部署了一個Eureka客戶端服務,因此關閉客戶端後知足「短期內丟失過多Eureka客戶端」的條件。spring

在開發中能夠先將保護模式給關了,咱們在Eureka服務端加上一條配置緩存

eureka.server.enable-self-preservation= false

開啓服務監控actuator

引入如下依賴

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

在application.properties中添加一些配置

# 啓用監控
# 開放全部端點health,info,metrics,經過actuator/+端點名就能夠獲取相應的信息。默認打開health和info,metrics默認不開放
management.endpoints.web.exposure.include=*
#未開啓actuator/health時,咱們獲取到的信息是{"status":"UP"},status的值還有多是 DOWN。開啓後打印詳細信息
management.endpoint.health.show-details=always
info.app.name=Server-Provider

訪問路徑

localhost根據本身部署的服務器IP、主機名訪問。 info、health爲默認開放,metrics默認不開放安全

  • 心跳檢查 http://localhost:8081/actuator/info
  • 健康檢查 http://localhost:8081/actuator/health
  • 指標 http://localhost:8081/actuator/metrics

Eureka集羣

ureka服務端充當了重要的角色,全部Eureka客戶端都將本身提供的服務註冊到Eureka服務端,而後供全部服務消費者使用。若是單節點的Eureka服務端宕機了,那麼全部服務都沒法正常的訪問,這必將是災難性的。爲了提升Eureka服務端的可用性,咱們通常會對其集羣部署,即同時部署多個Eureka服務端,而且能夠相互間同步服務。 服務器

在搭建Eureka服務端的時候咱們曾把下面兩個配置給關閉了網絡

eureka.client.register-with-eureka=false

eureka.client.fetch-registry=false

實際上在Eureka集羣模式中,開啓這兩個參數可讓當前Eureka服務端將本身也做爲服務註冊到別的Eureka服務端,而且從別的Eureka服務端獲取服務進行同步。因此這裏咱們將這兩個參數置爲true(默認就是true),下面開始搭建Eureka服務端集羣,爲了簡單起見這裏只搭建兩個節點的Eureka服務端集羣。

兩個applications.properties配置以下

  • 8080端口的Eureka服務端
server.port=8080
spring.application.name=Eureka-Server
# 指定了Eureka服務端的IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false
# eureka.client.register-with-eureka=false
# 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false
# eureka.client.fetch-registry=false
# 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8081
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8081/eureka/
# 用於定義服務續約任務的調用間隔時間,默認30秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5
# 關閉保護模式
eureka.server.enable-self-preservation=false
  • 8081端口的Eureka服務端
server.port=8081
spring.application.name=Eureka-Server
# 指定了Eureka服務端的IP
eureka.instance.hostname=localhost
eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info
eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health
eureka.instance.homePageUrl=http://${eureka.instance.hostname}/
# 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false
# eureka.client.register-with-eureka=false
# 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false
# eureka.client.fetch-registry=false
# 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8080
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8080/eureka/
# 用於定義服務續約任務的調用間隔時間,默認30秒
eureka.client.serviceUrl.registry-fetch-interval-seconds=5
# 關閉保護模式
eureka.server.enable-self-preservation=false

搭建consumer服務消費者

Eureka客戶端便是服務提供者,也是服務消費者,即自身的接口可能被別的服務訪問,同時也可能調用別的服務接口

引入一下依賴

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <!-- SpringCloud依賴,起到管理版本的做用 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在入口類中加入@EnableDiscoveryClient註解用於發現服務和註冊服務,並配置一個RestTemplate Bean,而後加上@LoadBalanced註解來開啓負載均衡

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudConsumerApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

}

編寫一個TestController,用於消費服務

@RestController
public class TestController {
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 注入了RestTemplate,getInfo中使用RestTemplate對象均衡的去獲取服務並消費。
     * 能夠看到咱們使用服務名稱(Server-Provider)去獲取服務的,而不是使用傳統的IP加端口的形式。
     * 這就體現了使用Eureka去獲取服務的好處,咱們只要保證這個服務名稱不變便可,IP和端口再也不是咱們關心的點
     *
     * @return
     */
    @GetMapping("/info")
    public String getInfo() {
        return this.restTemplate.getForEntity("http://Server-Provider/hello", String.class).getBody();
    }
}

在application.properties中添加一些配置

# 指定了服務的端口爲8083
server.port=8083
# 指定服務名稱爲Server-Consumer,後續服務消費者要獲取上面TestController中接口的時候會用到這個服務名
spring.application.name=Server-Consumer
# 雖然這兩個配置的默認值就是true,但這裏仍是顯式配置下,使Eureka客戶端的功能更爲直觀(即向服務端註冊服務並定時從服務端獲取服務緩存到本地)
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
# 指定Eureka服務端的地址,這裏爲上面定義的Eureka服務端地址
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/
# 訪問路徑能夠顯示IP地址
eureka.instance.prefer-ip-address=true

啓動該項目,訪問http://localhost:8083/info

Eureka添加認證

出於安全的考慮,咱們可能會對Eureka服務端添加用戶認證的功能。咱們在Eureka-Server引入Spring-Security依賴

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

而後在application.yml中配置用戶名和密碼

spring.security.user.name=admin
spring.security.user.password=123456

Eureka服務端配置了密碼以後,全部eureka.client.serviceUrl.defaultZone的配置也必須配置上用戶名和密碼,格式爲:eureka.client.serviceUrl.defaultZone=http://${userName}:${password}@${hosetname}:${port}/eureka/,如:

eureka.client.serviceUrl.defaultZone=http://admin:123456@${eureka.instance.hostname}:8080/eureka/

從新打包並部署後,訪問http://localhost:8080/,頁面將彈出驗證窗口,輸入用戶名和密碼後便可訪問

Eureka配置

Eureka中經常使用的配置選項及表明的含義

配置 含義 默認值
eureka.client.enabled 是否啓用Eureka Client true
eureka.client.register-with-eureka 表示是否將本身註冊到Eureka Server true
eureka.client.fetch-registry 表示是否從Eureka Server獲取註冊的服務信息 true
eureka.client.serviceUrl.defaultZone 配置Eureka Server地址,用於註冊服務和獲取服務 http://localhost:8761/eureka
eureka.client.registry-fetch-interval-seconds 默認值爲30秒,即每30秒去Eureka Server上獲取服務並緩存 30
eureka.instance.lease-renewal-interval-in-seconds 向Eureka Server發送心跳的間隔時間,單位爲秒,用於服務續約 30
eureka.instance.lease-expiration-duration-in-seconds 定義服務失效時間,即Eureka Server檢測到Eureka Client木有心跳後(客戶端意外下線)多少秒將其剔除 90
eureka.server.enable-self-preservation 用於開啓Eureka Server自我保護功能 true
eureka.client.instance-info-replication-interval-seconds 更新實例信息的變化到Eureka服務端的間隔時間,單位爲秒 30
eureka.client.eureka-service-url-poll-interval-seconds 輪詢Eureka服務端地址更改的間隔時間,單位爲秒。 300
eureka.instance.prefer-ip-address 表示使用IP進行配置爲不是域名 false
eureka.client.healthcheck.enabled 默認Erueka Server是經過心跳來檢測Eureka Client的健康情況的,經過置爲true改變Eeureka Server對客戶端健康檢測的方式,改用Actuator的/health端點來檢測。 false

Eureka還有許多別的配置,具體能夠參考EurekaClientConfigBeanEurekaServerConfigBeanEurekaInstanceConfigBean配置類的源碼。

References

[1] Spring Cloud Netflix: https://cloud.spring.io/spring-cloud-netflix/reference/html/#service-discovery-eureka-clients

相關文章
相關標籤/搜索