在服務呼叫關係中,會有兩個不同的角色:
服務提供者:一次業務中,被其它微服務呼叫的服務。(提供介面給其它微服務)
服務消費者:一次業務中,呼叫其它微服務的服務。(呼叫其它微服務提供的介面)
但是,服務提供者與服務消費者的角色並不是絕對的,而是相對於業務而言。
如果服務A呼叫了服務B,而服務B又呼叫了服務C,服務B是提供者還是消費者??
- 對於A呼叫B的業務而言:A是服務消費者,B是服務提供者
- 對於B呼叫C的業務而言:B是服務消費者,C是服務提供者
因此,服務B既可以是服務提供者,也可以是服務消費者。
在之前的例子中,user-service是服務提供者,order-service是服務消費者。
現在假設我們的服務提供者user-service部署了多個例項:
那麼現在就出現新的問題了:
- order-service在發起遠端呼叫的時候,該如何得知user-service例項的ip地址和埠?
- 有多個user-service例項地址,order-service呼叫時該如何選擇?
- order-service如何得知某個user-service例項是否依然健康,是不是已經當機?
透過SpringCloud的註冊中心Eureka就可以解決這些問題。
Eureka架構
在Eureka架構中,微服務角色有兩類:
EurekaServer:服務端,註冊中心
- 記錄服務資訊
- 心跳監控
EurekaClient:客戶端
- Provider:服務提供者,如例子中的 user-service
- 註冊自己的資訊到EurekaServer
- 每隔30秒向EurekaServer傳送心跳
- consumer:服務消費者,如例子中的 order-service
- 根據服務名稱從EurekaServer拉取服務列表
- 基於服務列表做負載均衡,選中一個微服務後發起遠端呼叫
這樣我就可以回答前面幾個問題了
問題1:order-service在發起遠端呼叫的時候,該如何得知user-service例項的ip地址和埠?
答:
- user-service服務例項啟動後,將自己的資訊註冊到eureka-server(EurekaServer)。
- eureka-server儲存服務名稱到服務例項地址列表的對映關係
- order-service根據服務名稱,拉取例項地址列表。這個叫服務發現或服務拉取
問題2:有多個user-service例項地址,order-service呼叫時該如何選擇?
答:
- order-service從例項列表中利用負載均衡演算法選中一個例項地址
- 向該例項地址發起遠端呼叫
問題3:order-service如何得知某個user-service例項是否依然健康,是不是已經當機?
答:
- user-service會每隔一段時間(預設30秒)向eureka-server發起請求,報告自己狀態,稱為心跳
- 當超過一定時間沒有傳送心跳時,eureka-server會認為微服務例項故障,將該例項從服務列表中剔除
- order-service拉取服務時,就能將故障例項排除了
搭建EurekaServer
一、註冊服務端
首先要註冊中心服務端:eureka-server,這必須是一個獨立的微服務。
二、引入依賴
建立好eureka-server服務後,需要引入SpringCloud為eureka提供的starter依賴:
<dependency><!-- eureka服務端-->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
三、編寫啟動類
給eureka-server服務編寫一個啟動類,一定要新增一個@EnableEurekaServer註解,開啟eureka的註冊中心功能:
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
四、編寫配置檔案
編寫一個application.yml檔案,內容如下:
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
五、測試
啟動微服務,然後在瀏覽器訪問:http://127.0.0.1:10086 ,就可以看到下面頁面:
服務註冊
接下來,將user-service註冊到eureka-server中去。
一、引入依賴
在user-service的pom檔案中,引入下面的eureka-client依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
二、修改配置檔案
在user-service中,修改application.yml檔案,新增服務名稱、eureka地址:
spring:
application:
name: userservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
三、啟動多個user-service例項
為了模擬啟動了多個user-service例項,可以新增一個SpringBoot的啟動配置,再啟動一個user-service,需要修改埠號。
在啟動兩個user-service例項後,檢視eureka-server管理頁面:
服務發現
將order-service的邏輯修改:向eureka-server拉取user-service的資訊,實現服務發現。
一、引入依賴
在order-service的pom檔案中,引入下面的eureka-client依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
二、修改配置檔案
在order-service中,修改application.yml檔案,新增服務名稱、eureka地址:
spring:
application:
name: orderservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
三、服務拉取和負載均衡
去eureka-server中拉取user-service服務的例項列表,並且實現負載均衡。
在order-service的RestTemplateConfig類中,給RestTemplate這個Bean新增一個@LoadBalanced註解:
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced //標識次方法發起的http請求會被Ribbon攔截
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
修改order-service服務中的OrderService類中的queryOrderById方法。修改訪問的url路徑,用服務名代替ip、埠:
點選檢視程式碼
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查詢訂單
Order order = orderMapper.findById(orderId);
// 2.利用RestTemplate發起http請求,查詢使用者
//url路徑
String url = "http://userserices/user/" + order.getUserId();
//傳送http請求,實現遠端呼叫
User user = restTemplate.getForObject(url, User.class); //反序列化
// 3.封裝user資訊
order.setUser(user);
// 4.返回
return order;
}
}
spring會自動幫助我們從eureka-server端,根據userservice這個服務名稱,獲取例項列表,而後完成負載均衡。
總結:
-
搭建EurekaServer
- 引入eureka-server依賴
- 新增@EnableEurekaServer註解
- 在application.yml中配置eureka地址
-
服務註冊
- 引入eureka-client依賴
- 在application.yml中配置eureka地址
-
服務發現
- 引入eureka-client依賴
- 在application.yml中配置eureka地址
- 給RestTemplate新增@LoadBalanced註解
- 用服務提供者的服務名稱遠端呼叫