注册中心和负载均衡(黑马SpringCloud笔记)

news2024/11/26 0:34:43

注册中心和负载均衡

目录

  • 注册中心和负载均衡
    • 一、服务远程调用
      • 1. RestTemplate
      • 2. 服务调用关系
      • 3. 远程调用的问题
    • 二、注册中心
      • 1. Eureka注册中心
        • 1.1 搭建Eureka注册中心
        • 1.2 服务注册
        • 1.3 服务拉取
        • 1.4 小结
      • 2. nacos注册中心
        • 2.1Nacos搭建
        • 2.2 服务注册
        • 2.3 服务拉取
        • 2.4 服务分级存储模型
        • 2.5 权重配置
        • 2.6 环境隔离
        • 2.7 临时实例和非临时实例
        • 2.8 nacos配置管理
        • 2.9 nacos集群搭建
    • 三、Ribbon负载均衡
      • 1. 负载均衡策略
      • 2. 饥饿加载

一、服务远程调用

1. RestTemplate

假设有两个服务、两个数据库

查询订单服务:

@GetMapping("/order/{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
    // 根据id查询订单并返回
    return orderService.queryOrderById(orderId);
}

订单数据库中的订单表

在这里插入图片描述

查询用户服务

@GetMapping("/user/{id}")
public User queryById(@PathVariable("id") Long id) {
    return userService.queryById(id);
}

用户数据库中的用户表

在这里插入图片描述

启动服务,查询订单101:

http://localhost:8080/order/101,返回:

{
    "id":101,
    "price":699900,
    "name":"Apple 苹果 iPhone 12 ",
    "num":1,
    "userId":1,
    "user":null
}

查询用户 1:

http://localhost:8081/user/1,返回:

{
    "id":1,
    "username":"柳岩",
    "address":"湖南省衡阳市"
}

显然,我们需要在查询订单的时候,根据用户id再去调用查询用户的服务。

RestTemplate可以帮助我们发起Http请求,调用其他服务的REST接口:

  1. 配置

    @SpringBootConfiguration
    public class CustomConfiguration {
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
  2. 使用

    @Autowired注入后

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.调用REST接口查询数据
        User user = restTemplate.getForObject("http://localhost:8081/user/" + order.getUserId(), User.class);
        // 3.封装数据
        order.setUser(user);
        // 4.返回
        return order;
    }
    

再次查询订单101:

{
    "id":101,
    "price":699900,
    "name":"Apple 苹果 iPhone 12 ",
    "num":1,
    "userId":1,
    "user":{
        "id":1,
        "username":"柳岩",
        "address":"湖南省衡阳市"
    }
}

2. 服务调用关系

  • 服务提供者:暴露接口给其他微服务调用
  • 服务消费者:调用其他微服务提供的接口

在刚刚的例子中,查询用户的服务可以称为服务提供者,查询订单的服务需要去调用它,那么查询订单的服务可以称为服务消费者。

假如一个服务B调用了服务A服务C又调用了服务B,那么服务B是什么角色呢?

由此可见,服务提供者和消费者是相对的

3. 远程调用的问题

刚刚的例子中有这样一行代码:

User user = restTemplate.getForObject("http://localhost:8081/user/" + order.getUserId(), User.class);

环境变更后(ip),怎么办?难道去改代码重新编译?还有,如果只能调用8081,集群意义何在?

问题1:消费者如何获取提供者的地址信息?

问题2:如果有多个提供者,消费者如何选择?

问题3:消费者如何得知提供者的健康状态?

在这里插入图片描述

注册中心解决了这些问题。

二、注册中心

注册中心是用来记录管理服务的。

注册中心解决了之前服务调用的三个问题:

在这里插入图片描述

  1. 首先服务提供者需要在注册中心注册服务,注册中心记录服务。
  2. 服务消费者在注册中心拉取服务信息,负载均衡后,挑选一个服务使用。
  3. 向注册中心发送心跳包,若心跳异常则服务下线。

1. Eureka注册中心

1.1 搭建Eureka注册中心

搭建Eureka注册中心三步走即可:

  1. 引入Eureka依赖(服务端引入server依赖,客户端引入client)

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. 编写启动类,加上@EnableEurekaServer注解

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServiceApplication.class, args);
        }
    }
    
  3. application.yml配置

    server:
      port: 10086
    spring:
      application:
        name: eurekaServer
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://127.0.0.1:10086/eureka/
    

这样就搭建了一个Eureka注册中心,访问ip+端口即可看到Eureka管理面板。

1.2 服务注册

注册一个服务

  1. 引依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  2. application.yml中配置

    eureka:
      client:
        serviceUrl: #???????????
          defaultZone: http://127.0.0.1:10086/eureka/
    

可以在启动类上加一个@EnableEurekaClient注解,不加暂时看起来也可以注册。然后直接启动,就可以在Eureka管理面板中看到一个新实例。

1.3 服务拉取

之前的代码是这样的:

User user = restTemplate.getForObject("http://localhost:8081/user/" + order.getUserId(), User.class);

现在我们不再把ip写死,而是去Eureka注册中心拉取服务,两步:

  1. 将ip改为服务名

    User user = restTemplate.getForObject("http://userservice/user/" + order.getUserId(), User.class);
    
  2. 添加负载均衡注解@LoadBalanced

    @SpringBootConfiguration
    public class CustomConfiguration {
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    

测试一下:

在这里插入图片描述

1.4 小结

在这里插入图片描述

2. nacos注册中心

nacos不仅可以作为注册中心,还有很多功能。

2.1Nacos搭建

下载nacos

下载对应系统版本的解压即可。

在/conf/application.properties下可以配置nacos的运行端口等。

在/bin目录下打开命令行,输入

startup.cmd -m standalone

单机启动nacos

访问控制台提供的url即可访问管理面板:

在这里插入图片描述

默认用户名密码都是nacos

2.2 服务注册

  1. 加入spring-cloud-alibaba的管理依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.5.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    
  2. 添加nacos客户端依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  3. 配置nacos注册中心地址

    spring:
     cloud:
      nacos:
        server-addr: localhost:8848
    

启动后,即可在nacos管理面板中发现该服务。

2.3 服务拉取

把刚刚的两个服务从Eureka换成nacos后,测试。

在这里插入图片描述

有一个小小的坑,那就是nacos的服务名是要区分大小写的,Eureka是不区分的,所以要特别注意服务名,不然会请求失败。

2.4 服务分级存储模型

也就是可以给服务分组。这个模型是这样的:

在这里插入图片描述

可以通过discovery.cluster-name来配置

spring:
 cloud:
  nacos:
   server-addr: localhost:8848
   discovery:
     cluster-name: SC

我们启动三个userservice实例,两个配置为SC,一个配置为SH,查看nacos变化:

在这里插入图片描述

设置这个有啥用呢?我们可以配置负载均衡规则来让ribbon优先调用和自己的discovery.cluster-name一样的服务集群。

配置:

userService:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

重启服务后请求order-service,多请求几次会发现,调用的都是clustername为SC的服务(order-service的clusterName也要设置为SC)。

2.5 权重配置

经过如上配置后,我们请求orderservice时,orderservice就会去找集群名一样的userservice,然后以轮询的方式请求,现在我们可以通过nacos管理面板来配置服务的权重,来控制服务被访问的频率。

  • 权重一般配置为0~1之间
  • 权重为0则服务不会被访问

2.6 环境隔离

nacos还可以配置namespace来进行环境隔离

在这里插入图片描述

不同namespace之间不能互相访问。

  1. nacos管理面板创建命名空间,不填id的话会自动生成uuid

  2. 在application.yml中配置命名空间,例如修改orderservice的命名空间:

    spring:
     cloud:
      nacos:
        server-addr: localhost:8848
        discovery:
          cluster-name: SC
          namespace: c8ae37f8-748e-4ada-8a9e-a9fb42c38116
    

重启实例后,请求orderservice,此时orderservice无法找到userservice。

2.7 临时实例和非临时实例

两者健康检测机制不同。

  • 临时:定时发送心跳给nacos,不健康的临时实例会被nacos剔除
  • 非临时:nacos主动发请求询问,不健康的非临时实例不会被nacos剔除

配置,ephemeral属性:

spring:
 cloud:
  nacos:
   server-addr: localhost:8848
   discovery:
    ephemeral: false

nacos会主动推送消息给消费者告诉某个服务挂了,eureka不会。

2.8 nacos配置管理

服务很多时,配置复杂繁琐,统一配置管理解决了很多问题。

  1. 在nacos管理面板上创建配置文件:

在这里插入图片描述

  1. 为了在读取application.yml前读取nacos配置文件,我们需要创建一个bootstrap.yml文件(里面存放nacos的地址等信息),该文件会在application.yml前读取:

    需要引入依赖:

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    

    创建bootstrap.yml(resource目录下):

    spring:
      application:
        name: userService
      profiles:
        active: dev
      cloud:
        nacos:
          server-addr: localhost:8848
          config:
            file-extension: yaml
    
  2. 写个接口测试一下(配置热更新加上@RefreshScope注解):

    @Slf4j
    @RestController
    @RequestMapping("/user")
    @RefreshScope
    public class UserController {
        @Value("${pattern.dateformat}")
      
        @GetMapping("/now")
        public String now() {
            return new SimpleDateFormat(dateformat, Locale.CHINA).format(new Date());
        }
    }
    

使用@ConfigurationProperties(prefix = "pattern")也可以热更新

稍微解释一下刚刚bootstrap.yml里面配置的东西:

微服务会去nacos读取多个配置文件(如果有)

  • [spring.application.name]-[profiles.active].yaml
  • [spring.application.name].yaml

配置内容相同的部分,前者优先级大于后者(本地优先级最低),可以在nacos中再建一个配置文件试试,后者就可以存放公共配置,实现多环境配置共享。

2.9 nacos集群搭建

在这里插入图片描述

部署多个nacos,并用nginx做负载均衡。

五个步骤:

  1. 搭建MySQL集群并初始化数据库表:

    sql:https://github.com/alibaba/nacos/blob/master/distribution/conf/mysql-schema.sql

  2. 下载解压nacos

  3. 配置nacos

    在conf目录下创建cluster.conf配置文件并按照cluster.conf.example的内容配置节点。

    # 配置nacos节点
    127.0.0.1:8847
    127.0.0.1:8849
    127.0.0.1:8851
    

    配置application.properties

    spring.datasource.platform=mysql
    db.num=1
    
    db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
    db.user.0=nacos
    db.password.0=nacos
    
  4. 启动nacos

    三台nacos分别启动,在bin目录下运行startup.cmd

    启动即可。

    这里有个小坑:

    Nacos2.0版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口。新增端口是在配置的主端口(server.port)基础上,进行一定偏移量自动生成。

    端口与主端口的偏移量描述
    98481000客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求
    98491001服务端gRPC请求服务端端口,用于服务间同步等

    也就是在同一台机器上,如果搭建集群,建议使用8848,8850,8852,这种有间隔的端口,否则可能导致端口冲突。

  5. nginx负载均衡

    upstream nacos-cluster {
        server 127.0.0.1:8847;
        server 127.0.0.1:8849;
        server 127.0.0.1:8851;
    }
    
    server {
        listen       80;
        server_name  localhost;
    
        location /nacos {
            proxy_pass http://nacos-cluster/nacos/;
        }
    }
    

    启动nginx后访问localhost/nacos即可访问。

    代码中将以前的8848改为80端口即可。

三、Ribbon负载均衡

1. 负载均衡策略

http://userservice/user/1 这个地址dns是解析不出来的,所以在order-service和user-service之间肯定有个东西能让他们通信,那就是Ribbon,Ribbon拿到这个地址后,根据配置的负载均衡策略去调用相应的服务实例。

在这里插入图片描述

Ribbon默认是ZoneAvoidanceRule策略,Eureka可配置的策略有:

在这里插入图片描述

配置策略有两种方式,代码方式和配置文件:

  1. 代码方式:

    @Bean
    public IRule randomRule() {
        return  new RandomRule();   
    }
    
  2. 配置文件:

    userService:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    

2. 饥饿加载

ribbon默认是懒加载,即客户端第一次请求服务时,ribbon才会去拉取服务列表,这样会导致第一次请求延迟大。我们可以设置饥饿加载策略来让ribbon在客户端创建时就拉取服务列表,降低第一次访问耗时。

在application.yml中配置:

ribbon:
  eager-load:
    enabled: true
    clients:
      - userservice

clients是一个数组,里面写需要饥饿加载的服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虹科新闻 | 虹科与丹麦Eupry正式建立合作伙伴关系

近期&#xff0c;虹科与丹麦Eupry正式建立合作伙伴关系。未来&#xff0c;虹科与Eupry将共同关注最具创新性和稳定性的解决方案&#xff0c;为客户提供温度记录仪、温湿度记录仪、Mapping温度分布验证服务、以及基于云的温湿度自动监测系统。 虹科非常高兴欢迎并宣布我们的新合…

【Linux】基础:进程信号

【Linux】基础&#xff1a;进程信号 摘要&#xff1a;本文将会从生活实际出发&#xff0c;由此掌握进程信号的学习过程&#xff0c;分别为信号的产生、信号的传输、信号的保存和信号的处理&#xff0c;最后再补充学习信号后方便理解的其他概念。 文章目录【Linux】基础&#xf…

echarts柱状图值为0时不显示以及柱状图百分比展示

echarts柱状图值为0时不显示以及柱状图百分比展示 1.效果展示 2.代码 <template><div id"container"><div id"main"></div></div> </template> <script>import * as echarts from echarts import * as lodash…

(JVM)浅堆深堆与内存泄露

​浅堆深堆与内存泄露 1. 浅堆&#xff08;Shallow Heap&#xff09; 浅堆是指一个对象所消耗的内存。在 32 位系统中&#xff0c;一个对象引用会占据 4 个字节&#xff0c;一个 int 类型会占据 4 个字节&#xff0c;long 型变量会占据 8 个字节&#xff0c;每个对象头需要占用…

01.【Vue】Vue2基础操作

一、Vue Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&…

十五天学会Autodesk Inventor,看完这一系列就够了(七),工程图纸

众所周知&#xff0c;Autocad是一款用于二维绘图、详细绘制、设计文档和基本三维设计&#xff0c;现已经成为国际上广为流行的绘图工具。Autodesk Inventor软件也是美国AutoDesk公司推出的三维可视化实体模拟软件。因为很多人都熟悉Autocad&#xff0c;所以再学习Inventor&…

自动化测试 | 这些常用测试平台,你们公司在用的是哪些呢?

本文节选自霍格沃兹测试学院内部教材 测试管理平台是贯穿测试整个生命周期的工具集合&#xff0c;它主要解决的是测试过程中团队协作的问题。在整个测试过程中&#xff0c;需要对测试用例、Bug、代码、持续集成等等进行管理。下面分别从这四个方面介绍现在比较流行的管理平台。…

Spring入门-SpringAOP详解

文章目录SpringAOP详解1&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知…

Anaconda+VSCode配置tensorflow

主要参考https://blog.csdn.net/qq_42754919/article/details/106121979vscode的安装以及Anaconda的安装网上有很多教程&#xff0c;大家可以自行百度就行。在安装Anaconda的时候忘记勾选自动添加path&#xff0c;需要手动添加环境变量path下面介绍tensorflow安装教程:1.打开An…

getRequestDispatcher()转发和sendRedirect()重定向介绍与比较

文章目录1. request.getRequestDispatcher()1.1请求转发和请求包含的区别1.2request域2.response.sendRedirect()3.请求转发与重定向的区别比较测试1. request.getRequestDispatcher() getRequestDispatcher()包含两个重要方法&#xff0c;分别是请求转发和请求包含。一个请求…

系分 - 案例分析 - 系统设计

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录系分 - 案例分析 - 系统设计结构化设计SD内聚偶然内聚逻辑内聚时间&#xff08;瞬时&#xff09;内聚过程内聚通信内聚顺序内聚功能内聚耦合内容耦合公共耦合外部耦合控制耦合标记耦合数据耦合非直接耦合补…

DTO 与 PO的相互转换

目录 常见Bean映射框架 Dozer Orika MapStruct ModelMapper JMapper 测试模型 转化器 OrikaConverter DozerConverter MapperStructConvert JMapperConvert ModelMapperConverter 测试 平均时间 吞吐量 SingleShotTime 采集时间 DTO&#xff08;Data Transfer …

Android项目Gadle统一依赖管理

一.Gradle管理依赖版本 在中大型Android项目中&#xff0c;都会有多个Module进行协同配合。这些module中可能会依赖同一个库的不同版本&#xff0c;这将导致一些问题&#xff0c;要么是代码冲突&#xff0c;要么是APK包体积增大&#xff0c;亦或是项目构建的时间变长&#xff…

在Revit里如何将普通墙与曲面墙的内壁连接

在Revit里如何将普通墙与曲面墙的内壁连接&#xff1f;创建异形建筑时&#xff0c;为了达到如图1所示的效果&#xff0c;该如何操作&#xff1b; 我们可以使用体量建模的方式来创建该类建筑&#xff0c;要点在于如将幕墙与曲面墙的内壁连接。具体方法如下&#xff1a; 一、创建…

ASP.NET Core+Element+SQL Server开发校园图书管理系统(一)

随着技术的进步&#xff0c;跨平台开发已经成为了标配&#xff0c;在此大背景下&#xff0c;ASP.NET Core也应运而生。本文主要基于ASP.NET CoreElementSql Server开发一个校园图书管理系统为例&#xff0c;简述基于MVC三层架构开发的常见知识点&#xff0c;仅供学习分享使用&a…

ubuntu20.04下出现protoc与gazebo版本问题

ubuntu20protocgazebo问题描述问题定位解决方案问题描述 今天在搞路径规划算法时&#xff0c;从git上拉下来一个算法&#xff0c;ros环境那些都有&#xff0c;但是在编译的时候出现了如下图所示的一下问题&#xff1a;&#xff08;为了方便搜索关键词&#xff09; In file incl…

锂离子电池热失控预警资料整理(三)

此前 个人搜集了一些锂电池热失控预警相关期刊、文献&#xff0c;并整理了一些个人认为重要的逻辑、知识点&#xff0c;希望通过此分享让有需要的人了解一些内容&#xff0c;如有问题欢迎同我探讨~ 锂离子电池热失控预警资料整理&#xff08;三&#xff09;九、基于数据分析的锂…

C语言基于FOC控制算法和STM32主控芯片的双路直流无刷电机控制器源码

【FOCSTM32】双路直流无刷电机矢量控制器-使用文档 &#x1f4d5; 介绍 控制器主控芯片采用STM32F405RGT6&#xff0c;控制器底层基于HAL库和FreeRTOS实时操作系统&#xff0c;预留CAN、USART、SWD、USB接口各一&#xff0c;便于通信和控制的工程应用。该控制器提供双路无刷电…

2022年艺术品和古董投资策略研究报告

第一章 行业概况 艺术品是艺术家智力劳动成果的结晶。作为一种特殊商品流通于艺术市场&#xff0c;与其他商品相同的是&#xff0c;它也具备普通商品的基本属性&#xff1a;使用价值和价值。不同的是&#xff0c;艺术品的使用价值体现在精神层面而不是物质层面上&#xff0c;它…

RabbitMQ消息队列实战(1)—— RabbitMQ的体系

RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;用来在不同的应用之间共享数据。1983年&#xff0c;被认为是RabbitMQ的雏形的Teknekron创建&#xff0c;首次提出了消息总线的概念。中间经历过数个阶段的发展&#xff0c;一直到2004年&#xff0c;AMQP&#xff08;Advan…