Spring Cloud構(gòu)建微服務架構(gòu)第四章:eureka集群高可用配置

  • 譬如eureka.client.register-with-eureka和fetch-registry是否要配置,配不配區(qū)別在哪里;
  • eureka的客戶端添加service-url時,是不是需要把所有的eureka的server地址都寫上,還是只需要寫一個server就可以了(因為server之間已經(jīng)相互注冊了)?如果寫上了所有的server地址,那相當于將每個client服務都往所有的server都添加了一遍,那還配置server間的相互注冊有什么意義?

上面的這些問題在多數(shù)講eureka集群教程里都沒有說明白,上來就是配server相互注冊,client添加所有的server地址,大大的誤導了我一把。專門從頭新建了項目來看看到底eureka集群是該怎么配置。

server端配置

創(chuàng)建個eureka server項目
pom.xml如下:

<?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.tianyalei</groupId>
   <artifactId>eureka_server</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>eureka_server</name>
   <description>Demo project for Spring Boot</description>

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.5.7.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>
       <spring-cloud.version>Dalston.SR4</spring-cloud.version>
   </properties>

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

application.yml如下

spring:
  resources:
    chain:
      cache: true #pring Boot Maven項目中的resource文件夾下的資源不進行緩存處理,即每次都需要去加載。生產(chǎn)環(huán)境設置為true
  profiles:
    active: server1

我用同一個項目打算啟動兩個server服務,占用不同的端口,以此模擬eureka服務集群。
添加了一個application-server1.yml

server:
  port: 20001
eureka:
  instance:
    hostname: server1
  client:
    # 表示是否注冊自身到eureka服務器
    # register-with-eureka: false
    # 是否從eureka上獲取注冊信息
    # fetch-registry: false
    service-url:
      defaultZone: http://server2:20002/eureka/

再添加一個application-server2.yml

server:
  port: 20002
eureka:
  instance:
    hostname: server2
  client:
    #register-with-eureka: false
    #fetch-registry: false
    service-url:
      defaultZone: http://server1:20001/eureka/

可以看到我指定了不同的端口,并且service-url這里是重點,我將server1的service-url設置為server2,將server2的設置為server1.以此完成兩個server服務間的相互注冊,這和別的文章里講的是一樣的,照著敲就OK。還有我把register和fetch那兩個配置注釋掉了,后面我們會放開,看看有沒有這個配置的區(qū)別。
instance.hostname是唯一標識。
由于我們使用了http://server1這種寫法,需要配一下host。Windows的host在/etc/host,mac的在/private/etc

image.png

然后在啟動類上加上EnableEurekaServer注解即可。

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

下面我們來看如何分別用server1和server2兩個配置啟動兩個server服務。
在idea右上角run,選擇edit configrations


image.png

原本應該只有一個啟動項,點擊+號,給兩個啟動項都設置一下Program arguments,就是--spring.profiles.active分別設置為server1和server2,代表分別以兩個不同的配置來啟動項目。
然后把兩個啟動項都啟動起來,分別訪問各自的端口


image.png

可以看到圖上registered-replicas和available-replicas分別有了對方的地址。
eureka服務端的配置就這樣就OK了。

client端配置

新建一個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.tianyalei</groupId>
    <artifactId>eureka_client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>eureka_client</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.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>
        <spring-cloud.version>Dalston.SR4</spring-cloud.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>${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>

application.yml如下

spring:
  application:
    name: eureka_client
eureka:
  client:
    service-url:
      defaultZone: http://server1:20001/eureka/

defaultZone這里代表eureka server的地址,很多文章在這里會將所有的server都配置上去,用逗號分隔,我們這里只配置一個server1,然后測試一下如果server1掛掉了,服務中心還能不能起作用。
在啟動類上加注解eurekaClient注解

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

然后啟動項目
再看看server端的界面


image.png

可以看到eureka_client已經(jīng)在兩個server上都注冊上了,雖然我們在client的yml里default_zone只配置了server1。這是因為eureka是通過在各個節(jié)點進行復制來達到高可用的目的。
測試很簡單,我們直接關掉server1,然后看看server2是否還能維持住client的發(fā)現(xiàn)。
關掉server1,20001的網(wǎng)頁已經(jīng)打不開了,20002上也已經(jīng)沒有了20001的服務發(fā)現(xiàn),控制臺在一直報錯。


image.png

image.png

但是我們看到client的注冊信息還在,這說明server2還能繼續(xù)提供注冊發(fā)現(xiàn)的服務,這樣就避免了單點故障后的整體服務發(fā)現(xiàn)的癱瘓。
但是需要注意的是,因為大家都在server1進行的注冊,如果server1掛掉了,那么后續(xù)的client就無法再注冊上來,重啟Client后也無法再注冊到eureka上來。

這就是為什么很多人在Client端添加多個eureka地址的原因!是避免自己注冊的eureka單點掛掉。只要自己注冊的eureka還在,那么后續(xù)添加N個eureka的其他server,所有注冊信息都會被復制過去。

而事實上,eureka的注冊信息不僅僅復制在server端,也會復制到client端。也就是說,即便eureka的server全部掛掉,client間任然是可以互通的!譬如client1 client2都已經(jīng)注冊在了server1 server2上,即便server1 server2全死掉了,Client1還是可以和client2進行互通,因為eureka的客戶端也會復制所有的注冊信息,當server全死掉后,客戶端會根據(jù)自己本地的備份進行連接。

下面我們可以測試一下把server端yml里配置register-with-eureka: false的那兩行注釋給放開,看看eureka的server忽略自己后,是否能完成服務發(fā)現(xiàn)的高可用。
測試很簡單,可以看到和上面的最終結(jié)果是一樣的,都是server1關閉后,server2依舊能進行client的發(fā)現(xiàn)。區(qū)別在于


image.png

這個就是和之前注釋掉后界面不同的地方。
至于在client端配置所有的server地址,各位可以自行嘗試。

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

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

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