SpringCloud從入門到進階(二)——注冊中心Eureka的偽分布式部署


內容

  服務發現是微服務架構中一個關鍵的原則,Eureka提供了服務注冊和服務發現的功能,並且各注冊中心之間會互相拷貝所注冊的微服務的信息,這一機制增強了Eureka對網絡分區的容錯能力。本篇文章講解了在一台主機上運行三個Eureka Server實例,實現Eureka的偽分布式部署。

版本

  IDE:IDEA 2017.2.2 x64

  JDK:1.8.0_171

  manve:3.3.3

  SpringBoot:1.5.9.RELEASE

  SpringCloud:Dalston.SR1

適合人群

  Java開發人員

說明

  轉載請說明出處:SpringCloud從入門到進階(二)——注冊中心Eureka的偽分布式部署

  GitHub倉庫地址:https://github.com/leo-zz/SpringCloudDemo/tree/master/EurekaServer

參考

       Linux入門實踐筆記(二)--Jar包運行與關閉

內容

Eureka工作機制

​  Eureka就像開發公司的人事部,人事部維護了公司的通訊錄,通過通訊錄可以找到每一名員工的聯系方式。正如人員在入職和離職時,人事部會更新公司的通訊錄一樣;當服務上線或者下線時,Eureka都會進行服務的注冊和注銷的操作。

  Eureka分為Server端和Client,包括Eureka Server在內(默認設置)的所有的微服務組件都屬於Eureka Client。Eureka Client在服務啟動時會注冊到Eureka Server中,並在運行過程中定時向Eureka Server發送心跳以保持注冊狀態。Eureka Server把所有的注冊信息都存儲到內存中,並沒有進行持久化存儲。此外,每個Eureka Client都在內存中緩存一份Eureka Clients的注冊信息,使的它在請求其他微服務時無需每次都從Eureka Server獲取。本文主要講解了Eureka Server的配置。
  默認情況下,Eureka Client使用主機名進行注冊,這個主機名可以使用eureka.instance.hostname來規定。微服務之間也是通過主機名來調用的。如果DNS沒有配置主機名跟IP的映射關系,那么使用主機名注冊的方式就會導致微服務無法調用。可以修改eureka.instance.preferIpAddress為true,讓Eureka Client注冊時使用IP地址,本示例就是通過IP的方式注冊微服務的。

兩種工作模式

  Eureka Server有兩種工作模式,單機模式(Standalone Mode)和集群模式(Peer Awareness)。

單機模式

  默認情況下每個Eureka Server都是一個Eureka Client,有着Eureka Client的行為,在啟動時會向Eureka Server進行注冊,因此需要配置“service-url”以定位其他Eureka Server。如果沒有正確的配置該參數,Eureka Server雖然會正常工作,但是日志上會有許多“無法注冊到其他Eureka Server”的干擾信息。
  如果想在單機模式下使用Eureka Server,需要修改配置eureka.client.registerWithEureka 和 eureka.client.fetchRegistry為false,以關閉其Eureka Client的行為,避免向Eureka Server注冊。本示例搭建的是Eureka Server的集群模式,不討論單機模式的情況。

集群模式

  通過啟動多個Eureka Server實例,並將它們互相注冊以組建集群。集群模式有着更高的可用性。這也是Eureka Server默認的工作模式,在“service-url”上配置其他Eureka Server實例(peer)的地址。
  集群中的實例不要求必須能夠兩兩互相訪問,只要能夠組建出一條連接鏈,集群之間就可以互相同步注冊信息。比如三個實例A、B、C,A跟B可以互相訪問,B跟C可以互相訪問,但是A與C不能互相訪問,那么A、B、C組建的集群仍然可以在所有實例之間互相同步注冊信息。即使集群中的部分實例被物理分割,Eureka在原則上可以避免集群分區類型的故障(腦裂問題)。

項目路徑

pom.xml

  配置maven的依賴文件pom.xml,引入SpringBoot,SpringCloud,Eureka的依賴,以及Spring Boot打包的Maven插件。

<?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.leo.springcloud</groupId>
    <artifactId>eurekaserver</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 通過繼承的方式引入spring boot -->
    <!--parent標簽用於指定父pom-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <!--properties標簽用於聲明一些常量,例如源碼編碼為UTF-8,輸出代碼也為UTF-8,Java版本為1.8-->
    <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.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <!--子Module不會繼承該依賴,除非顯示聲明-->
    <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>

    <!-- Spring Boot的Maven插件,使用Maven插件的方式來啟動Spring Boot工程 如果不添加該插件在使用mvn命令打包的jar有問題,執行時會報錯:xxx.jar中沒有主清單屬性-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
yaml

  配置Eureka的yaml文件,此處按照集群模式配置Eureka,配置了三個profiles,以便在同一台機器上使用同一個jar包開啟三個Eureka實例。

spring: profiles: peer1 application: name: application-eurekaserver server: port: 7001 eureka: instance:
  #設置實例的hostname
    hostname: eureka7001.com instance-id: springcloud-eurekaserver-7001
    #作為Eureka Client,把實例的ip的信息注冊到eureka server中。
    prefer-ip-address: true client:
    #不將eureka server 注冊進來,會提示unavailable-replicas
    #默認情況下,Eureka Server會向自己注冊,這時需要配置eureka.client.registerWithEureka 和 eureka.client.fetchRegistry為false,防止自己注冊自己。
    register-with-eureka: true fetch-registry: true service-url:
    #defaultZone中填寫的URL必須包括后綴/eureka,否則各eureka server之間不能通信
    #defaultZone為默認的Zone,來源於AWS的概念。區域(Region)和可用區(Availability Zone,AZ)是AWS的另外兩個概念。區域是指服務器所在的區域,
    #比如北美洲、南美洲、歐洲和亞洲等,每個區域一般由多個可用區組成。 在本案例中defaultZone是指Eureka Server的注冊地址。
     defaultZone: http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka #eureka集群的時候使用
      #http://${eureka.instance.hostname}:${server.port}/eureka/ #eureka單機模式的時候使用,指向自己。 # server: # enable-self-preservation: false #關閉自我保護機制 #actuator
management: port: 7101  #配置了Actuator對外暴露REST API接口的端口號,如果不指定,端口為應用程序的啟動端口,這樣做的目的是將程序端口和程序的監控端口分開。
  security: enabled: false #Actuator 采取非安全驗證方式,l.5x 版本默認開啟了 Actuator 的安全驗證。​
--- spring: profiles: peer2 application: name: application-eurekaserver server: port: 7002 eureka: instance: hostname: eureka7002.com instance-id: springcloud-eurekaserver-7002 prefer-ip-address: true client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7003.com:7003/eureka #eureka集群的時候使用 #actuator
management: port: 7102  #配置了Actuator對外暴露REST API接口的端口號,如果不指定,端口為應用程序的啟動端口,這樣做的目的是將程序端口和程序的監控端口分開。
  security: enabled: false #Actuator 采取非安全驗證方式,l.5x 版本默認開啟了 Actuator 的安全驗證。
--- spring: profiles: peer3 application: name: application-eurekaserver server: port: 7003 eureka: instance: hostname: eureka7003.com instance-id: springcloud-eurekaserver-7003 prefer-ip-address: true client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #eureka集群的時候使用 #actuator
management: port: 7103  #配置了Actuator對外暴露REST API接口的端口號,如果不指定,端口為應用程序的啟動端口,這樣做的目的是將程序端口和程序的監控端口分開。
  config: enabled: false #Actuator 采取非安全驗證方式,l.5x 版本默認開啟了 Actuator 的安全驗證。
SpringBootApplication

  配置SpringBoot的啟動類,增加@EnableEurekaServer注解。

@SpringBootApplication @EnableEurekaServer public class EurekaServerDemo { public static void main(String[] args) { SpringApplication.run(EurekaServerDemo.class,args); } }
項目打包

  在命令行工具中進入項目pom文件所在路徑,然后執行mvn clean package打包。

F:\SpringCloud>cd eureka-server-7001-7002 #進入項目根目錄 F:\SpringCloud\eureka-server-7001-7002>mvn clean package #執行maven打包語句 ... [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 29.597 s [INFO] Finished at: 2018-10-23T09:14:11+08:00 [INFO] Final Memory: 35M/293M ...
拷貝

  由於當時注冊發現服務沒有開通公網,需要使用Bitvise SFTP或WinSCP等工具將jar包上傳到有公網的服務器。然后再使用scp命令在局域網內從公網服務器拷貝到注冊發現服務器。

1540257784254

  然后使用scp命令將jar包拷貝到注冊發現服務器普通用戶的~/jars路徑下。

[ServerA@hostname jars]$ scp eureka-server-7001-7002-1.0-SNAPSHOT.jar  user@172.26.125.118:/home/user/jars ... eureka-server-7001-7002-1.0-SNAPSHOT.jar                                           100%   38MB  38.4MB/s   00:00
修改hosts文件

  將內部域名eureka7001.com、eureka7002.com、eureka7003.com綁定到局域網IP 172.26.125.118。

  修改/etc/hosts,添加hostname對應的ip地址

#IP 域名 別名 [user@EurekaServer ~]$ sudo vi /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1   eureka7003.com

  重啟網卡

[user@EurekaServer ~]$ sudo /etc/rc.d/init.d/network restart Restarting network (via systemctl): [ OK ]

  進行ping測試

[user@EurekaServer ~]$ ping eureka7001.com PING eureka7001.com (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.016 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms [user@EurekaServer ~]$ ping eureka7002.com PING eureka7002.com (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.012 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms [user@EurekaServer ~]$ ping eureka7003.com PING eureka7003.com (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.012 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.024 ms
啟動與測試

  在啟動時,通過JVM參數-Dspring.profiles.active選擇項目啟動的profiles。此處還設定了虛擬機堆空間的最小值為512mb,堆空間的最大值為1024mb。

[ServerA@hostname jars]$ java  -Xms512m -Xmx1024m -Dspring.profiles.active=peer1 -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar [ServerA@hostname jars]$ java -Xms512m -Xmx1024m -Dspring.profiles.active=peer2  -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar [ServerA@hostname jars]$ java -Xms512m -Xmx1024m -Dspring.profiles.active=peer3  -jar eureka-server-7001-7002-1.0-SNAPSHOT.jar  

  確保本地能訪問到eureka服務器,訪問http://eureka7001:7001/

  訪問http://eureka7002:7002/

 

  訪問http://eureka7003:7003/

 

  關於運行和關閉java程序的操作請參考:Linux入門實踐筆記(二)--Jar包運行與關閉

  通過Eureka的管理界面,可以看到所有Eureka的replicas的都是unavailable狀態。下一節將在源碼層級探究replicas為何是unavailable狀態的原因,以及解決方法。

補充:關於Eureka client注冊ip信息和主機名這兩種方式的說明  

  集群模式下的Eureka Server,同時也是Eureka Client,因此會向Eureka Server中注冊自己的信息。Eureka Server的yaml配置的中prefer-ip-address屬性為true,表示這個實例把IP地址注冊到Eureka Server中,並不會要求或者限制其他Eureka Client的注冊行為。筆者曾誤以為Eureka Server的yaml配置的中prefer-ip-address屬性為true,會要求所有向該Eureka Server注冊的Client在注冊時都提交IP信息。顯然這是錯誤的。

  對於Eureka Server,不會限制Client以哪種信息注冊,這個選擇權在Client。比如ClientA把自己的ip信息注冊到Eureka,而ClentB把自己的主機名注冊到Eureka,那么ClientC在調用ClientA時會從Eureka中拿到它的ip信息進行調用;在調用ClientB時會從Eureka中拿到它的主機名信息進行調用,如果此時未配置主機名和ip的DNS信息,那么調用可能會出錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM