Eureka注册中心的作用

Eureka架构

远程调用的两个问题

  • 服务的ip地址和端口号写死: 生产环境中服务的地址可能会随时发生变化,如果写死每次都需要重新修改代码
  • 多实例问题: 在高并发的情况下一个服务可以有多个实例形成一个集群,此时如果采用硬编码的方式只能访问服务的一个实例地址

在Eureka架构中,微服务角色分为EurekaServer和EurekaClient两类

  • EurekaServer(服务端): 可以记录服务的注册信息(包含服务名称及其相关实例地址), 对所有的服务心跳监控
  • EurekaClient(客户端): Provider(服务提供者)和consumer(服务消费者)

服务提供者与消费者

在服务调用关系中包含服务的提供者和服务的消费者,这两种角色的定义并不是绝对的,因为在不同业务中有些服务既可以是服务提供者也可以是服务消费者

  • 服务提供者:一次业务中被其他微服务调用的服务(暴露接口给其他微服务)
  • 服务消费者:一次业务中调用其他微服务的服务(调用其他微服务提供的接口)

服务消费者在发起远程调用的时候,确定服务提供者实例的ip地址和端口号的过程,注意服务消费者也需要把自己注册到Eureka服务端后才能使用其提供的服务

  • 第一步服务注册: 服务提供者实例启动后会将自己的信息注册到eureka-server(Eureka服务端)
  • 第二步服务映射:Eureka服务端将所有服务提供的名称和其对应的服务实例地址的映射关系保存到Map集合当中
  • 第三步服务发现: 服务消费者根据服务提供者的名称从eureka中拉取对应信息,一个服务可能有多个服务提供者所以最终会得到一个服务实例地址列表
  • 第四步负载均衡: 服务消费者从实例地址列表中利用负载均衡算法选中一个实例地址并发起远程调用

服务消费者如何感知服务提供者健康状态即判断服务提供者是否宕机

  • 第一步: 服务提供者会每隔一段时间(默认30秒)向EurekaServer服务端发送心跳请求用来报告自己的健康状态
  • 第二步:eureka通过检查心跳请求更新服务提供者的列表信息, 发现心跳不正常就从服务列表中剔除, 这样服务消费者就可以拉取到服务提供者最新的信息

配置Eureka注册中心

搭建注册中心(EurekaServer)

第一步创建子模块: 在父工程cloud-demo中创建子模块eureka-server,然后引入SpringCloud为Eureka提供的starter服务端依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>

第二步编写启动类: 在eureka-server模块中编写一个启动类并添加@EnableEurekaServer注解,这样eureka-server服务就具有了作为注册的中心功能

  • 所有的微服务包括eureka-server服务自己都会去注册中心注册自己的信息(包含服务的名称及其相关实例地址)
@SpringBootApplication@EnableEurekaServerpublic class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class);}}

第三步编写配置文件: 在eureka-server服务中将它自己的服务名称和相关的实例地址信息注册到eureka-server服务上,便于和其他eureka集群之间的通信

server:port: 10086 # 服务端口spring:application:name: eureka-server # eureka的服务名称# eureka服务将自己的信息注册到Eureka服务端eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka

第四步:启动微服务然后在浏览器访问http://localhost:10086/

服务注册

第一步引入依赖: 在user-service,order-service模块的pom.xml文件中引入Eureka的客户端依赖spring-cloud-starter-netflix-eureka-client

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

第二步服务注册: 在user-service,order-service模块的application.yml中配置自己的服务的名称eureka-server服务的地址信息

spring:application:name: userservice # 服务名称# userservice服务将自己的信息注册到Eureka服务端eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka spring:application:name: orderservice # 服务名称# orderservice将自己的信息注册到Eureka服务端eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka

第三步模拟多实例部署: 在IDEA中复制一份user-service实例的配置重新设置Name同时配合VM选项修改端口号-Dserver.port=8082多次启动

第四步: 查看Eureka服务端注册的服务及其相关的所有实例

服务调用

服务发现

第一步引入依赖: 服务发现和服务注册统一都封装在Eureka的客户端依赖中,如果注册时已经引入了该依赖就不用重复引入了

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

第二步服务发现:只要orderservice服务注册到eureka-server服务中就可以拉取userservice服务的实例地址列表

  • orderservice模块的启动类中给注册的RestTemplate这个Bean上添加一个负载均衡的注解@LoadBalanced
  • order-service模块OrderService类中的queryOrderById方法中远程调用的访问路径中使用服务名(userservice)代替服务实例的ip和端口
  • Spring会自动帮我们从Eureka服务端根据userservice这个服务名称获取对应的实例地址列表,然后利用负载均衡算法选中一个实例地址并发起远程调用
@MapperScan("cn.itcast.order.mapper")@SpringBootApplicationpublic class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}}
public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.调用userservice服务远程查询User,使用服务的名称代替服务的IP地址和端口//String url = "http://localhost:8081/user/" + order.getUserId();String url = "http://userservice/user/" + order.getUserId();User user = restTemplate.getForObject(url, User.class);// 3.存入查询到的user对象order.setUser(user);// 4.返回return order;}