?? 簡介:java系列技術(shù)分享(??持續(xù)更新中…??)
?? 初衷:一起學(xué)習(xí)、一起進步、堅持不懈
?? 如果文章內(nèi)容有誤與您的想法不一致,歡迎大家在評論區(qū)指正??
?? 希望這篇文章對你有所幫助,歡迎點贊 ?? 收藏 ?留言 ???? 更多文章請點擊

一、Eureka簡介
Spring Cloud
官網(wǎng):https://spring.io/projects/spring-cloudEureka
官網(wǎng):https://github.com/Netflix/eureka
Spring Cloud
是目前用于開發(fā)微服務(wù)的主流框架之一,我們都知道在微服務(wù)架構(gòu)中最為基礎(chǔ)、核心的模塊,就是服務(wù)注冊與發(fā)現(xiàn)。
Spring Cloud
封裝了 Netflix
公司開發(fā)的 Eureka
模塊來實現(xiàn) 服務(wù)注冊和發(fā)現(xiàn)。Eureka Server
作為 服務(wù)注冊中心,系統(tǒng)中的 其他微服務(wù),使用 Eureka
的 客戶端 連接到 Eureka Server
,并通過 心跳連接 檢測服務(wù)的 存活狀態(tài)。
Eureka 包含兩個組件:Eureka Server
和 Eureka Client
-
Eureka Server
: 作為 服務(wù)注冊中心,提供 服務(wù)注冊和發(fā)現(xiàn),提供服務(wù)注冊服務(wù),各個節(jié)點啟動后,會在 EurekaServer 中進行注冊,這樣 EurekaServer 中的服務(wù)注冊表中將會存儲所有可用服務(wù)節(jié)點的信息。 -
Eureka Client
: 所有注冊到 服務(wù)中心 的服務(wù)。是一個 Java 客戶端,用于簡化 Eureka Server 的交互,客戶端同時也具備一個內(nèi)置的、使用輪詢(round-robin) 負(fù)載算法的負(fù)載均衡器
。在應(yīng)用啟動后,將會向 Eureka Server 發(fā)送心跳 (默認(rèn)周期為 30 秒)。-
Service Provider
: 把 自身的服務(wù) 注冊到 Eureka Server,從而使 服務(wù)消費方 能夠找到。 -
Service Consumer
: 從Eureka Server
獲取 服務(wù)注冊列表,從而能夠 消費服務(wù)。
-
二、 Eureka 注冊中心
在微服務(wù)架構(gòu)中往往會有一個注冊中心,每個微服務(wù)都會向注冊中心去注冊自己的地址及端口信息
,注冊中心維護著服務(wù)名稱與服務(wù)實例的對應(yīng)關(guān)系。首先我們注冊中心服務(wù)端:eureka-server,這必須是一個獨立的微服務(wù)
。下面我們來搭建搭建 eureka-server。
原始http服務(wù)調(diào)用 -存在問題:
- 如果有多個服務(wù)提供者,消費者如何選擇?
- 消費者如何獲取服務(wù)提供者地址信息?
- 如何知曉服務(wù)提供者是否健康?
請看下圖
(純手工繪制有點瑕疵)Eureka的作用 圖解:
Eureka的作用-圖解
2.1 首先基于Spring Boot創(chuàng)建父工程
以Maven模塊化項目方式創(chuàng)建,便于各個微服務(wù)的項目管理。
2.1.1 需要注意(重要)
來自Spring Cloud官方文檔 :https://spring.io/projects/spring-cloud
概述了Spring Cloud的版本與Spring Boot的版本對應(yīng)關(guān)系,需要注意
最新更新可查看官方文檔
2.1.2 本項目引入主要配置
父項目Pom文件
可以看到下文中:Spring Boot
的版本是2.7.1
因此根據(jù)上圖Spring Cloud
的版本為:2021.0.1
第一種 (選擇一種即可,區(qū)別不大)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
<hutool.version>5.8.2</hutool.version>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- springCloud -->
<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>
第二種
不引入parent也可以這樣配置
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.7.1</spring-boot.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
<hutool.version>5.8.2</hutool.version>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
兩種都可以
2.2 搭建Eureka-Server
- 在父工程基礎(chǔ)上 創(chuàng)建eureka-server模塊`
- 引入
spring-cloud-starter-netflix-eureka-server
依賴
<!--eureka 服務(wù)端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 在啟動類上添加
@EnableEurekaServer
注解 - 添加配置
server:
port: 10086
spring:
application:
name: eureka-server
main:
allow-bean-definition-overriding: true
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:10086/eureka/
# register-with-eureka: false # 不注冊自己
# fetch-registry: false #不拉取服務(wù)
- 啟動服務(wù)
然后訪問:http://localhost:10086/
看到如下頁面則成功
2.3 搭建Eureka-Client(服務(wù)注冊)
將provider-service注冊到Eureka-Server中
步驟如下:
- 在父工程基礎(chǔ)上 創(chuàng)建
provider-service模塊
(服務(wù)提供者) - 引入
spring-cloud-starter-netflix-eureka-client
依賴,注意后綴是client
<!--eureka 客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 添加配置
server:
port: 20086
spring:
application:
name: provider-service
main:
allow-bean-definition-overriding: true
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:10086/eureka/
-
同理創(chuàng)建
consumer-service模塊
(服務(wù)消費者) -
最終項目結(jié)構(gòu)如下圖所示:
我這里創(chuàng)建了個
common公共包,無要求,非必須
2.4 服務(wù)拉取準(zhǔn)備工作
2.4.1 需求
需求
:根據(jù)訂單id查詢訂單的同時查詢對應(yīng)用戶信息一起返回
消費者中提供訂單信息
提供者提供用戶信息
數(shù)據(jù)在各自對應(yīng)數(shù)據(jù)庫中
2.4.2 數(shù)據(jù)庫表數(shù)據(jù)展示
order訂單表
用戶表
2.4.3 消費者端
- controller
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
/**
* 消費者
*/
@Autowired
private ConsumerService consumerService;
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
// 根據(jù)id查詢訂單并返回
return consumerService.queryOrderById(orderId);
}
}
- service
public interface ConsumerService {
/**
* 根據(jù)id查詢訂單并返回
*/
Order queryOrderById(Long orderId);
}
- impl
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
/**
* 根據(jù)id查詢訂單并返回
*/
@Override
public Order queryOrderById(Long orderId) {
// 1.查詢訂單
Order order = orderMapper.findById(orderId);
//2遠(yuǎn)程查詢用戶信息
String url="http://localhost:20086/provider/"+order.getUserId();
//2. 發(fā)起調(diào)用
User user = restTemplate.getForObject(url, User.class);
//3. 存入order
order.setUser(user);
// 4.返回
return order;
}
}
- mapper
@Mapper
public interface OrderMapper {
@Select("select id, name, num, user_id userId, price from `order` where id = #{id}")
Order findById(Long orderId);
}
- 啟動類,并配置RestTemplate
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
/**
* 沒有實例化RestTemplate時,初始化RestTemplate
* @return
*/
@ConditionalOnMissingBean(RestTemplate.class)
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.4.4 提供者端
- controller
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private ProviderService providerService;
/**
* 根據(jù)id查詢用戶信息
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return providerService.queryById(id);
}
}
- service
public interface ProviderService {
/**
* 根據(jù)id查詢用戶信息
*/
User queryById(Long id);
}
- impl
@Service
public class ProviderServiceImpl implements ProviderService {
@Autowired
private UserInfoMapper userMapper;
/**
* 根據(jù)id查詢用戶信息
*/
@Override
public User queryById(Long id) {
return userMapper.findById(id);
}
}
- mapper
@Mapper
public interface UserInfoMapper {
@Select("select * from user where id = #{id}")
User findById(@Param("id") Long id);
}
- 啟動類
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
2.4.5 注冊成功
三、服務(wù)啟動測試
3.1 原始http全路徑調(diào)用 及 存在問題
查看上文代碼消費者端是基于全路徑http://localhost:20086/provider/1 調(diào)用
//2遠(yuǎn)程查詢用戶信息
String url="http://localhost:20086/provider/"+order.getUserId();
成功調(diào)用如下圖
存在問題:
- 如果有多個服務(wù)提供者,消費者如何選擇?
- 消費者如何獲取服務(wù)提供者地址信息?
- 如何知曉提供者是否健康 ?
可參考上文------Eureka的作用 圖解
3.2 使用Eureka注冊中心的服務(wù)名調(diào)用
這是成功注冊的服務(wù)
基于服務(wù)名稱獲取服務(wù)列表,然后對服務(wù)列表做負(fù)載均衡
-
服務(wù)名代替ip,端口
-
使用
provider-service
(自己配置的服務(wù)名)代替localhost:20086
//2遠(yuǎn)程查詢用戶信息 String url="http://provider-service/provider/"+order.getUserId();
-
在服務(wù)消費者的啟動類的
RestTemplate
添加@LoadBalanced
負(fù)載均衡注解負(fù)載均衡詳解后續(xù)文章中更新
/** * 沒有實例化RestTemplate時,初始化RestTemplate * @return */ @ConditionalOnMissingBean(RestTemplate.class) @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
測試結(jié)果成功
四、總結(jié)
4.1 Eureka的作用
-
消費者該如何獲取服務(wù)提供者具體信息?
- 服務(wù)提供者啟動時向eureka注冊自己的信息
- eureka保存這些信息
- 消費豬根據(jù)服務(wù)名稱向eureka拉取提供者信息
-
如果有多個服務(wù)提供者,消費者該如何選擇?
- 服務(wù)消費者利用負(fù)載均衡算法,從服務(wù)列表中選擇一個
-
消費者如何感知服務(wù)提供者健康狀態(tài)?
文章來源:http://www.zghlxwxcb.cn/news/detail-530340.html- 服務(wù)提供者會每隔30秒向EurekaServer發(fā)送心跳請求,報告健康狀態(tài)
- eureka會更新記錄服務(wù)列表信息,心跳不正常會被剔除
- 消費者就可以拉取到最新的信息
4.2 在Eureka架構(gòu)中,微服務(wù)角色有兩類:
-
EurekaServer: 服務(wù)端,注冊中心
- 記錄服務(wù)信息
- 心跳監(jiān)控
- Eurekaclient:客戶端
-
Provider
: 服務(wù)提供者,例如案例中的provider-service
- 注冊自己的信息到EurekaServer
- 每隔30秒向EurekaServer發(fā)送心跳
-
consumer
:服務(wù)消費者,例如案例中的consumer-service
- 根據(jù)服務(wù)名稱從EurekaServer拉取服務(wù)列表
- 基于服務(wù)列表做負(fù)載均衡,選中一個微服務(wù)后發(fā)起遠(yuǎn)程調(diào)用
-
文章來源地址http://www.zghlxwxcb.cn/news/detail-530340.html
到了這里,關(guān)于Spring Cloud 之注冊中心 Eureka 精講的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!