一、註冊中心出現的背景
單體應用經過拆分之後變成多個微服務,每個服務獨立部署,架構也由當初的一臺Nginx負載多個tomcat。例如:現在有2個微服務分別爲服務A和服務B,
服務A調用服務B。服務B部署了3個實例,要將A的請求轉發到服務B的3個實例中有2個方案。
方案1:A服務部署一個nginx維護服務B三個實例的IP地址,如果服務B的實例增加或減少需要通知服務A修改服務B實例的IP。
方案2:服務B自己部署一個Nginx服務維護3個微服務實例的IP地址,如果服務B的實例需要增加或者修改則只需自己修改nginx中的配置就可以,不需要通知服務A去修改Nginx。
二、Eureka-Server註冊中心
註冊中心的出現解決了微服務實例維護困難的問題,所有的微服務將自己的IP和端口地址及相關的信息發送到註冊中心,由註冊中心來維護微服務實例。
CAP理論
在一個分佈式系統中,當涉及讀寫操作時,只能保證一致性(Consistency)、可用性(Availability)、分區容忍性(Partition Tolerance)三者中的兩個,另外一個必須被犧牲。
1.一致性(Consistency)
對於某個指定的客戶端來說,讀操作保證能夠返回最新的寫操作結果。
2.可用性(Availability)
非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)
3.分區容忍性(Partition Tolerance)
當出現網絡分區後,系統能夠繼續提供服務。
Eureka-Server 的複製策略
Eureka-Server 採用的是P2P(對等複製)模式,但是它不保證複製操作一定能成功,因此它提供的是一個最終一致性的服務實例視圖。Client端在Server端的註冊信息有個帶期限的租約,一旦Server端在指定的時間沒有收到Client端發送的心跳,則Server端認爲Client端的服務是不可用的,定時任務會將其從註冊表中刪除。
1.創建spring-cloud-demo
2.創建父模塊spring-cloud-parent
在父模塊中引入相關的依賴
<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>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.2</version>
</dependency>
</dependencies>
3.創建Eureka-Server
pom.xml指定parent並引入eureka-server依賴
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.example</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud-parent/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>${spring-cloud-eureka-server.version}</version>
</dependency>
</dependencies>
配置application.yml
server:
port: 8762
eureka:
instance:
hostname: localhost
# 指定Eureka Client 間隔多久需要向Eureka-Server發送心跳來告知Eureka-Server該實例還存活 默認90
lease-expiration-duration-in-seconds: 10
# 優先使用IP地址
prefer-ip-address: true
client:
# 是否應該將實例註冊到Eureka-Server 默認爲true
register-with-eureka: false
fetch-registry: true
service-url:
defaultZone: http://localhost:8762/eureka/
server:
wait-time-in-ms-when-sync-empty: 0
enable-self-preservation: false
spring:
application:
name: eureka-server
4.創建Eureka-Client 模塊(spring-cloud-service-provide)
配置pom.xml,指定parent並引入eureka-client等相關依賴
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.example</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud-parent/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring-cloud-starter-openfeign.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<!--<version>${spring-cloud-eureka-client.version}</version>-->
</dependency>
</dependencies>
配置application.yml,將服務註冊到Eureka-Server
server:
port: 8086
spring:
application:
name: cloud-service-provide
eureka:
instance:
hostname: localhost
prefer-ip-address: true
lease-expiration-duration-in-seconds: 10
client:
serviceUrl:
# 註冊到Eureka-Server
defaultZone: http://localhost:8762/eureka/
分別啓動Eureka-Server和Eureka-Client,通過瀏覽器訪問註冊中心http://localhost:8762,可以看到cloud-serivce-provide已經註冊到Eureka-Server
三、Eureka-Server rest api
操作 | 請求類型 | URL | 描述 |
---|---|---|---|
註冊服務實例 | POST | /eureka/apps/{appId} | 可以輸入json或xml格式的body數據,成功返回204 |
註銷應用實例 | DELETE | /eureka/apps/{appId}/{instanceId} | 成功返回200 |
應用實例發送心跳 | PUT | /eureka/apps/{appId}/{instanceId} | 成功返回200,如果instanceId不存在返回404 |
查詢所有實例 | GET | /eureka/apps | 成功返回200,輸出json或xml格式數據 |
查詢指定appId的實例 | GET | /eureka/apps/{appId} | 成功返回200,輸出json或xml格式數據 |
根據appId和instanceId查詢 | GET | /eureka/apps/{appId}/{instanceId} | 成功返回200,輸出json或xml格式 |
根據指定instanceId查詢 | GET | /eureka/instances/{instanceId} | 成功返回200,輸出json或xml格式 |
暫停應用實例 | PUT | /eureka/apps/{appId}/{instanceId}/status?value=OUT_OF_SERVER | 成功返回200,失敗返回500 |
恢復應用實例 | DELETE | /eureka/apps/{appId}/{instanceId}/status?value=UP | 成功返回200,失敗返回500 |
更新元數據 | PUT | /eureka/apps/{appId}/{instanceId}/metadata?key=value | 成返回200,失敗返回500 |
根據vip地址查詢 | GET | /eureka/vips/{vipAddress} | 成返回200,輸出json或xml |
根據svip地址查詢 | GET | /eureka/svips/{svipAddress} | 成功返回200,輸出json或xml格式數據 |