【SpringCloud】Eureka的基本原理与使用
【问】如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?
order-service 如何得知 user-service实例地址?
order-service如何从多个user-service实例中选择具体的实例?
order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
(1)创建项目,引入 spring-cloud-starter-netflix-eureka-server 的依赖
(2)编写启动类,添加 @EnableEurekaServer 注解
【注】自身就是Eureka,为什么要配置自身的地址信息呢???
(1)引入 spring-cloud-starter-netflix-eureka-client 依赖
(1)修改 order-service 的代码,修改访问路径,用服务名代替IP、端口
(2)在 order-service 项目的启动类中的 RestTemplate添加负载均衡的注解
【SpringCloud】Eureka的基本原理与使用
一、Eureka-提供者与消费者
在服务调用关系中,会有两个不同的角色
- 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
- 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
【问】如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?
-
对于A调用B的业务而言:A是服务消费者,B是服务提供者
-
对于B调用C的业务而言:B是服务消费者,C是服务提供者
所以,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。服务B既可以是服务提供者,也可以是服务消费者!
二、Eureka的结构和作用
什么是Eureka?
Eureka是Spring Cloud Netflix 模块中的子模块。
Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:
- Eureka Server:Eureka 服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。
- Eureka Client:Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
Eureka的作用
Eureka 解决服务调用的问题
order-service 如何得知 user-service实例地址?
-
user-service 服务实例启动后,将自己的信息注册到 eureka-server(Eureka服务端)。这个叫服务注册
-
eureka-server 保存服务名称到服务实例地址列表的映射关系
-
order-service 根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
order-service如何从多个user-service实例中选择具体的实例?
-
order-service 从实例列表中利用负载均衡算法选中一个实例地址
-
向该实例地址发起远程调用
order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
-
user-service 会每隔一段时间(默认30秒)向 eureka-server 发起请求,报告自己状态,称为心跳
-
当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
-
order-service 拉取服务时,就能将故障实例排除了
三、Eureka 的使用
搭建步骤
- 搭建注册中心,搭建EurekaServer
- 服务注册,将user-service、order-service都注册到Eureka中
- 服务发现,在order-service中完成服务拉取,然后通过负载均衡挑选一个服务,实现远程调用!
1. 搭建注册中心EurekaServer
(1)创建项目,引入 spring-cloud-starter-netflix-eureka-server 的依赖
<dependencies>
<!-- eureka服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
(2)编写启动类,添加 @EnableEurekaServer 注解
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
(3)添加 application.yml 配置文件
server:
port: 10086 # 服务端口
spring:
application:
name: eurekaserver # eureka的服务名称
eureka:
client:
service-url: # eureka 的地址信息
defaultZone: http://127.0.0.1:10086/eureka
配置文件中配置3个信息,服务端口号、服务名称、eureka的地址信息
【注】自身就是Eureka,为什么要配置自身的地址信息呢???
是这样子的!因为Eureka自身也是一个微服务,所以,在启动的时候,会将自己也注册到eureka上!这是为了之后Eureka集群通信,假如启动了多个eureka,那么这些 Eureka之间会相互做注册,这样子它们之间就可以做数据交互了!
访问 Eureka服务
地址:http://127.0.0.1:10086/eureka (我们刚刚在application.yml配置的)
服务每部署一份就是一个实例!
2. 服务注册
我们这里是要将 user-service 注册到 eureka-server 中去
(1)引入 spring-cloud-starter-netflix-eureka-client 依赖
在 user-service模块 的 pom.xml 文件中,引入下面的 spring-cloud-starter-netflix-eureka-client 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)applicaiton.yml 配置文件
server:
port: 8081
spring:
application:
name: userservice # eureka的服务名称
...
eureka:
client:
service-url: # eureka 的地址信息
defaultZone: http://127.0.0.1:10086/eureka
所以,我们可以总结一下,注册一个服务大致有如下2个步骤!
(1)导入 eureka-client 依赖
(2)在applicaiton.yml 中配置 Erueka地址
3. 服务发现
我们将 order-service 的逻辑修改:向 eureka-server 拉取 user-service 的信息,实现服务发现。
(1)修改 order-service 的代码,修改访问路径,用服务名代替IP、端口
@Service
public class OrderService {
@Resource
private OrderMapper orderMapper;
@Resource
private RestTemplate restTemplate;
/**
* 使用restTemplate 方式进行远程调用
* @param orderId
* @return
*/
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.利用restTemplate发起http请求
// 为了负载均衡使用服务名称
String url = "http://userservice/user/" + order.getUserId();
// 得到的结果是json风格,getForObject()可以将json反序列化!
User user = restTemplate.getForObject(url, User.class);
// 3.封装user到Order
order.setUser(user);
// 4.返回
return order;
}
}
(2)在 order-service 项目的启动类中的 RestTemplate添加负载均衡的注解
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* @LoadBalanced: 表示restTemplate发起的请求要被 Ribbon处理
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
运行结果
IDEA运行情况
通过 OrderService 模块去调用 UserService 模块,获取 User信息