SpringCloud從入門到進階(二)——註冊中心Eureka的僞分佈式部署

內容html

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

版本git

  IDE:IDEA 2017.2.2 x64github

  JDK:1.8.0_171spring

  manve:3.3.3apache

  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信息,那麼調用可能會出錯。

相關文章
相關標籤/搜索