SpringCloud Eureka-服務註冊與發現02 3.搭建EurekaServer集群-實現負載均衡&故障容錯 3.1為什麼需要集群EurekaServer? 微服務RPC遠程服務調用最核心的是高可用 如果註冊中心只有1個,如果出現故障,會導致整個服務環境不可用 解決辦法就是搭建Eureka ...
SpringCloud Eureka-服務註冊與發現02
3.搭建EurekaServer集群-實現負載均衡&故障容錯
3.1為什麼需要集群EurekaServer?
- 微服務RPC遠程服務調用最核心的是高可用
- 如果註冊中心只有1個,如果出現故障,會導致整個服務環境不可用
- 解決辦法就是搭建Eureka註冊中心集群,實現負載均衡和故障容錯(構成集群的幾個主機之間的提供的服務是相同的)
3.2搭建EurekaServer集群
3.2.1搭建第二個註冊中心
搭建 e-commerce-eureka-server-9002 微服務模塊,作為第二個 EurekaServer -註冊中心。
搭建的具體步驟和 e-commerce-eureka-server-9001 一樣,見上篇2.2
(1)創建Module,在pom.xml加入相關依賴(略)
(2)創建配置文件application.yml
server:
port: 9002
#配置Eureka-server
eureka:
instance:
hostname: eureka9002.com #服務實例名
client: #如果Eureka是一個集群,那麼相互兩個EurekaServer之間也可以當做對方為客戶端
#配置是否向註冊中心註冊自己
register-with-eureka: false
#表示自己就是註冊中心,作用是維護註冊的服務實例,不需要去檢索服務
fetch-registry: false
service-url:
#當前的註冊中心 需要註冊到 Eureka9001 註冊中心
defaultZone: http://eureka9001.com:9001/eureka/
(3)創建主啟動類
package com.li.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author 李
* @version 1.0
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication9002 {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication9002.class,args);
}
}
3.2.2修改第一個註冊中心
(1)修改 e-commerce-eureka-server-9001 的 application.yml 文件
server:
port: 9001
#配置Eureka-server
eureka:
instance:
hostname: eureka9001.com #服務實例名
client: #如果Eureka是一個集群,那麼相互兩個EurekaServer之間也可以當做對方為客戶端
#配置是否向註冊中心註冊自己
register-with-eureka: false
#表示自己就是註冊中心,作用是維護註冊的服務實例,不需要去檢索服務
fetch-registry: false
service-url: #設置於 Eureka server 的交互模塊,查詢服務和註冊服務都需要依賴這個地址
#EurekaServer之間相互註冊
defaultZone: http://eureka9002.com:9002/eureka/
(2)將e-commerce-eureka-server-9001的主啟動類的名稱修改為 EurekaApplication9001
3.2.3修改host文件
因為是在一臺電腦上模擬的集群,為了瀏覽器輸入類似eureka9002.com:9002/eureka/
的地址,可以直接訪問到,這裡修改host文件,對上述指定功能變數名稱進行本機的ip映射。
文件位置:C:\Windows\System32\drivers\etc\hosts
3.2.4完成測試
分別啟動兩個註冊中心,在瀏覽器中訪問上圖配置的地址:
3.3.5將其他微服務註冊到EurekaServer集群
(1)將member-service-provider-10000註冊到 EurekaServer 集群
部分配置:
eureka:
service-url:
#將本微服務註冊到多個EurekaServer,使用逗號間隔
defaultZone: http://eureka9001.com:9001/eureka,http://eureka9002.com:9002/eureka
(2)將member-service-consumer-80註冊到 EurekaServer 集群:同上,修改位置相同(略)。
(3)啟動這些微服務,可以看到在所有EurekaServer的監控頁面中都註冊了上述微服務:
3.3搭建會員中心服務提供方集群
同樣的,為了高可用性,我們不僅在EurekaServer中要使用集群,在服務提供方也要使用集群(構成集群的幾個主機之間的提供的服務是相同的)。
3.3.1搭建第二個服務提供方
所以參考 member-service-provider-10000 的代碼來創建 member-service-provider-10002 ,以下簡稱為10000 和 10002
(1)創建Module-member-service-provider-10002
(2)可以將磁碟下10000子模塊的main目錄複製替換10002的main目錄
(3)然後在10002的pom.xml中導入和10000的pom.xml相同的依賴
(4)最後修改10002的埠和當前應用的名稱,並修改10002的主程式名稱。
(5)測試
3.3.2註意事項和細節
因為member-service-provider-10000和member-service-provider-10002是作為一個集群對外提供服務的,因為我們需要將兩個微服務的spring.application.name進行統一,這樣消費方可以通過統一的別名進行負載均衡調用。
spring:
application:
name: member-service-provider #同一將服務提供方的應用名設置為member-service-provider
設置後,重新啟動服務啟動方,在EurekaServer中可以看到註冊列表中只有一個服務提供名,但是它包含了兩個遠程調用的介面:
3.4配置服務消費端使用會員中心服務集群
配置服務消費端 member-service-consumer-80,讓它可以使用會員中心服務集群。
(1)修改MemberConsumerController.java
package com.li.springcloud.controller;
import ...
/**
* @author 李
* @version 1.0
*/
@RestController
@Slf4j
public class MemberConsumerController {
@Resource
private RestTemplate restTemplate;
/**
* 1.MEMBER-SERVICE-PROVIDER 是服務提供方[集群]註冊到EurekaServer的別名
* 2.也是服務提供方[集群]對方暴露的名稱
* 3.這裡MEMBER-SERVICE-PROVIDER 目前有兩個可以獲取的區域:
* member-service-provider-10000、member-service-provider-10002
*/
public static final String MEMBER_SERVICE_PROVIDER_URL =
"http://MEMBER-SERVICE-PROVIDER";//改為提供服務模塊的別名
//添加對象到資料庫表中
@PostMapping("/member/consumer/save")
public Result<Member> save(Member member) {
return restTemplate.postForObject
(MEMBER_SERVICE_PROVIDER_URL + "/member/save",
member,
Result.class);
}
//根據id調用服務介面,返回member對象信息
@GetMapping("/member/consumer/get/{id}")
public Result<Member> getMemberById(@PathVariable("id") Integer id) {
return restTemplate.getForObject
(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id,
Result.class);
}
}
(2)修改 CustomInitBean.java
需要增加註解 @LoadBalanced,賦予 RestTemplate負載均衡能力,即選擇 MEMBER-SERVICE-PROVIDER 某一個服務訪問,預設是輪詢演算法
package com.li.springcloud.config;
import ...
/**
* @author 李
* @version 1.0
* 註入RestTemplate Bean
*/
@Configuration
public class CustomInitBean {
@Bean
@LoadBalanced //賦予RestTemplate負載均衡的能力,預設是使用輪詢演算法來訪問遠程調用介面
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
(3)依次啟動EurekaServer集群、服務提供方集群、服務消費方
為了區分,可以在服務提供方的Controller中列印當前的服務提供方的名稱
-
先用瀏覽器直接訪問服務提供方集群的介面,目的是測試服務提供方是否正常工作:
註意這裡訪問的分別是不同的服務提供方的介面
-
在用瀏覽器訪問服務消費方的介面,測試服務消費方是否正常工作:
可以看到瀏覽器訪問同一個地址(即只有一個服務消費方模塊),但是底層調用的服務提供方是不一樣的(輪詢訪問)
第一次訪問:
第二次訪問:
交替訪問member服務說明:
- 註解 @LoadBalanced底層是Ribbon支持演算法
- Ribbon和Eureka整合後,服務消費方可以直接調用服務,而不用再關心服務提供方的地址和埠號
- 該服務還有負載功能
3.5通過DiscoveryClient獲取EurekaServer服務註冊信息
無論是服務消費方還是服務提供方,它們都是EurekaClient。如果希望獲取到EurekaServer的服務註冊信息,可以使用DiscoveryClient。
這裡以服務消費方為例,獲取EurekaServer的服務註冊信息:
(1)修改 MemberConsumerController.java
package com.li.springcloud.controller;
import ...
/**
* @author 李
* @version 1.0
*/
@RestController
@Slf4j
public class MemberConsumerController {
@Resource
private RestTemplate restTemplate;
//裝配一個DiscoveryClient,
//註意用的包是 import org.springframework.cloud.client.discovery.DiscoveryClient;
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/member/consumer/discovery")
public Object discovery() {
List<String> services = discoveryClient.getServices();
for (String service : services) {
log.info("服務名={}", service);
//通過服務名來獲取服務名對應的實例
List<ServiceInstance> instances = discoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
log.info("id={},host={},port={},uri={}",
instance.getServiceId(), instance.getHost(),
instance.getPort(), instance.getUri());
}
}
return discoveryClient;
}
//其他方法略..
}
(2)修改啟動類,添加註解啟用服務發現
(3)重啟服務消費模塊,瀏覽器訪問 http://localhost/member/consumer/discovery
,後臺輸出如下: