【SpringCloud】02 注册中心Eureka的原理与使用

阅读提示:

本文是SpringCloud系列第二篇,请先阅读前置文章。
所有代码都基于01认识微服务,了解服务拆分与远程调用中的基础代码cloud-demo,可以前往下载。

一、问题引入

在上一篇文章中,我们在OrderService类的queryOrderById方法里,使用RestTemplate里向user-service微服务发起调用请求,根据用户id查询用户信息,代码如下:

// 2.使用RestTemplate发起http请求 实现远程调用
String url = "http://localhost:8081/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);

当前存在的问题
在微服务中,往往一个服务模块如这里的user-service服务,会部署在多台机器上以应对高并发访问,因此会有多个实例及地址,以本机部署三个user-service服务为例,它们的端口号分别为8081,8082,8083,如下图:
在这里插入图片描述
那么这时我依然使用之前的RestTemplate发起访问请求,会存在以下几个问题:

// 2.使用RestTemplate发起http请求 实现远程调用
String url = "http://localhost:8081/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
  • user-service实例的ip地址和端口变化时,order-service该如何得知?
    很显然目前我们只能把user-service实例的地址写死在order-service的配置文件中,当user-service实例的地址和端口变化,也要修改order-service的配置文件,说不定还有很多其他微服务,也要调用user-service,当不得已修改user-service实例的地址和端口时,重新部署非常麻烦。
  • 有多个user-service实例的地址时,order-service该选择哪一个?
    1.首先固定选择其中某一个实例,肯定是不合适,因为只要这个user-service实例宕机,调用它的order-service实例也就宕机了,会影响微服务架构的稳定性、可用性。
    2.那么该怎么选择呢?这很难选,因为order-service不知道哪一个实例是健康的,哪一个已经宕机;或者哪一个当前服务器资源比较紧张,暂时不应该访问的(负载均衡)。而且RestTemplate的url地址是写死的,虽然可以在运行过程中修改url地址,但还是回到了问题本身,不清楚该选择哪一个。

二、Eureka的结构与作用

上述问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:
在这里插入图片描述
回答上述两个问题。

  • user-service实例的ip地址和端口变化时,order-service该如何得知?
    user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端),这个叫服务注册。
    eureka-server保存服务名称到服务实例地址列表的映射关系。
    order-service根据user-service服务名称,拉取其实例地址列表。这个叫服务发现。
    在这种服务注册与发现的方式下,order-service甚至不需要把user-service的具体地址写入自己的配置文件中,只需要在访问user-service时,去Eureka服务端拉取目前的user-service服务实例的地址即可。
  • 有多个user-service实例的地址时,order-service该选择哪一个?
    使用@LoadBalanced注解,让order-service从user-service的实例列表中利用负载均衡算法选择其中一个实例地址;并且user-service的实例会定时向Eureka服务端发送心跳,超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除,order-service拉取服务时,就能将故障实例排除了,这就保证了order-service选择user-service实例时,既能保证保证均衡,又能保证排除故障实例。

因此注册中心解决的主要问题就是微服务之间进行远程调用时,让微服务之间能够互相发现对方,同时一定程度上可以监测微服务的健康状态,并提供负载均衡的功能,归根到底解决的就是远程调用时选择哪个实例这一个问题。

注意: 一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端,且每个微服务启动时都会将自己注册到Eureka服务端中。

三、搭建Eureka-server

首先搭建注册中心服务端:eureka-server,这必须是一个独立的微服务。
在cloud-demo模块下,创建一个子模块maven工程,命名为eureka-server。
在这里插入图片描述
引入SpringCloud为eureka提供的starter依赖:

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

给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:

package cn.itcast.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

编写配置文件application.yml,内容如下:这里我们设置eureka-server的ip为本机的10086端口

server:
  port: 10086
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka

启动微服务EurekaApplication,然后在浏览器访问:http://127.0.0.1:10086
看到下面结果就是成功了:
在这里插入图片描述

四、服务注册与发现

前面已经说过,一个微服务既可以是服务的提供者,也可以是服务消费者,因此只需要使用同一个依赖spring-cloud-starter-netflix-eureka-client,就可以同时实现一个微服务的注册与发现。

4.1 配置user-service

(1) 引入依赖
在user-service的pom文件中,引入下面的eureka-client(eureka客户端)依赖:

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

(2) 修改配置文件
在user-service中,修改application.yml文件,添加服务名称、eureka地址:
后续其他服务要访问user-service,就是通过这个服务名称来发起请求,因此这里命名最好规范。

spring:
  application:
    name: userservice 
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

(3) 使用IDEA启动多个user-service实例
首先,右键复制原来的user-service启动配置:
在这里插入图片描述
修改运行实例名称为UserApplication2,点击Modify options,点击Add VM Options
在这里插入图片描述
在这里插入图片描述
接着填写-Dserver.port=8082来修改运行端口号
在这里插入图片描述
启动两个User-service实例,可以在eureka控制台看到如下信息:
在这里插入图片描述

4.2 配置order-service

之前说过,服务发现、服务注册统一都封装在eureka-client依赖,因此引入依赖和与配置文件的修改和user-service基本一致。
(1) 引入依赖
在order-service的pom文件中,引入下面的eureka-client依赖

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

(2) 修改配置文件
在order-service中,修改application.yml文件,添加服务名称、eureka地址

spring:
  application:
    name: orderservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

(3) 服务拉取与负载均衡
负载均衡的设置
在order-service的OrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:

    /**
     * 创建RestTemplate并注入Spring容器
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

服务拉取
修改order-service服务中的cn.itcast.order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名userservice代替ip+端口的url

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.使用RestTemplate发起http请求 实现远程调用
        String url = "http://userservice/user/"+order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        // 封装到order中
        order.setUser(user);
        // 4.返回
        return order;
    }

@LoadBalanced注解可以让RestTemplate能够识别服务的名称而不是直接使用URL。这样,发送HTTP请求时,RestTemplate会根据服务名称来选择一个可用的实例进行调用。它会根据负载均衡策略,在多个实例之间分配请求,以达到负载均衡的效果,当然前提是结合注册中心使用。
详细原理请阅读:https://zhuanlan.zhihu.com/p/617967367

4.3 效果测试

重新启动OrderApplication,浏览器访问localhost:8080/order/101,可以发现IDEA控制台中8081和8082端口的UserApplication服务轮流打印信息,因此注册中心部署和服务注册、发现,负载均衡都成功实现。

  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值