Eureka分爲兩部分
-
註冊中心:用於維護客戶端註冊表。
-
客戶端:通過註冊中心獲取其他客戶端的註冊信息表,可通過客戶端負載均衡的方式訪問服務實例。每個客戶端即可是服務提供者,也可使服務消費者。
服務註冊
客戶端服務實例啓動成功後,會發送一個http請求提供本身的一些信息註冊中心中心,這些信息包括服務名稱、ip地址、端口號、版本信息和通信協議,註冊中心會將這些信息寫入自己的註冊表中。除此之外,註冊中心還會以心跳監測的方式檢查註冊列表中的服務實例是否可用,需要把不可用的實例從註冊表中剔除。
服務發現
在Eureka框架下,服務之間的調用不再通過指定具體的服務地址調用,而是通過服務名稱來進行調用,這得益於註冊表的存在。進行服務調用時,客戶端會向註冊中心獲取註冊表,實際上不會每次都會去註冊中心獲取,客戶端本地會緩存一份,在真正進行http調用時,會通過服務名從註冊表的信息中組裝真正的地址,如果一個服務存在多個實例,將通過負載均衡策略訪問其中的某個實例。
下面使用eureka來實現服務之間的調用,服務之間的關係如下所示:
搭建服務註冊中心
新建一個spring boot項目,將它命名爲eureka-server-demo。
修改pom.xml文件,引入Eureka server,如下所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在@SpringBootApplication類中加入@EnableEurekaServer註釋開啓Eureka server。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerDemoApplication.class, args);
}
}
在application.properties文件中加入Eureka server的配置
server.port=9091
eureka.instance.hostname=localhost
#由於該服務是註冊中心,所以設置不註冊自己
eureka.client.register-with-eureka=false
#由於該服務是註冊中心,所以設置不需要檢索服務
eureka.client.fetch-registry=false
#設置註冊中心的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
經過這3個步驟就可簡單的配置一個單機版的Eureka註冊中心了。
在瀏覽器中輸入http://localhost:9091/ 就可以看到Eureka的註冊詳情。
搭建Eureka客戶端(服務提供者)
新建一個spring boot項目,將它命名爲eureka-service-demo,該服務扮演一個服務提供者。
修改pom.xml,如下所示:
<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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
修改主類,加入@EnableDiscoveryClient註解。
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaServiceDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceDemoApplication.class, args);
}
}
在application.properties文件中加入Eureka client的配置
server.port=9092
#服務名稱,需要它來訪問該服務
spring.application.name=service-demo
#服務註冊中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:9091/eureka/
創建controller,如下所示:
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("hello")
public String hello(){
return "hello";
}
}
搭建Eureka客戶端(服務消費者)
新建一個spring boot項目,將它命名爲eureka-consumer-demo,該服務扮演一個服務提供者。由於要使用ribbton來進行客戶端負載均衡調用服務提供者提供的服務,所以除了要引入eureka-client外,還要引入ribbton。修改pom.xml,如下所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在主類加入@EnableDiscoveryClient註解,聲明一個RestTemplate用於使用負載均衡。如下所示:
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaConsumerDemoApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerDemoApplication.class, args);
}
}
在application.properties文件中加入Eureka client的配置
server.port=9093
#服務名稱,需要它來訪問該服務
spring.application.name=consumer-demo
#服務註冊中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:9091/eureka/
增加一個controller,如下所示:
@Controller
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@ResponseBody
@RequestMapping("hello")
public String hello(){
return restTemplate.getForObject("http://SERVICE-DEMO/hello/",String.class);
}
}
測試調用
分別運行上面3個spring boot項目,在瀏覽器上輸入http://localhost:9091/,可用看到eureka服務註冊詳情界面,如下所示:
可用看到已經註冊了兩個服務,每個服務註冊了一個實例。eureka使用服務名+端口號來區分服務實例。現在在服務器上輸入http://localhost:9093/hello可以看到瀏覽器輸入hello,comsumer服務成功調用了service服務提供的服務。
高可用的Eureka
Eureka是高可用的,允許對服務註冊中心集羣,實現方式是通過註冊中心將自己作爲服務註冊到其他的註冊中心。這樣就可以實現一組互相註冊的服務註冊中心,以實現服務清單的互相同步,達到高可用的集羣效果。
搭建服務註冊中心集羣
Eureka的服務端是可以進行集羣的,保證高可用性。下面將搭建一個Eureka的服務端集羣示例,將包含3個Eureka服務端實例。修改之前的eureka-server-demo項目。
在resurces目錄下新建application-server1.properties,加入如下內容
server.port=9081
spring.application.name=eureka-server
eureka.instance.hostname=server1
#設置其他註冊中心實例地址
eureka.client.serviceUrl.defaultZone=http://server2:9082/eureka/,http://server3:9083/eureka/
在resurces目錄下新建application-server2.properties,加入如下內容
server.port=9082 spring.application.name=eureka-server eureka.instance.hostname=server2 #設置其他註冊中心實例地址 eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server3:9083/eureka/
在resurces目錄下新建application-server3.properties,加入如下內容
server.port=9083
spring.application.name=eureka-server
eureka.instance.hostname=server3
#設置其他註冊中心實例地址
eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server2:9082/eureka/
修改本地的host文件,加入如下內容,如下所示
127.0.0.1 server1
127.0.0.1 server2
127.0.0.1 server3
將eureka-server-demo打包成jar包,分別允許
java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server1
java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server2
java -jar eureka-server-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=server3
就啓動了3個實例的註冊中心集羣,在瀏覽器中輸入http://server1:9081/,可以看到詳情界面,如下所示:
可以看到服務註冊中心EUREKA-SERVER包含了3個實例。
之前的示例服務service-demo和cousumer-demo要註冊到集羣,需要修改application.properties文件,如下所示
#修改該屬性
eureka.client.serviceUrl.defaultZone=http://server1:9081/eureka/,http://server2:9082/eureka/,http://server3:9083/eureka/
斷開server2實例,可以看到
server2被標記爲不可用,但集羣仍可正常允許。只需要重啓server2,server2就可以變爲可用狀態。
eureka 自我保護
當訪問eureka管理界面出現如下提示,就代表eureka進入了自我保護狀態。
服務註冊到服務註冊中心後,會和服務註冊中心維持一個心跳連接來告訴服務註冊中自己還活着。服務註冊中心在運行期間會統計心跳失敗比例是否在15分鐘內是否低於85%,如果低於,會將該服務實例的信息保護起來,保證它不會過期。這種自我保護機制是有意義的,因爲可能存在這種情況,服務本身沒有問題,但是和服務註冊中心之間的網絡連接不通,這樣會導致服務註冊中心收不到心跳反應。然而也存在這樣的情況,服務確實掛了,但服務註冊中心開啓了自我保護,調用該服務的服務就會獲取到包含失效服務的服務清單,所有調用服務必須要有容錯機制,如斷路器、重試機制等。
可以通過設置eureka.server.enable-self-preservation=false來禁止該機制。