Eureka是spring cloud中的一個負責服務注冊與發現的組件。遵循着CAP理論中的A(可用性)P(分區容錯性)。
一個Eureka中分為eureka server和eureka client。其中eureka server是作為服務的注冊與發現中心。eureka client既可以作為服務的生產者,又可以作為服務的消費者。具體結構如下圖:
上圖中我們首先會啟動一個或多個Eureka server,這些eureka server同步保留着所有的服務信息。然后我們啟動不同的eureka client,向服務端發起服務注冊和服務查詢。不論我們是向那個eureka server進行的注冊,最終都會同步給所有配置好的eureka server。我們獲取的服務信息,也同樣都是一致的。
eureka server實現
spring cloud是基於spring boot進行的開發,因此我們需要創建一個spring boot項目,同時在里面添加eureka server包。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <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>
添加完成后,在我們的啟動類中添加注解@EnableEurekaServer
@SpringBootApplication @EnableEurekaServer public class ServiceRegistryApplication { public static void main(String[] args) { SpringApplication.run(ServiceRegistryApplication.class, args); } }
然后是一些配置信息在配置文件中配置:
#服務端口 server.port=8077 #服務名稱 spring.application.name=eureka-server #服務地址 eureka.instance.hostname=localhost #不向注冊中心注冊自己 eureka.client.register-with-eureka=false #取消檢索服務 eureka.client.fetch-registry=false #開啟注冊中心的保護機制,默認是開啟 eureka.server.enable-self-preservation=true #設置保護機制的閾值,默認是0.85。 eureka.server.renewal-percent-threshold=0.5 #注冊中心路徑,如果有多個eureka server,在這里需要配置其他eureka server的地址,用","進行區分,如"http://address:8888/eureka,http://address:8887/eureka" eureka.client.service-url.default-zone=http://${eureka.instance.hostname}:${server.port}/eureka
配置完成后,我們運行啟動類,可以看到打印出來的信息里面,eureka server已經啟動。
這個時候可以進入地址http://localhost:8077,查看注冊中心:
eureka client服務注冊
同樣的先添加eureka client的包
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <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>
然后在啟動類中添加注解@EnableEurekaClient。
@SpringBootApplication // 注意:服務端配置的是EnableEurekaServer,客戶端配置的是EnableEurekaClient @EnableEurekaClient public class UserServerApplication { public static void main(String[] args) { SpringApplication.run(UserServerApplication.class, args); } }
在這里我們可以創建一個controller,用來提供一個服務,並填寫返回值。
@RestController public class UserController { @GetMapping("users/{id}") public String getUser(@PathVariable("id") String id) { System.out.println("接收到請求[/users/" + id + "]"); return "testUser"; } }
在配置文件中添加配置信息:
#服務端口 server.port=7001 #服務名稱 spring.application.name=user #服務地址 eureka.instance.hostname=localhost #注冊中心路徑,表示我們向這個注冊中心注冊服務,如果向多個注冊中心注冊,用“,”進行分隔 eureka.client.serviceUrl.defaultZone=http://localhost:8077/eureka #心跳間隔5s,默認30s。每一個服務配置后,心跳間隔和心跳超時時間會被保存在server端,不同服務的心跳頻率可能不同,server端會根據保存的配置來分別探活 eureka.instance.lease-renewal-interval-in-seconds=5 #心跳超時時間10s,默認90s。從client端最后一次發出心跳后,達到這個時間沒有再次發出心跳,表示服務不可用,將它的實例從注冊中心移除 eureka.instance.lease-expiration-duration-in-seconds=10
然后我們運行啟動類,查看打印出來的日志信息,紅框內容表示用eureka注冊服務user,狀態為up。
這時我們再訪問我們的注冊中心地址:http://localhost:8077,里面已經有了一個服務實例USER了。
如果這個時候我們再把服務關掉,查看eureka server的控制台打印:
注意看時間,不是在我們關掉服務的時候立即檢測出來,而是差不多120秒后,先打印一個WARN,服務USER已經超出過期時間。然后打印一個INFO,將服務USER的實例從注冊中心移除。
eureka client服務消費者
上面我們創建了一個注冊中心和一個注冊的服務,下面我們再通過eureka client來調用所注冊的服務。
在eureka中,實際上是不區分服務的消費者和服務生產者的,一個服務的消費者,同樣也可以是一個服務的生產者。因此我們首先要做的就是再創建一個eureka client。這個enreka client命名為roleServer
創建好eureka client后,我們創建一個配置類,創建RestTemplate來進行服務間的連接
@Configuration public class RestConfig { @Bean @LoadBalanced //負載均衡 public RestTemplate restTemplate() { return new RestTemplate(); } }
然后在Controller中進行服務的調用:
@RestController public class RoleController { // 這里配置的是我們要調用的服務實例名,我們要調用USER服務,因此這里的地址是USER private String rest_url_prefix = "http://user"; @Autowired private RestTemplate restTemplate; @GetMapping("roles/{id}") public String getRole(@PathVariable("id") String id) { System.out.println("接收到請求[/roles/" + id + "]"); // 調用USER服務中的/users/{id}服務 return restTemplate.getForObject(rest_url_prefix + "/users/" + id, String.class); } }
配置完成,運行啟動類,我們首先在服務注冊中心可以看到這兩個服務實例
我們訪問ROLE服務中定義的請求路徑:http://localhost:7003/roles/1,可以看到頁面返回了我們在USER服務中的定義的返回值"testUser":
由此,我們的一個euraka注冊中心、服務生產者、服務消費者均已經創建完成。