Spring Cloud(二):Eureka 服務(wù)注冊(cè)中心

前言

服務(wù)治理

隨著業(yè)務(wù)的發(fā)展,微服務(wù)應(yīng)用也隨之增加,這些服務(wù)的管理和治理會(huì)越來越難,并且集群規(guī)模、服務(wù)位置、服務(wù)命名都會(huì)發(fā)生變化,手動(dòng)維護(hù)的方式極易發(fā)生錯(cuò)誤或是命名沖突等問題。而服務(wù)治理正是為了解決這個(gè)問題,服務(wù)治理是微服務(wù)架構(gòu)中最為核心和基礎(chǔ)的模塊,它主要實(shí)現(xiàn)各個(gè)微服務(wù)實(shí)例的自動(dòng)化注冊(cè)和發(fā)現(xiàn)。

服務(wù)注冊(cè)

在服務(wù)治理框架中,都會(huì)構(gòu)建一個(gè)或多個(gè)服務(wù)注冊(cè)中心。

每個(gè)服務(wù)模塊向注冊(cè)中心登記自己所提供的服務(wù),將主機(jī)host、端口號(hào)、版本號(hào)、通信協(xié)議等一些附加信息告知注冊(cè)中心,注冊(cè)中心按服務(wù)名分類組織服務(wù)清單。

服務(wù)注冊(cè)中心還需要以心跳的方式去監(jiān)測(cè)清單中的服務(wù)是否可用,若不可用需要從服務(wù)清單中剔除,達(dá)到排除故障服務(wù)的效果。

服務(wù)發(fā)現(xiàn)

服務(wù)間調(diào)用不再通過指定具體實(shí)例地址來實(shí)現(xiàn),而是通過向服務(wù)名發(fā)起請(qǐng)求調(diào)用實(shí)現(xiàn)。

服務(wù)調(diào)用方需要先從服務(wù)注冊(cè)中心獲取所有服務(wù)的實(shí)例清單,才能實(shí)現(xiàn)對(duì)具體服務(wù)實(shí)例的訪問。

服務(wù)調(diào)用方在發(fā)起調(diào)用時(shí),會(huì)以某種策略取出一個(gè)具體的服務(wù)實(shí)例進(jìn)行服務(wù)調(diào)用(客戶端負(fù)載均衡)。

在生產(chǎn)環(huán)境中為了考慮性能等因素,不會(huì)采用每次都向服務(wù)注冊(cè)中心獲取服務(wù)的方式,并且不同的應(yīng)用場(chǎng)景在緩存和服務(wù)剔除等機(jī)制上也會(huì)采用不同的實(shí)現(xiàn)策略。

Spring Cloud Eureka

Spring Cloud Eureka 是基于 Netflix Eureka 來實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)的。它主要包括兩個(gè)組件:

  • Eureka Server(服務(wù)端):服務(wù)注冊(cè)中心,支持高可用配置,依托于強(qiáng)一致性提供良好的服務(wù)實(shí)例可用性,服務(wù)注冊(cè)中心之間可以通過異步模式互相復(fù)制各自的狀態(tài)。
  • Eureka Client(客戶端):處理服務(wù)的注冊(cè)與發(fā)現(xiàn),客戶端可以通過注解和參數(shù)配置的方式實(shí)現(xiàn)注冊(cè)與發(fā)現(xiàn),客戶端向注冊(cè)中心注冊(cè)自身提供的服務(wù)并周期性地發(fā)送心跳來更新它的服務(wù)租約,Eureka客戶端從服務(wù)端查詢當(dāng)前注冊(cè)的服務(wù)信息并把它們緩存到本地并周期性的刷新服務(wù)狀態(tài)。

Eureka 基礎(chǔ)架構(gòu)

  • 服務(wù)注冊(cè)中心(Eureka Server):服務(wù)端,提供服務(wù)注冊(cè)和發(fā)現(xiàn)功能。
  • 服務(wù)提供者(Service Provider):提供服務(wù)的應(yīng)用,將自己提供的服務(wù)注冊(cè)到 Eureka Server,供其他應(yīng)用發(fā)現(xiàn)。
  • 服務(wù)消費(fèi)者(Service Consumer):消費(fèi)者應(yīng)用從 Eureka Server 獲取服務(wù)列表,從而調(diào)用對(duì)應(yīng)的服務(wù)(ribbon或者feign)。

基礎(chǔ)架構(gòu)圖


image

image

快速搭建服務(wù)注冊(cè)中心(Eureka Server)

1. 創(chuàng)建 Spring Boot 項(xiàng)目,添加依賴

<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>

2. @EnableEurekaServer 注解啟動(dòng)服務(wù)注冊(cè)中心

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaServerApplication {

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

}

3. 配置文件 application.properties

server.port=9999
#eureka
eureka.instance.hostname=127.0.0.1
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
  • eureka.client.register-with-eureka:當(dāng)前應(yīng)用為服務(wù)注冊(cè)中心,所以設(shè)置為false,代表不向注冊(cè)中心注冊(cè)自己。
  • eureka.client.fetch-registry:注冊(cè)中心的職責(zé)主要是維護(hù)服務(wù)實(shí)例,所以設(shè)置為false,代表不去檢索當(dāng)前應(yīng)用的服務(wù)。
  • eureka.client.serviceUrl.defaultZone:用于與 Eureka Server 交互的地址,注冊(cè)服務(wù)和發(fā)現(xiàn)服務(wù)都需要依賴這個(gè)地址。

4.啟動(dòng)應(yīng)用,訪問:http://127.0.0.1:9999/

可以看到 Eureka 的信息面板,其中 Instances currently registered with Eureka 中列表顯示 No instances available,說明該注冊(cè)中心還沒有注冊(cè)任何服務(wù)。


image

服務(wù)提供者(Service Provider)

1. 創(chuàng)建 Spring Boot 項(xiàng)目,添加依賴

<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <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-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>

2. @EnableDiscoveryClient 注解啟動(dòng) Eureka 客戶端

@SpringBootApplication
//@EnableEurekaClient  該注解在采用eureka作為注冊(cè)中心時(shí)使用,場(chǎng)景較為單一
@EnableDiscoveryClient //場(chǎng)景更為廣泛
public class SpringCloudEurekaServiceApplication {

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

}

@EnableEurekaClient@EnableDiscoveryClient 在當(dāng)前示例中使用效果好是一樣的,@EnableEurekaClient 注解在采用eureka作為注冊(cè)中心時(shí)使用,場(chǎng)景較為單一,@EnableDiscoveryClient 場(chǎng)景更為廣泛。

3. 配置文件 application.properties

server.port=8888
spring.application.name=spring-cloud-eureka-service
#info 應(yīng)用信息
info.app.name=spring-cloud-eureka-service
info.app.version=v1.0.0
info.app.description=spring-cloud-eureka-service
#eureka
eureka.instance.hostname=127.0.0.1
#每隔5s心跳一次,證明本服務(wù)還活著
eureka.instance.lease-renewal-interval-in-seconds=5
#本服務(wù)10s內(nèi)沒有心跳,就將該服務(wù)從服務(wù)端剔除
eureka.instance.lease-expiration-duration-in-seconds=10
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:9999/eureka/

  • eureka.instance.lease-renewal-interval-in-seconds:設(shè)置心跳間隔秒數(shù)
  • eureka.instance.lease-expiration-duration-in-seconds:設(shè)置秒數(shù)內(nèi)無心跳,則剔除服務(wù)

4. 啟動(dòng)應(yīng)用,訪問:http://127.0.0.1:9999/

在服務(wù)注冊(cè)中心的控制臺(tái)中我們可以看到如下輸出,說明服務(wù)被注冊(cè)成功了。

 c.n.e.registry.AbstractInstanceRegistry  : Registered instance SPRING-CLOUD-EUREKA-SERVICE/192.168.101.201:spring-cloud-eureka-service:8888 with status UP (replication=false)

而在 Eureka 的信息面板上,在 Instances currently registered with Eureka 列表中同樣可以看到服務(wù)的注冊(cè)信息。如下圖:

image

高可用注冊(cè)中心(集群)

上面介紹了單節(jié)點(diǎn)模式的服務(wù)注冊(cè)中心,不過在實(shí)際生產(chǎn)環(huán)境中,通常不會(huì)采用這種模式。在分布式系統(tǒng)中,服務(wù)注冊(cè)中心是非常重要的組成部分,如果是單節(jié)點(diǎn)模式,發(fā)生故障的話將會(huì)是毀滅性的災(zāi)害。所以為了維護(hù)服務(wù)的高可用性,通常采用集群的解決方案。

Eureka 的服務(wù)治理設(shè)計(jì)中,所有的節(jié)點(diǎn)既是服務(wù)提供方,也是服務(wù)消費(fèi)方,服務(wù)注冊(cè)中心也不例外。Eureka 通過互相注冊(cè)服務(wù)的方式,以實(shí)現(xiàn)服務(wù)清單的互相同步,達(dá)到高可用的效果。

雙節(jié)點(diǎn)注冊(cè)中心

  1. 搭建服務(wù)注冊(cè)中心 A,配置文件如下:
server.port=9991
spring.application.name=eureka-server
spring.profiles.active=nodea
#eureka
eureka.instance.hostname=nodea
#設(shè)置微服務(wù)調(diào)用地址為IP優(yōu)先(缺省為false)
#eureka.instance.prefer-ip-address=true
eureka.client.serviceUrl.defaultZone=http://nodeb:9992/eureka/
  1. 搭建服務(wù)注冊(cè)中心 B,配置文件如下:
server.port=9992
spring.application.name=eureka-server
spring.profiles.active=nodeb
#eureka
eureka.instance.hostname=nodeb
#設(shè)置微服務(wù)調(diào)用地址為IP優(yōu)先(缺省為false)
#eureka.instance.prefer-ip-address=true
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/
  1. 在 /etc/hosts(windows系統(tǒng)路徑為 C:\Windows\System32\drivers\etc\hosts) 文件中添加 nodea 和 nodeb 的轉(zhuǎn)換,如下:
127.0.0.1 nodea
127.0.0.1 nodeb
  1. 啟動(dòng)兩個(gè)項(xiàng)目,分別訪問http://nodea:9991/http://nodeb:9992/,我們可以看到兩個(gè)節(jié)點(diǎn)都已經(jīng)被注冊(cè),如下圖所示:
image
  1. 搭建完多節(jié)點(diǎn)服務(wù)注冊(cè)中心之后,服務(wù)提供者也需要做一些簡單的配置,以上面的服務(wù)提供者為例,修改如下:
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/

啟動(dòng)項(xiàng)目后,訪問兩個(gè)服務(wù)注冊(cè)中心,我們看到服務(wù)被注冊(cè)到這兩個(gè)節(jié)點(diǎn)內(nèi)。

image
  1. 這時(shí)我們關(guān)閉服務(wù)注冊(cè)中心節(jié)點(diǎn) A,我們可以看到服務(wù)注冊(cè)中心節(jié)點(diǎn) B 依然可以提供服務(wù),而節(jié)點(diǎn) A 從 available-replicas(可以分片) 變?yōu)?unavailable-replicas(不可用分片)。
image

服務(wù)消費(fèi)者(Service Consumer)

使用 Ribbon 調(diào)用服務(wù)

1. pom 相關(guān)依賴配置
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </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>

2. 配置文件 application.properties
spring.application.name=spring-cloud-ribbon-consumer
server.port=8081
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/
3. 啟動(dòng)類配置

通過 @EnableDiscoveryClient 注解將應(yīng)用注冊(cè)為 Eureka 客戶端,獲得服務(wù)發(fā)現(xiàn)能力。

創(chuàng)建 RestTemplate 的 Spring Bean 實(shí)例用來調(diào)用服務(wù)。

通過 @LoadBalanced 注解來開啟客戶端的負(fù)載均衡。

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudRibbonConsumerApplication {

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

}
4. ConsumerController 來實(shí)現(xiàn)服務(wù)調(diào)用
@RestController
public class ConsumerController {

    @Autowired
    RestTemplate restTemplate;
    
    @RequestMapping("/test")
    public String test() {
        return restTemplate.getForEntity("http://spring-cloud-eureka-service/test", String.class).getBody();
    }
}

spring-cloud-eureka-service 為服務(wù)注冊(cè)中心的應(yīng)用名稱,大小寫均可。

使用 Feign 調(diào)用服務(wù)

1. pom 相關(guān)依賴配置
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </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>
2. 配置文件 application.properties
spring.application.name=spring-cloud-feign-consumer
server.port=8080
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/
3. 啟動(dòng)類配置

通過 @EnableDiscoveryClient 注解將應(yīng)用注冊(cè)為 Eureka 客戶端,獲得服務(wù)發(fā)現(xiàn)能力。

通過 @EnableFeignClients 注解來啟用feign進(jìn)行遠(yuǎn)程調(diào)用。

@SpringBootApplication
@EnableDiscoveryClient//啟用服務(wù)注冊(cè)與發(fā)現(xiàn)
@EnableFeignClients//啟用feign進(jìn)行遠(yuǎn)程調(diào)用
public class SpringCloudFeignConsumerApplication {

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

}
4. 實(shí)現(xiàn)服務(wù)調(diào)用接口
@FeignClient(name = "spring-cloud-eureka-service")
public interface TestService {

    @RequestMapping("/test")
    public String test();
}

spring-cloud-eureka-service 為服務(wù)注冊(cè)中心的應(yīng)用名稱,大小寫均可。

此接口中的方法和遠(yuǎn)程服務(wù)中contoller中的方法名和參數(shù)需保持一致。

5. ConsumerController 來實(shí)現(xiàn)服務(wù)調(diào)用
@RestController
public class ConsumerController {

    @Autowired
    private TestService testService;
    
    @RequestMapping("/test")
    public String test() {
        return testService.test();
    }
}

示例代碼

github

碼云

非特殊說明,本文版權(quán)歸 朝霧輕寒 所有,轉(zhuǎn)載請(qǐng)注明出處.

原文標(biāo)題:Spring Cloud(二):Eureka 服務(wù)注冊(cè)中心

原文地址: https://www.zwqh.top/article/info/28

如果文章有不足的地方,歡迎提點(diǎn)建議,后續(xù)會(huì)完善~

如果文章對(duì)您有幫助,請(qǐng)給我點(diǎn)個(gè)贊哦~

關(guān)注下我的公眾號(hào),文章持續(xù)更新中...

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容