內容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
參考
內容
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在原則上能夠避免集羣分區類型的故障(腦裂問題)。
配置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>
配置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 的安全驗證。
配置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命令在局域網內從公網服務器拷貝到註冊發現服務器。
而後使用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
將內部域名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/
關於運行和關閉java程序的操做請參考:Linux入門實踐筆記(二)--Jar包運行與關閉
經過Eureka的管理界面,能夠看到全部Eureka的replicas的都是unavailable狀態。下一節將在源碼層級探究replicas爲什麼是unavailable狀態的緣由,以及解決方法。
集羣模式下的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信息,那麼調用可能會出錯。