介紹
關於 Eureka
Eureka 是由 Netfix 開發的服務註冊發現組件,後來 spring cloud 將其集成到其子項目 spring-cloud-netfix 中。Eureka 本身是基於 REST 的服務,在集羣中主要用於服務管理。Eureka 提供了 Java 的客戶端組件,同時該客戶端組件實現了負載均衡的功能,爲業務組件的集羣部署創造了條件。我們可以很簡單的將業務組件註冊到 Eureka 中,由 Eureka 維護這些服務的列表並自動檢查組件的狀態。
Eureka 架構
常見的 Eureka 架構,由若干個(一般2~3個) Eureka 服務器、若干個 Eureka 客戶端組成,客戶端可以向服務器獲取服務並進行服務調用。
由圖可以看到服務器支持集羣部署,每個服務器作爲對方服務器的客戶端進行相互註冊與複製,客戶端也支持部署多個實例,這樣一來,保證了 Eureka 集羣的高可用性。
快速開始
構建 Eureka 服務端
在 IDEA 中通過 Spring Initializr 先創建一個名稱爲 eureka-server 的 Spring Boot 項目作爲 Eureka 服務端,在 pom.xml 引入 eureka 服務端的依賴:
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
在啓動類上加上 @EnableEurekaServer
註解:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication .class,args);
}
}
在 application.yml 配置文件中加入如下配置:
server:
port: 8761
spring:
application:
name: ek-server
eureka:
instance:
hostname: ek-server
instance-id: ${spring.application.name}:${server.port}
client:
# 是否將自己的信息註冊到 Eureka 服務器
register-with-eureka: false
# 是否到 Eureka 服務器中抓取註冊信息
fetch-registry: false
service-url:
default-zone: http://localhost:8761/eureka/
server:
# 關閉保護模式,生產模式下要開啓
enable-self-preservation: false
這裏把設置
register-with-eureka
跟fetch-registry
屬性爲 false,不然啓動服務的時候會報錯。因爲 eureka 服務端本身也可以作爲客戶端註冊到別的服務端上,組成一個服務端集羣。由於我們演示只需要一個服務端就可以,所以把這兩個屬性都設置爲 false。
這樣我們的 Eureka 服務端就寫好了,啓動項目,訪問 localhost:8761,出現如下界面證明我們的服務端已經正常啓動:
編寫服務提供者
在微服務裏面,通常習慣將一個應用稱之爲服務,所以服務提供者,是指註冊到註冊中心,並提供服務的應用。
同樣新建一個 Spring Boot 項目,名稱爲 ek-provider,先引入 Eureka 客戶端的依賴:
<!--eureka客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件中加入如下配置:
server:
port: 8081
spring:
application:
name: ek-client
eureka:
instance:
hostname: ek-client
client:
service-url:
# 服務端註冊地址
default-zone: http://localhost:8761/eureka/
default-zone 配置的是服務註冊的地址。接着在啓動類加上 Eureka 客戶端註解 @EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication .class,args);
}
}
也可以將
@EnableEurekaClient
註解換成@EnableDiscoveryClient
註解,兩者的區別是@EnableEurekaClient
註解只能在使用 Eureka 作爲註冊中心使用,而當使用別的註冊中心的時候,@EnableDiscoveryClient
註解也能用
編寫 HelloController,提供一個簡單的 rest 服務:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello world";
}
}
啓動客戶端,然後刷新 Eureka 服務端頁面( localhost:8761
),可以看到我們的客戶端已經註冊上去了:
編寫服務調用者
服務調用者同樣需要註冊到註冊中心,可以進行服務的查找與調用。新建 ek-invoker 項目,加入如下依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- ribbon負載均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
這裏我們用了 ribbon 做負載均衡,因爲服務提供者可能部署多個,而且可以動態擴容,這時候,就需要負載均衡機制來幫我們解決如何選擇調用者的問題。
application.yml 配置如下:
server:
port: 8082
spring:
application:
name: ek-invoker
eureka:
instance:
hostname: ek-invoker
client:
service-url:
# 服務端註冊地址
default-zone: http://localhost:8761/eureka/
最後編寫調用代碼,新建 InvokerController:
@RestController
@Configuration
public class InvokerController {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Autowired
public RestTemplate restTemplate;
@GetMapping("/router")
public String router(){
return restTemplate.getForObject("http://ek-client/hello", String.class);
}
}
注意 getForObject 方法的 url 參數,不是 http://localhost:8081/hello ,而是指定應用的名稱。這裏使用 Ribbon 提供的
@LoadBalanced
註解修飾 RestTemplate,這樣RestTemplate 便有了負載均衡的能力,只需要將 url 的域名換成應用的應用名,Ribbon 就會到 Eureka 服務端中查找該名稱的應用,並根據負載均衡算法,選擇合適的應用。
啓動 ek-invoker 應用,在 eureka 監控頁面可以看到我們的服務已經註冊上去了:
訪問 localhost:8082/router,可以看到瀏覽器輸出 hello world,根據輸出可知,服務調用方正確尋找到提供方,並順利調用了提供方的 /hello 接口。
公衆號
可以關注我的公衆號,不定時更新工作中的踩坑經歷,及一些工作思考