Eureka是一種基於rest提供服務註冊和發現的產品:java
- Eureka-Server: 用於定位服務,以實現中間層服務器的負載平衡和故障轉移。
- Eureka-client:用於服務間的交互,內置負載均衡器,能夠進行基本的循環負載均衡
Eureka 是一種客戶端服務發現模式,提供Server和Client兩個組件。Eureka Server做爲服務註冊表的角色,提供REST API管理服務實例的註冊和查詢。POST請求用於服務註冊,PUT請求用於實現心跳機制,DELETE請求服務註冊表移除實例信息,GET請求查詢服務註冊表來獲取全部的可用實例。Eureka Client是Java實現的Eureka客戶端,除了方便集成外,還提供了比較簡單的Round-Robin Balance。配合使用Netflix Ribbon ,能夠實現更復雜的基於流量、資源佔用狀況、請求失敗等因素的Banlance策略,爲系統提供更爲可靠的彈性保證。git
eureka的server,client是相對於註冊發現服務的,並非常見RPC請求的client,server,服務註冊在Eureka Server上,每30秒發送心跳來維持註冊狀態。客戶端90s內都沒有發心跳,Eureka Server就會認爲服務不可用並將其從服務註冊表移除。服務的註冊和更新信息會同步到Eureka集羣的其餘節點。全部zone的Eureka Client每30秒查詢一次當前zone的服務註冊表獲取全部可用服務,而後採用合適的Balance策略向某一個服務實例發起請求。github
Eureka是一個AP的系統,具有高可用性和分區容錯性。每一個Eureka Client本地都有一份它最新獲取到的服務註冊表的緩存信息,即便全部的Eureka Server都掛掉了,依然能夠根據本地緩存的服務信息正常工做。Eureka Server沒有基於quorum 機制實現,而是採用P2P的去中心化結構,這樣相比於zookeeper,集羣不須要保證至少幾臺Server存活才能正常工做,加強了可用性。可是這種結構註定了Eureka不可能有zookeeper那樣的一致性保證,同時由於Client緩存更新不及時、Server間同步失敗等緣由,都會致使Client訪問不到新註冊的服務或者訪問到過時的服務。web
當Eureka Server節點間某次信息同步失敗時,同步失敗的操做會在客戶端下次心跳發起時再次同步;若是Eureka Server和Eureka Client間有網絡分區存在(默認的檢測機制是15分鐘內低於85%的心跳彙報),Eureka Server會進入自我保護模式,再也不把過時服務從服務註冊表移除(這種狀況下客戶端有可能獲取已經中止的服務,配合使用Hystrix經過熔斷機制來容錯和降級,彌補基於客戶端服務發現的時效性的缺點)。更復雜的狀況見在Eureka官網文檔上有詳細說明:Understanding Eureka Peer to Peer Communicationspring
dubbo,Nacos;Consul緩存
如今搭建eureka實在是方便,我這邊使用的是IDEA新建的;服務器
選擇Eureka Server網絡
POM文件:app
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.M1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies> <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>
application配置以下負載均衡
server.port=8081 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
默認該服務註冊中心也會將本身做爲客戶端來嘗試註冊它本身,因此咱們須要禁用它的客戶端註冊行爲,只須要在application.properties配置文件中增長以上信息便可;
進入管理頁面
此時尚未啓動provide,因此目前提供方是空的;
新建的流程與eureka server一致,只是選擇組件的時候選擇eureka Discovery
POM文件
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.M1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.16</version> <scope>provided</scope> </dependency> </dependencies> <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>
server: port: 8080 # 服務端口 eureka: client: service-url: defaultZone: http://localhost:8081/eureka/ # 服務註冊中心地址 spring: application: name: eureka-provider # 服務名稱
@RestController @Slf4j public class ComputeController { @Autowired private DiscoveryClient discoveryClient; @Autowired private Registration registration; @RequestMapping(value = "/add" ,method = RequestMethod.GET) public Integer add(@RequestParam Integer a, @RequestParam Integer b) { ServiceInstance serviceInstance = this.serviceInstance(); Integer r = a + b; log.info("/add, host:" + serviceInstance.getHost() + ", service_id:" + serviceInstance.getServiceId() + ", result:" + r); return r; } /** * 獲取當前服務的服務實例 * * @return ServiceInstance */ public ServiceInstance serviceInstance() { List<ServiceInstance> list = discoveryClient.getInstances(registration.getServiceId()); if (list != null && list.size() > 0) { return list.get(0); } return null; } }
註冊中心監控
此時能夠看到服務提供者註冊成功了
server: port: 8082 # 服務端口 eureka: client: register-with-eureka: false #所以處只是消費,不提供服務,因此不須要向eureka server註冊 service-url: defaultZone: http://localhost:8081/eureka/ # 服務註冊中心地址 spring: application: name: eureka-consumer # 服務名稱# 服務名稱
package com.lc.springcloud.eureka.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; /** * Eureka客戶端Controller * @author LC * @date 2018/11/9 */ @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/add", method = RequestMethod.GET) public String add() { System.out.println(restTemplate.getForEntity("http://EUREKA-PROVIDER/add?a=10&b=20", String.class).getBody()); return restTemplate.getForEntity("http://EUREKA-PROVIDER/add?a=10&b=20", String.class).getBody(); } }
至此,spring cloud之eureka搭建完畢
文中示例代碼:eureka 示例