SpringCloud Alibaba【Nacos集群搭建(Windows+Linux)&Ribbon负载均衡】

SpringCloud Alibaba

中文官方文档

开源地址

在这里插入图片描述

】一切模块均以maven 项目创建

  • 父依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.vinjcent</groupId>
    <artifactId>springcloud</artifactId>
    <packaging>pom</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <modules>
        <module>springcloud-provider-dept-8001</module>
        <module>springcloud-consumer-dept-80</module>
    </modules>
    <name>springcloud</name>

    <description>SpringCloud Alibaba</description>

    <properties>
        <java.version>1.8</java.version>
        <spring.cloud.alibaba.version>2.2.5.RELEASE</spring.cloud.alibaba.version>
        <spring.boot.version>2.3.11.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR8</spring.cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--SpringCloud alibaba 管理-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--SpringBoot 管理-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--SpringCloud 管理-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1. Alibaba 微服务组件 Nacos 注册中心(Eureka服务注册与发现)


1.1 什么是 Nacos

官方:一个更易于构建云原生态应用的动态服务(Nacos Discovery)、服务配置(Nacos Config)和服务管理平台

Nacos 的关键特性包括:

  • 服务发现和服务健康检测
  • 动态配置服务
  • 动态DNS服务
  • 服务及其元数据管理

CAP 理论

  • C–一致性

    • 访问所有的节点,得到的数据结果都是一样的。注意:这里的一致性指的是强一致性,也就是数据更新完,访问任意节点,看到的数据完全一致,要和弱一致性、最终一致性区分开来
  • A–可用性

    • 所有节点都保持高可用性。注意:这里的高可用还包括,不能出现延迟,如节点B由于等待数据同步而阻塞了请求,那么节点B就不满足高可用性
  • P–分区容错性

    • 这里的分区指的是网络意义上的分区。由于网络是不可靠的,所有节点之间很可能出现无法通讯的情况,在节点不能通信时,要保证系统可以继续正常服务

主流的注册中心

功能NacosEurekaConsulCoreDNSZookeeper
一致性CP + APAPCPCP
健康检查TCP/HTTP/MYSQL/Client/BeatClient/BeatTCP/HTTP/gRPCKeep Alive
负载均衡策略权重/metadata/SelectorRibbonFabioRoundRobin
雪崩保护
自动注销实例支持支持支持不支持支持
访问协议HTTP/DNSHTTPHTTP/DNSDNSTCP
监听支持支持支持支持不支持支持
多数据中心支持支持支持不支持不支持
跨注册中心同步支持不支持支持不支持不支持
SpringCloud集成支持支持支持不支持支持
Dubbo集成支持不支持支持不支持支持
K8S集成支持不支持支持支持不支持

1.2 服务与注册中心

在Windows上部署

  1. github下载 Nacos 安装包:https://github.com/alibaba/nacos

选择 2.0.1 版本

在这里插入图片描述

在这里插入图片描述

  1. /bin目录下,修改startup.cmd文件,设置为单机模式
set MODE="standalone"

在这里插入图片描述

  1. 运行startup.cmd文件

在这里插入图片描述

  1. 访问地址命令窗口显示的地址http://192.168.166.1:8848/nacos/index.html

用户名、密码 都为 nacos

在这里插入图片描述

  1. 创建一个项目springcloud-api,用于构建对象与接口API

1)导入依赖

  • pom.xml
    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2)编写实体类

  • Department
@Data
@NoArgsConstructor
@Accessors(chain = true)      // 链式写法
public class Department implements Serializable {   // 实体类 orm 类表关系映射

    private Long deptId;    	// 主键
    private String deptName;    // 部门名

    // 这个数据存在哪个数据库的字段  微服务,一个服务对应一个数据库,同一个信息可能存在不同的数据库
    private String db_source;

    public Department(String deptName) {
        this.deptName = deptName;
    }

    /**
     * 链式写法:
     * Department dept = new Department();
     *
     * 原来dept.setName();
     *
     * 加了之后:
     * dept
     *      .setDeptName()
     *      .setDeptId()
     *      .setDb_source();
     *
     */

}
  1. 创建一个项目 springcloud-provider-dept-8001,导入依赖
<dependencies>
    <dependency>
        <groupId>com.vinjcent</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <!--web-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--nacos-服务注册与发现-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>
  1. 配置application.yml
# 端口号
server:
  port: 8001

spring:
  application:
    name: springcloud-provider-dept   # 应用名称
  # 配置nacos
  cloud:
    nacos:
      # nacos 服务地址
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos   # nacos用户名
        password: nacos
        namespace: public   # 分隔开发环境和测试环境使用
  1. 启动 springcloud-provider-dept-8001 项目

在这里插入图片描述

  1. 将我们的 springcloud-provider-dept-8001 项目终止,nacos 会更改服务的健康状态(一般是15s左右),如果一定时间内 nacos 没有接受到心跳,会剔除该注册用户(一般是30s左右)

在这里插入图片描述

1.3 使用 nacos 服务与注册,通过应用名访问

官方手册

  1. 创建一个 springcloud-consumer-dept-80 模块(消费端)

  2. 导入依赖

  • pom.xml
<dependencies>
    <dependency>
        <groupId>com.vinjcent</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <!--web-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--nacos-服务注册与发现-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

</dependencies>
  1. 在类中配置 RestTemplate 模板
@Configuration
public class ConfigBean {
    @Bean
    public RestTemplate getRestTemplate(RestTemplateBuilder builder){
        return builder.build();
    }
}
  1. 再写一个 controller
  • DeptController
@RestController
@RequestMapping("/consumer")
@SuppressWarnings("all")
public class DeptController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/dept/msg")
    public String getMessage(){
        return restTemplate.getForObject("http://springcloud-provider-dept/dept/msg",String.class);
    }

}
  1. 配置application.yml文件
# 端口号
server:
  port: 80
  1. springcloud-provider-dept-8001 项目中写一个 controller
  • DeptController
@RestController
@RequestMapping("/dept")
@SuppressWarnings("all")
public class DeptController {

    @Value("${server.port}")
    private int port;

    @GetMapping("/msg")
    public String getMessage(){
        return "获取服务成功!"+port;
    }
}
  1. springcloud-consumer-dept-80 启动
  2. springcloud-provider-dept-8001 启动
  3. 访问 http://localhost/consumer/dept/msg

在这里插入图片描述

  • 问题

需要给消费者 springcloud-consumer-dept-80 添加负载均衡

在这里插入图片描述

原因:nacos 本身没有办法解析服务名称到我们的 nacos 服务地址

再次访问http://localhost/consumer/dept/msg

在这里插入图片描述

具体流程

在这里插入图片描述

扩展

默认的负载均衡机制轮询

在这里插入图片描述

1.4 有关 Nacos Discovery Starter 配置的更多信息

钥匙默认值描述
服务器地址spring.cloud.nacos.discovery.server-addrNacos Server监听的IP和端口
服务名称spring.cloud.nacos.discovery.service${spring.application.name}命名当前服务
重量spring.cloud.nacos.discovery.weight1取值范围:1~100,数值越大,权重越大
网卡名称spring.cloud.nacos.discovery.network-interface如果不指定IP地址,则注册的IP地址为网卡的IP地址。如果也没有指定,则默认使用第一块网卡的 IP 地址。
注册IP地址spring.cloud.nacos.discovery.ip最高优先级
注册端口spring.cloud.nacos.discovery.port-1默认会自动检测。不需要配置。
命名空间spring.cloud.nacos.discovery.namespace一个典型的场景是隔离不同环境的服务注册,例如测试和生产环境之间的资源(配置、服务等)隔离
访问密钥spring.cloud.nacos.discovery.access-key阿里云账号accesskey
密钥spring.cloud.nacos.discovery.secret-key阿里云账号秘钥
元数据spring.cloud.nacos.discovery.metadata您可以以 Map 格式为您的服务定义一些元数据
日志文件名spring.cloud.nacos.discovery.log-name
集群名称spring.cloud.nacos.discovery.cluster-nameDEFAULTNacos的集群名称
端点spring.cloud.nacos.discovery.endpoint特定区域中某项服务的域名。您可以使用此域名动态检索服务器地址
是否集成 Ribbonribbon.nacos.enabledtrue在大多数情况下设置为 true
启用 Nacos Watchspring.cloud.nacos.discovery.watch.enabledtrue设置为 false 监视

2. Nacos集群部署(eureka1、eureka2,eureka3)


Nacos官方文档

在这里插入图片描述

在Linux虚拟机上部署

2.1 在 Linux 虚拟机中配置 Nacos

Linux配置环境

1)64 bit OS Linux/Unix/Mac,推荐使用Linux系统

2)64 bit JDK 1.8+

3)Maven 3.2.x+

4)nginx 作为负载均衡(SLB)

  1. 在 github 下载Nacos安装包:

https://github.com/alibaba/nacos/releases

  • 选择 2.0.1 版本

在这里插入图片描述

  • 选择 Linux 系统的安装包

在这里插入图片描述

  1. 使用 XShell 和 Xftp 软件将压缩文件上传至我们的 Linux 虚拟机中

在这里插入图片描述

  1. 在 Linux 虚拟机中找到压缩包的位置,进行解压和重命名,并且复制三份

在这里插入图片描述

千万要注意,Nacos 下载的是2.0+版本的,端口号不能相连在一起,必须间隔>=2,如:7002、7004、7006

最后面有张图就是连在一起的报错结果!然后又得重新开始

当然,跟着我的步骤就好了!(端口间隔为10)

# 解压三次	并附带它们的端口号
# nacos-7070
[root@vinjcent nacos]# tar -zxvf nacos-server-2.0.1.tar.gz
[root@vinjcent nacos]# mv nacos nacos-7070
# nacos-7080
[root@vinjcent nacos]# tar -zxvf nacos-server-2.0.1.tar.gz
[root@vinjcent nacos]# mv nacos nacos-7080
# nacos-7090
[root@vinjcent nacos]# tar -zxvf nacos-server-2.0.1.tar.gz
[root@vinjcent nacos]# mv nacos nacos-7090

解压完后的三个文件显示

在这里插入图片描述

  1. 修改 nacos 的端口号,并打开以下几个设置

1)修改 nacos-7070application.properties文件

vim ./nacos-7070/conf/application.properties

在这里插入图片描述

在这里插入图片描述

  1. 创建数据库(必须创建,不然也会报错,因为上面的图片,我们设置了开启数据库连接

在 window 版的 nacos 中,该目录nacos-server-2.0.1\nacos\conf下有一个 nacos-mysql.sql 文件

在这里插入图片描述

在数据库中创建一个名为 nacos 的数据库,执行这个 sql 文件(使用的是Linux虚拟机下的数据库,不是本地的数据库!

在这里插入图片描述

5)设置 nacos 集群的关联端口

/usr/local/nacos/nacos-7070/conf下复制一份文件

cp cluster.conf.example cluster.conf		# 复制一份名为cluster.conf的文件

编辑 cluster.conf 文件

vim cluster.conf

编辑内容如下

在这里插入图片描述

回到\bin目录下编辑startup.sh文件(可以设置,可以不设置)

vim startup.sh
  • 由于个人虚拟机内存较小,如果你的虚拟机够大,就不需要更改了。更改内容如图所示

在这里插入图片描述

6)测试 nacos-7070 是否可以启动

# 在Linux虚拟机中开启端口7070
[root@vinjcent bin]# firewall-cmd --zone=public --add-port=7070/tcp --permanent
# 重启防火墙
systemctl restart firewalld.service
  • \bin目录下启动startup.sh
./startup.sh

在这里插入图片描述

使用命令查看是否启动成功(如果这里报错了,就是因为你是用的是你本机的数据库,需要在Linux系统安装数据库!

[root@vinjcent bin]# tail -f ../logs/start.out
  • 这个有点长,慢慢等

在这里插入图片描述

  • 启动成功!

  • 在本机(自己电脑)访问 Linux IP:7070/nacos/index.html#/login

在这里插入图片描述

  • 配置成功!

7)将/nacos-7070/conf/路径下的application.properties文件分别给 nacos-7080、nacos-7090 进行覆盖

# 覆盖nacos-7080/conf/application.properties文件
[root@vinjcent nacos]# cp ./nacos-7070/conf/application.properties ./nacos-7080/conf/application.properties
# 覆盖nacos-7090/conf/application.properties文件
[root@vinjcent nacos]# cp ./nacos-7070/conf/application.properties ./nacos-7090/conf/application.properties

8)将/nacos-7070/conf/路径下的cluster.conf文件也分别复制到 nacos-7080、nacos-7090

[root@vinjcent nacos]# cp ./nacos-7070/conf/cluster.conf ./nacos-7080/conf/cluster.conf
[root@vinjcent nacos]# cp ./nacos-7070/conf/cluster.conf ./nacos-7090/conf/cluster.conf

9)将nacos-7070/bin/路径下的startup.sh文件也分别给nacos-7080、nacos-7090进行覆盖

[root@vinjcent nacos]# cp ./nacos-7070/bin/startup.sh ./nacos-7080/bin/startup.sh
cp: overwrite ‘./nacos-7080/bin/startup.sh’? y
[root@vinjcent nacos]# cp ./nacos-7070/bin/startup.sh ./nacos-7090/bin/startup.sh
cp: overwrite ‘./nacos-7090/bin/startup.sh’? y

10)分别修改nacos-7080、nacos-7090application.properties文件里的端口号

[root@vinjcent nacos]# vim ./nacos-7080/conf/application.properties
[root@vinjcent nacos]# vim ./nacos-7090/conf/application.properties
  • nacos-7080

在这里插入图片描述

  • nacos-7090

在这里插入图片描述

11)在 Linux 虚拟机中,开启防火墙端口 7080、7090

# 开启7080端口
[root@vinjcent nacos]# firewall-cmd --zone=public --add-port=7080/tcp --permanent
# 开启7090端口
[root@vinjcent nacos]# firewall-cmd --zone=public --add-port=7090/tcp --permanent
# 重启防火墙
[root@vinjcent nacos]# systemctl restart firewalld.service

在这里插入图片描述

firewall-cmd --list-ports	# 只看端口信息

在这里插入图片描述

可以看到已经将7080、7090端口开启

12)分别启动 nacos-7080、nacos-7090startup.sh文件

[root@vinjcent nacos]# sh ./nacos-7080/bin/startup.sh
[root@vinjcent nacos]# sh ./nacos-7090/bin/startup.sh

在这里插入图片描述

下面这个图片就是使用 7001、7002、7003 相连端口报错的信息,所以我不得不重新修改端口再来一遍(请勿模仿!)

在这里插入图片描述

个人建议下载一个 XShell 和 Xftp 方便文件的修改

访问

http://虚拟机的IP:7080/nacos/index.html#/login
http://虚拟机的IP:7090/nacos/index.html#/login

在这里插入图片描述

在这里插入图片描述

用户名、密码都是 nacos

登陆后查看红色区域的页面

出现该页面即搭建 Nacos 集群成功!

在这里插入图片描述

修改 springcloud-provider-dept-8001 模块下的application.yml文件

在这里插入图片描述

2.2 Nacos自带的微服务负载均衡器 Ribbon

2.2.1 Ribbon 负载均衡策略

在这里插入图片描述

IRule
是所有负载均衡策略的父接口,里边的核心方法就是 choose 方法,用来选择一个服务实例

AbstractLoadBalancerRule

AbstractLoadBalancerRule 是一个抽象类,类里主要定义了一个 ILoadBalancer,就是我们上文所说的负载均衡器,用于定义它的目的主要是辅助负责均衡策略选取合适的服务端实例

  • RandomRule

    • 是一种负载均衡策略就是随机选择一个服务实例,看源码可以知道,在 RandomRule 的无参构造方法中初始化了一个 Random 对象,然后在它重写的 choose 方法又调用了,choose(ILoadBalancer lb.Obect key) 这个重载的 choose 方法,在这个重载的 choose 方法中,每次利用 random 对象生成一个不大于服务实例总数的随机数,并将该数作为下标所以获取一个服务实例
  • RoundRobinRule

    • RoundRobinRule 这种负载均衡策略叫做线性轮询负载均衡策略。这个类的 choose(ILoadBalancer lb.Objectkey)整体逻辑是这样的:开启一个计数器 count,在 while 循环中遍历服务清单,获取清单之前先通过 incrementAndGetModulo 方法获取一个下标,这个下标是一个不断自增的数,先加1然后和服务清单总数取模之后获取到的(所以这个下标从来不会越界),拿着下标再去服务清单列表中取服务,每次循环计数器都会加1,如果连续10次都没有取到服务,则会报一个警告No available alive servers after 10 tries from load balancer:ILoadBalancer
  • RetryRule (在轮询的基础上进行重试)

    • 这种负载均衡策略带有重试功能。首先 RetryRule 中又定义了一个 subRule,它的实现类是 RoundRobinRule,然后在 RetryRule 的 choose(ILoadBalancer lb,Object key) 方法中,每次还是采用 RoundRobinRule 中的 choose 规则来选择一个服务实例,如果选到的实例正常就返回,如果选择的服务实例为null或者已经失效,则在失效时间 deadline 之前不断的进行重试 (重试时获取服务的策略还是 RoundRobinRule 中定义的策略),如果超过了 deadline 还是没取到则会返回一个null
  • WeightedResponseTimeRule(权重–nacos 的 NacosRule,Nacos还扩展了一个自己的基于配置的权重扩展)

    • WeightedResponseTimeRule 是 RoundRobinRule 的一个子类,在 WeightedResponseTimeRule 中对 RoundRobinRule 的功能进行了扩展, WeightedResponseTimeRule 中会根据每一个实例的运行情况来给计算出该实例的一个权重,然后在挑选实例的时候则根据权重进行挑选,这样能够实现更优的实例调用。WeightedResponseTimeRule 中有一个名叫 DynamicServerWeightTask 的定时任务,默认情况下每隔30秒会计算一次各个服务实例的权重,权重的计算规则也很简单:如果一个服务的平均响应时间越短则权重越大,那么该服务实例被选中执行任务的概率也就越大
  • ClientConfigEnabledRoundRobinRule

    • ClientConfigEnabledRoundRobinRule 选择策略内部定义了 RoundRobinRule,choose 方法还是采用了 RoundRobinRule 的 choose 方法,所以它的选择策略和 RoundRobinRule的选择策略一致
  • BestAvailableRule

    • BestAvailableRule 继承自 ClientConfiqEnabledRoundRobinRule,它在ClientConficEnabledRoundRobinRule 的基础上主要增加了根据loadBalancerStats中保存的服务实例的状态信息来过滤掉失效的服务实例的功能,然后顺便找出并发请求最小的服务实例来使用,然而 loadBalancerStats 有可能为null,如果 loadBalancerStats 为null,则 BestAvailableRule 将采用它的父类即 ClientConfigEnabledRoundRobinRule 的服务选取策略(线性轮询)
  • ZoneAvoidanceRule默认规则,复合判断server所在区域的性能和server的可用性选择服务器)

    • ZoneAvoidanceRule 是 PredicateBasedRule 的一个实现类,只不过这里多了一个过滤条件,ZoneAvoidanceRule 中的过滤条件是以 ZoneAvoidancePredicate 为主过滤条件和以 AvailabilityPredicate 为次过滤条件组成的一个叫做 CompositePredicate 的组合过滤条件,过滤成功之后,继续采用线性轮询(RoundRobinRule)的方式从过滤结果中选择一个出来
  • AvailabilityFilteringRule(先过滤掉故障实例,再选择并发较小的实例)

    • 过滤掉一直连接失败的被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端Server或者使用一个 AvailabilityPredicate 来包含过滤server的逻辑,实质上就是检查status里记录的各个Server的运行状态

2.2.2 修改默认默认负载均衡策略

方式一(使用注解)

1)在消费端 springcloud-consumer-dept-80 模块下,创建一个RibbonStrategy.class类,注入一个 IRule 的bean

注意该包位置必须不在主启动类的包下,因为会被@ComponentScan注解扫描到

测试

@RibbonClients(value = {

@RibbonClient(name = "ProviderApplication1",configuration = xxx.class)			//随机策略

@RibbonClient(name = "ProviderApplication2",configuration = xxx.class)			//重试策略

})

public class ConfigBean {
		...
}

@RibbonClients 指定某个服务提供方使用的均衡策略

@ComponentScan注解扫描到,对于一个类配置了多个@RibbonClient,相当于全局配置的效果,比如上面一个是随机策略,一个是重试策略,如果将此类放在与主启动类同一个包下,重试策略将会失效,使得所有服务提供者使用同一个策略

如图所示

在这里插入图片描述

2)修改模块 springcloud-consumer-dept-80 中的application.yml文件

server:
  port: 80

spring:
  application:
    name: springcloud-consumer-dept
  # 配置nacos
  cloud:
    nacos:
      # nacos 服务地址
      server-addr: 192.168.159.100:7070,192.168.159.100:7080,192.168.159.100:7090
      discovery:
        username: nacos   # nacos用户名
        password: nacos
        namespace: public   # 分隔开发环境和测试环境使用

3)在主启动类上加上注解@RibbonClients

@SpringBootApplication
@RibbonClients(value = {
        /**
         * name 提供者应用名称
         * configuration 使用的是哪个负载均衡配置类
         */
        @RibbonClient(name = "springcloud-provider-dept",configuration = RibbonStrategy.class)
})
public class SpringCloud_Consumer_80 {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloud_Consumer_80.class,args);
    }
}

4)复制两份 springcloud-provider-dept-8001 模块,改名为 springcloud-provider-dept-8002springcloud-provider-dept-8003

将其application.yml文件的端口分别改为8002、8003

5)

  1. 在 Linux 已经启动了 Nacos 的条件下,访问网页
    http://192.168.159.100:7070/nacos/index.html#/ 或
    http://192.168.159.100:7080/nacos/index.html#/ 或
    http://192.168.159.100:7090/nacos/index.html#/ 其中一个

  2. 启动springcloud-provider-dept-8001

  3. 启动springcloud-provider-dept-8002

  4. 启动springcloud-provider-dept-8003

  5. 启动springcloud-consumer-dept-80

  6. 不断访问http://localhost/consumer/dept/msg

  7. 查看输出结果

方式二(使用配置文件)

1)将 springcloud-consumer-dept-80 项目下的主启动类的@RibbonClients注解注释掉

在这里插入图片描述

2)在该项目下修改application.yml文件

server:
  port: 80

spring:
  application:
    name: springcloud-consumer-dept
  # 配置nacos
  cloud:
    nacos:
      # nacos 服务地址
      server-addr: 192.168.159.100:7070,192.168.159.100:7080,192.168.159.100:7090
      discovery:
        username: nacos   # nacos用户名
        password: nacos
        namespace: public   # 分隔开发环境和测试环境使用

# 调用的服务提供方应用名称
springcloud-provider-dept:
  ribbon:
    # 复制NacosRule类的引用路径,使用的是NacosRule权重策略
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

在这里插入图片描述

3)访问 nacos 注册中心,修改两个提供者的权重

在这里插入图片描述

在这里插入图片描述

如果报错

caused: errCode: 500, errMsg: do metadata operation failed ;caused: com.alibaba.nacos.consistency.exception.ConsistencyException: com.alibaba.nacos.core.distributed.raft.exception.NoLeaderException: The Raft Group [naming_instance_metadata] did not find the Leader node;caused: com.alibaba.nacos.core.distributed.raft.exception.NoLeaderException: The Raft Group [naming_instance_metadata] did not find the Leader node;

解决办法

  • 在 Linux 安装的 nacos 文件夹下删除以下的三个文件即可

在这里插入图片描述

  • 而如果使用 windows 系统则删除这两个文件
    在这里插入图片描述

  • 再次修改,刷新页面
    在这里插入图片描述

修改成功!

4)测试

  1. 启动 springcloud-consumer-dept-80 模块

  2. 多次访问 http://localhost/consumer/dept/msg

查看结果(权重越大,就越频繁调用该服务提供者)

2.2.3 自定义负载均衡器

通过实现 IRule 接口可以自定义负载策略,主要的选择服务逻辑是在 choose 方法中

1)在 springcloud-consumer-dept-80 模块的 ribbon 包下创建一个MyRibbon.class

在这里插入图片描述

  • MyRibbon
public class MyRibbon extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {

        ILoadBalancer loadBalancer = this.getLoadBalancer();

        //获得当前请求服务的实例
        List<Server> reachableServers = loadBalancer.getReachableServers();

        //根据服务的数量,获取范围内的随机数
        int random = ThreadLocalRandom.current().nextInt(reachableServers.size());

        //根据随机数获取服务
        Server server = reachableServers.get(random);

        //可以判断获取该服务是否存活
        //不存活就继续获取

        return server;
    }
}

2)将其配置到Ribbon策略

方式一:注解

  1. RibbonStrategy.class类中修改

在这里插入图片描述

  1. 在主启动类开启注解

在这里插入图片描述

方式二:配置文件

  1. 复制自定义的负载均衡策略引用路径

在这里插入图片描述

  1. application.yml修改引用路径

在这里插入图片描述

3)测试

  1. 重新启动 springcloud-consumer-dept-80 模块

  2. 不断访问 http://localhost/consumer/dept/msg,看结果

如果自己想写一个负载均衡配置策略,可以观摩一下RandomRule.clss类策略

2.2.4 拓展

Ribbon 的饿加载模式

在使用 Spring Cloud 的 Ribbon 或 Feign 来实现服务调用的时候,如果机器或网络环境等原因不是很好的话,有时候会发现这样一个问题:服务消费方调用服务提供方接口的时候,第一次请求经常会超时,而之后的调用就没有问题了

问题的原因

造成第一次服务调用出现失败的原因主要是Ribbon 进行客户端负载均衡的 Client 并不是在服务启动的时候就初始化的,而是在调用的时候才会去创建相应的 Client,所以第一次调用的耗时不仅仅包含发送 HTTP 请求的时间,还包含了创建 RibbonClient 的时间,这样一来如果创建时间速度较慢,同时设置的超时时间又比较短的话,很容易就会出现上面所描述的显现

解决的方法

ribbon:
  eager-load:
    # 开启饥饿加载
    enabled: true
    # 配置服务名为springcloud-provider-dept使用ribbon饥饿加载,多个服务可以使用","分隔
    clients: springcloud-provider-dept

下一篇文章微服务组件Feign&Nacos配置中心使用


版权声明:本文为Wei_Naijia原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。