注冊(cè)中心-Eureka
介紹
又稱服務(wù)中心,管理各種服務(wù)功能包括服務(wù)的注冊(cè)、發(fā)現(xiàn)、熔斷、負(fù)載、降級(jí)等。
任何一個(gè)服務(wù)都不能直接去掉用,都需要通過(guò)注冊(cè)中心來(lái)調(diào)用。通過(guò)服務(wù)中心來(lái)獲取服務(wù)你不需要關(guān)注你調(diào)用的項(xiàng)目IP地址,由幾臺(tái)服務(wù)器組成,每次直接去服務(wù)中心獲取可以使用的服務(wù)去調(diào)用既可。
由于各種服務(wù)都注冊(cè)到了服務(wù)中心,就有了很多高級(jí)功能條件。比如幾臺(tái)服務(wù)提供相同服務(wù)來(lái)做客戶端負(fù)載均衡(Ribbon);監(jiān)控服務(wù)器調(diào)用成功率來(lái)做斷路器(Hystrix),移除服務(wù)列表中的故障點(diǎn);監(jiān)控服務(wù)調(diào)用時(shí)間來(lái)對(duì)不同的服務(wù)器設(shè)置不同的權(quán)重、智能路有(Zuul)等等。
Spring Cloud 封裝了 Netflix 公司開發(fā)的 Eureka 模塊來(lái)實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)。Eureka 采用了 C-S 的設(shè)計(jì)架構(gòu)。Eureka Server 作為服務(wù)注冊(cè)功能的服務(wù)器,它是服務(wù)注冊(cè)中心。而系統(tǒng)中的其他微服務(wù),使用 Eureka 的客戶端連接到 Eureka Server,并維持心跳連接。這樣系統(tǒng)的維護(hù)人員就可以通過(guò) Eureka Server 來(lái)監(jiān)控系統(tǒng)中各個(gè)微服務(wù)是否正常運(yùn)行。Spring Cloud 的一些其他模塊(比如Zuul)就可以通過(guò) Eureka Server 來(lái)發(fā)現(xiàn)系統(tǒng)中的其他微服務(wù),并執(zhí)行相關(guān)的邏輯。
Eureka由兩個(gè)組件組成:Eureka服務(wù)器和Eureka客戶端。Eureka服務(wù)器用作服務(wù)注冊(cè)服務(wù)器。Eureka客戶端是一個(gè)java客戶端,用來(lái)簡(jiǎn)化與服務(wù)器的交互、作為輪詢負(fù)載均衡器,并提供服務(wù)的故障切換支持。Netflix在其生產(chǎn)環(huán)境中使用的是另外的客戶端,它提供基于流量、資源利用率以及出錯(cuò)狀態(tài)的加權(quán)負(fù)載均衡。

上圖簡(jiǎn)要描述了Eureka的基本架構(gòu),由3個(gè)角色組成:
1、Eureka Server
- Eureka Server 作為一個(gè)獨(dú)立的部署單元,以 REST API 的形式為服務(wù)實(shí)例提供了注冊(cè)、管理和查詢等操作。同時(shí),Eureka Server 也為我們提供了可視化的監(jiān)控頁(yè)面,可以直觀地看到各個(gè) Eureka Server 當(dāng)前的運(yùn)行狀態(tài)和所有已注冊(cè)服務(wù)的情況。
2、Service Provider
- 服務(wù)提供方
- 將自身服務(wù)注冊(cè)到Eureka,從而使服務(wù)消費(fèi)方能夠找到
3、Service Consumer
- 服務(wù)消費(fèi)方
- 從Eureka獲取注冊(cè)服務(wù)列表,從而能夠消費(fèi)服務(wù)
上手-Eureka Server
1.創(chuàng)建一個(gè)基礎(chǔ)的Spring Boot工程,pom中添加依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.啟動(dòng)代碼中添加@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApplication.class, args);
}
}
3.默認(rèn)設(shè)置下,該服務(wù)注冊(cè)中心也會(huì)將自己作為客戶端來(lái)嘗試注冊(cè)它自己,所以我們需要禁用它的客戶端注冊(cè)行為,在application.properties添加以下配置:
spring.application.name=Eureka Server
server.port=7001
eureka.client.register-with-eureka=false #表示是否將自己注冊(cè)到Eureka Server,默認(rèn)為true
eureka.client.fetch-registry=false #表示是否從Eureka Server獲取注冊(cè)信息,默認(rèn)為true
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/ #設(shè)置與Eureka Server交互的地址,查詢服務(wù)和注冊(cè)服務(wù)都需要依賴這個(gè)地址。默認(rèn)是http://localhost:8761/eureka ;多個(gè)地址可使用 , 分隔
application.yml形式(下面不再給出)
eureka:
client:
fetch-registry:
register-with-eureka: false
serviceUrl:
defaultZone: http://localhost:${server.port}/eureka/
server:
port: 7001
spring:
application:
name: Eureka Server
啟動(dòng)工程后,訪問(wèn):http://localhost:7001/,可以看到?jīng)]有任何服務(wù)。
上手-Eureka Client
創(chuàng)建提供服務(wù)的客戶端,并向服務(wù)注冊(cè)中心注冊(cè)自己。實(shí)現(xiàn)一個(gè)RESTful API,通過(guò)傳入兩個(gè)參數(shù)a和b,最后返回a + b的結(jié)果
1.創(chuàng)建一個(gè)基礎(chǔ)的Spring Boot工程,pom中添加依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.實(shí)現(xiàn)/add請(qǐng)求處理接口,通過(guò)DiscoveryClient對(duì)象,在日志中打印出服務(wù)實(shí)例的相關(guān)內(nèi)容
@RestController
public class ComputeController {
private final Logger logger = Logger.getLogger(getClass());
@Autowired
private DiscoveryClient client;
@RequestMapping(value = "/add" ,method = RequestMethod.GET)
public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
ServiceInstance instance = client.getLocalServiceInstance();
Integer r = a + b;
logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
return r;
}
}
3.啟動(dòng)代碼中添加@EnableDiscoveryClient注解,該注解能激活Eureka中的DiscoveryClient實(shí)現(xiàn),才能實(shí)現(xiàn)Controller中對(duì)服務(wù)信息的輸出。
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApplication.class, args);
}
}
4.在application.properties添加以下配置:
spring.application.name=Eureka Client #可以指定微服務(wù)的名稱后續(xù)在調(diào)用的時(shí)候只需要使用該名稱就可以進(jìn)行服務(wù)的訪問(wèn)。
server.port=8001 #端口
eureka.client.serviceUrl.defaultZone=http://localhost:7001/eureka/ #屬性對(duì)應(yīng)服務(wù)注冊(cè)中心的配置內(nèi)容,指定服務(wù)注冊(cè)中心的位置
啟動(dòng)工程后,再次訪問(wèn):http://localhost:7001/,可以看到定義的服務(wù)被注冊(cè)了。
停止服務(wù)
-
直接停掉服務(wù)。
默認(rèn)情況下,如果Eureka Server在90秒沒(méi)有收到Eureka客戶的續(xù)約,它會(huì)將實(shí)例從其注冊(cè)表中刪除。但這種做法的不好之處在于, 客戶端已經(jīng)停止了運(yùn)行,但仍然在注冊(cè)中心的列表中。 雖然通過(guò)一定的負(fù)載均衡策略或使用熔斷器可以讓服務(wù)正常進(jìn)行,但有沒(méi)有方法讓注冊(cè)中心馬上知道服務(wù)已經(jīng)下線呢?
2.為了讓注冊(cè)中心馬上知道服務(wù)要下線, 可以向eureka 注冊(cè)中心發(fā)送delete請(qǐng)求
格式為 /eureka/apps/{application.name}(application的name)/劃紅線的地址
劃紅線的地址 eureka.client.instance.instance-id
下面是下線一個(gè)hello-service的例子。
下圖是用postman 發(fā)送delete請(qǐng)求
值得注意的是,Eureka客戶端每隔一段時(shí)間(默認(rèn)30秒)會(huì)發(fā)送一次心跳到注冊(cè)中心續(xù)約。如果通過(guò)這種方式下線了一個(gè)服務(wù),而沒(méi)有及時(shí)停掉的話,該服務(wù)很快又會(huì)回到服務(wù)列表中。
所以,可以先停掉服務(wù),再發(fā)送請(qǐng)求將其從列表中移除。
http://127.0.0.1:7001/eureka/apps/config-server/WINDOWS-61L7RBP:config-server:8769
-
客戶端主動(dòng)通知注冊(cè)中心下線
如果你的eureka客戶端是是一個(gè)spring boot應(yīng)用,可以通過(guò)調(diào)用以下代碼通知注冊(cè)中心下線。
DiscoveryManager.getInstance().shutdownComponent();
例子如下,在eureka client 中
@RestController
public class HelloController {
@Autowired
private DiscoveryClient client;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String index() {
java.util.List<ServiceInstance> instances = client.getInstances("hello-service");
return "Hello World";
}
@RequestMapping(value = "/offline", method = RequestMethod.GET)
public void offLine(){
DiscoveryManager.getInstance().shutdownComponent();
}
}
GET 請(qǐng)求 127.0.0.1:6020/offline