• 【黑马-SpringCloud技术栈】【03】Eureka注册中心_Ribbon负载均衡



    持续学习&持续更新中…

    守破离


    Eureka注册中心

    远程服务调用出现的问题

    • 服务消费者该如何获取服务提供者的地址信息?
    • 如果有多个服务提供者,消费者该如何选择?
    • 消费者如何得知服务提供者的健康状态?

    在这里插入图片描述

    Eureka原理

    这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:

    在这里插入图片描述

    在Eureka架构中,微服务角色有两类:

    1. EurekaServer:服务端,注册中心
      • 记录服务信息
      • 心跳监控
    2. EurekaClient:客户端
      • Provider:服务提供者,例如案例中的 user-service
        注册自己的信息到EurekaServer
        每隔30秒向EurekaServer发送心跳
      • consumer:服务消费者,例如案例中的 order-service
        根据服务名称从EurekaServer拉取服务列表
        基于服务列表做负载均衡,选中一个微服务后发起远程调用

    Eureka如何解决这些问题

    服务消费者该如何获取服务提供者的地址信息?

    • 服务提供者启动时向eureka注册自己的信息
    • eureka保存这些信息
    • 消费者根据服务名称向eureka拉取提供者信息

    如果有多个服务提供者,消费者该如何选择?

    • 服务消费者利用负载均衡算法,从服务列表中挑选一个

    消费者如何得知服务提供者的健康状态?

    • 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
    • eureka会更新记录服务列表信息,心跳不正常会被剔除
    • 消费者就可以拉取到最新的信息

    动手实践

    在这里插入图片描述

    搭建EurekaServer

    创建项目,引入spring-cloud-starter-netflix-eureka-server的依赖

    <dependency>
    	<groupId>org.springframework.cloudgroupId>
    	<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    编写启动类,添加@EnableEurekaServer注解

    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    添加application.yml文件,编写下面的配置:

    server:
      port: 10086 # eureka服务端口
    # 服务注册
    spring:
      application: # eureka自己也是一个微服务,需要注册自己到eureka上
        name: eurekaserver # eureka服务名称
    eureka:
      client:
        service-url: # eureka服务地址
          defaultZone: http://127.0.0.1:10086/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    成功后,在浏览器中输入:http://localhost:10086/查看Eureka的管理页面。

    服务注册

    在user-service项目引入spring-cloud-starter-netflix-eureka-client的依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在application.yml文件,编写下面的配置:

    server:
      port: 8081
    spring:
      application:
        name: userservice
    eureka:
      client:
        service-url: # eureka服务地址
          defaultZone: http://127.0.0.1:10086/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    另外,我们可以将user-service多次启动, 模拟多实例部署,但为了避免端口冲突,需要修改端口设置:

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    服务发现

    order-service虽然是消费者,但与user-service一样都是eureka的client端,同样可以实现服务注册:

    在order-service项目引入spring-cloud-starter-netflix-eureka-client的依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在application.yml文件,编写下面的配置:

    server:
      port: 8080
    spring:
      application:
        name: orderservice
    eureka:
      client:
        service-url: # eureka服务地址
          defaultZone: http://127.0.0.1:10086/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡

    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    @Service
    public class OrderService {
        @Autowired
        private OrderMapper orderMapper;
        @Autowired
        private RestTemplate restTemplate;
    
        public Order queryOrderById(Long orderId) {
            // 1.查询订单
            Order order = orderMapper.findById(orderId);
            // 2.查询用户
    //        String url = "http://localhost:8081/user/" + order.getUserId();
    		// 修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:
    		// 使用Eureka的服务名称
            String url = "http://userservice/user/" + order.getUserId();
            User user = restTemplate.getForObject(url, User.class);
            // 3.封装user信息
            order.setUser(user);
            // 4.返回
            return order;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端;无论是消费者还是提供者,引入eureka-client依赖、知道eureka地址后,都可以完成服务注册

    总结1

    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拉取服务时,就能将故障实例排除了

    总结2

    搭建EurekaServer:

    • 引入eureka-server依赖
    • 添加@EnableEurekaServer注解
    • 在application.yml中配置eureka地址

    服务注册:

    • 引入eureka-client依赖
    • 在application.yml中配置eureka地址

    服务发现:

    • 引入eureka-client依赖
    • 在application.yml中配置eureka地址
    • 给RestTemplate添加@LoadBalanced注解
    • 用服务提供者的服务名称远程调用

    Ribbon负载均衡

    SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。

    负载均衡原理

    在这里插入图片描述

    在这里插入图片描述

    基本流程如下:

    • 拦截我们的RestTemplate请求http://userservice/user/1
    • RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
    • DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
    • Eureka返回列表,localhost:8081、localhost:8082
    • IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
    • RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求

    负载均衡策略

    Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则:

    在这里插入图片描述

    默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询。

    在这里插入图片描述

    通过定义IRule实现可以修改负载均衡规则,有两种方式:

    • 代码方式【配置灵活,但修改时需要重新打包发布】:在order-service中的OrderApplication类中,定义一个新的IRule:

      @MapperScan("cn.itcast.order.mapper")
      @SpringBootApplication
      public class OrderApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(OrderApplication.class, args);
          }
      
          @Bean
          @LoadBalanced
          public RestTemplate restTemplate() {
              return new RestTemplate();
          }
      
          @Bean
          public IRule iRule() {
              return new RandomRule();
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • 配置文件方式【直观,方便,无需重新打包发布,但是无法做全局配置】:在order-service的application.yml文件中,添加新的配置也可以修改规则:

      userservice: # 只针对某个微服务
        ribbon:
          NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
      
      • 1
      • 2
      • 3

    注意,一般用默认的负载均衡规则,不做修改。

    懒加载和饥饿加载

    Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载。

    在order-service的application.yml:

    ribbon:
      eager-load:
        enabled: true # 开启饥饿加载 
        clients: userservice # 指定对userservice这个服务饥饿加载
    
    • 1
    • 2
    • 3
    • 4

    参考

    黑马程序员:SpringCloud微服务技术栈.


    本文完,感谢您的关注支持!


  • 相关阅读:
    [Vue]写一个简单的文件上传控件
    PID参数调节的经验
    关于重写equals方法引发的不一致
    网络是怎样连接的 - 读书笔记
    用 Python 实现微信推送消息
    6、行内元素和块元素
    Linux的权限
    时间序列分析|异常值检测
    亚马逊纽扣电池、含纽扣电池产品新规标准
    三七皂苷-壳聚糖(PNS-CSB)水凝胶/聚乙烯吡咯烷酮/pH敏感性羧甲基/壳聚糖水凝胶的制备
  • 原文地址:https://blog.csdn.net/weixin_44018671/article/details/124515992