【Spring Cloud 四】Ribbon负载均衡

Ribbon负载均衡

  • 系列文章目录
  • 背景
  • 一、什么是Ribbon
  • 二、为什么要有Ribbon
  • 三、使用Ribbon进行负载均衡
    • 服务提供者A代码
      • pom文件
      • yml配置文件
      • 启动类
      • controller
    • 服务提供者B
      • pom文件
      • yml配置文件
      • 启动类
      • controller
    • 服务消费者
      • pom文件
      • yml文件
      • 启动类
      • controller
    • 运行测试
  • 四、Ribbon的负载均衡策略
    • Ribbon核心接口
    • Ribbon提供的负载均衡算法
    • 配置此消费者嗲用任何服务都用某种负载均衡策略
    • 访问不同的服务使用不同的算法规则
  • 总结

系列文章目录

【Spring Cloud一】微服务基本知识
【Spring Cloud 三】Eureka服务注册与服务发现


背景

目前公司项目使用的注册中心主要是Spring Cloud Alibaba的Nacos做的注册中心和配置中心。并且Nacos使用了Ribbon作为默认的负载均衡器。但是相当于将Ribbon的负载均衡给透明化了,日常开发明面上是看不到Ribbon的。所以出于提升自己的角度,博主对Ribbon进行了理论学习并进行了实践。

一、什么是Ribbon

Spring Cloud Ribbon它是一个基于HTTP和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的。通过Spring Cloud的封装,可以让我们轻松的面向服务的REST模板请求自动转换为客户端负载均衡的服务调用。

Ribbon主要干什么工作:它用在服务消费者需要调用多个相同功能的服务提供者实例时,帮助决定选择哪个服务提供者实例来完成调用。Ribbon可以通过多种负载均衡策略(随机、轮询、加权 、iphash)等方式,将请求分配到不同的服务实例上,以实现负载均衡和高可用。

二、为什么要有Ribbon

总体来说Ribbon是为了解决在微服务架构中服务调用的负载均衡和容错问题而引入的。

Ribbon解决了以下关键问题:

  1. 负载均衡:通过不同势力之间分配负载,Ribbon可以使系统更加稳定和高效,防止某个实例过载而导致服务不可用。
  2. 容错和自动恢复:如果调用的服务实例发生故障或不可用,Ribbon会自动尝试从其他健康的实例中选择一个进行请求处理,这种机制可以提高系统的可靠性和健壮性。
  3. 多种负载均衡策略:可以允许根据实际需求进行定制,更好的满足不同的应用场景。

三、使用Ribbon进行负载均衡

补充:Ribbon作为服务消费者的负载均衡器,有两种使用方式,一种是和RestTemplate相结合,另一种是和OpenFeign相结合。OpenFeign已经默认集成了Ribbon。

例系统中总共有四个服务,一个是Eureka来做服务注册和服务发现,两个服务提供者,一个服务消费者。
Eureka已经在这篇博客进行了实践【Spring Cloud 三】Eureka服务注册与服务发现,本篇博客不在进行一步一步搭建。

服务提供者A代码

pom文件

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wangwei</groupId>
    <artifactId>provider-a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>provider-a</name>
    <description>provider-a</description>
    <properties>
        <java.version>8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <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>

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

</project>

yml配置文件


server:
  port: 8080

spring:
    application:
      name: provider


eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8761/eureka #eureka服务端和客户端的交互地址,不写的话默认是 8761,集群的话地址用,隔开。
    register-with-eureka: true #设置为fasle 不往eureka-server注册
    fetch-registry: true #应用是否拉取服务列表到本地
    registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答


  instance: #实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    hostname: localhost #主机名称或者服务ip
    prefer-ip-address: true #以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔

启动类

@SpringBootApplication
@EnableEurekaClient
public class ProviderAApplication {

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

}

controller

@RestController
public class ProviderController {
    @GetMapping("hello")
    public String hello(){
        return "我是服务提供者A";
    }
}

服务提供者B

pom文件

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wangwei</groupId>
    <artifactId>provider-b</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>provider-b</name>
    <description>provider-b</description>
    <properties>
        <java.version>8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <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>

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

</project>

yml配置文件


server:
  port: 8081

spring:
  application:
    name: provider


eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: true #设置为fasle 不往eureka-server注册
    fetch-registry: true #应用是否拉取服务列表到本地
    registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答


  instance: #实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    hostname: localhost #主机名称或者服务ip
    prefer-ip-address: true #以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔

启动类

@SpringBootApplication
@EnableEurekaClient
public class ProviderBApplication {

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

}

controller

@RestController
public class ProviderController {
    @GetMapping("hello")
    public String hello(){
        return "我是服务提供者B";
    }
}

服务消费者

pom文件

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wangwei</groupId>
    <artifactId>consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer</name>
    <description>consumer</description>
    <properties>
        <java.version>8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.9.RELEASE</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <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>

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

</project>

yml文件



server:
  port: 8082

spring:
  application:
    name: consumer


eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: true #设置为fasle 不往eureka-server注册
    fetch-registry: true #应用是否拉取服务列表到本地
    registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答


  instance: #实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    hostname: localhost #主机名称或者服务ip
    prefer-ip-address: true #以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔



ribbon:
    eager-load:
        enabled: false #ribbon只有自己的话是不能做服务发现,需要借助eureka。如果为false表示懒加载,请求调用的时候开启。如果为true表示程序启动的时候开启
    eureka:
        enabled: true
    http: #我们使用ribbon用的是RestTemplate发请求。底层是java.net.HttpUrlConnection发的请求, 很方便但是不支持连接池
        client:  # 发送请求的工具有很多如:httpClient 它支持连接池,效率更好。如果你想该请求的工具,需要添加对应的依赖。
          enabled: false
    okhttp:   #这个也是请求工具,移动端用的比较多, 轻量级请求
        enabled: false

启动类

@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {

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

    /**
     * 这个RestTemplate
     * 添加上了LoadBalanced 它会被ribbon来操作
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
 }

controller

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("testRibbon")
    public String testRibbon(String serviceName){
        String result = restTemplate.getForObject("http://" + serviceName + "/hello", String.class);
        return result;
    }
}

运行测试

先运行Eureka服务,再运行服务提供者最后运行服务消费者。
调用接口的实现效果:Ribbon默认的负载均衡策略是轮询,及A——B——A——B。
在这里插入图片描述
在这里插入图片描述

四、Ribbon的负载均衡策略

Ribbon核心接口

根据负载均衡策略从所有对应的服务中选取一个服务
在这里插入图片描述

Ribbon提供的负载均衡算法

  1. com.netflix.loadbalancer.RoundRobinRule 轮询
  2. com.netflix.loadbalancer.RandomRule 随机
  3. com.netflix.loadbalancer.WeightedResponseTimeRule 权重轮询
  4. com.netflix.loadbalancer.AvailabilityFilteringRule 会先过滤掉由于多次访问故障处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对于剩余的服务按照轮询的策略进行访问。
  5. com.netflix.loadbalancer.WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越大。刚启动时如果统计信息不足,则使用轮询的策略,等统计信息足够会切换到自身规则。
  6. com.netflix.loadbalancer.BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量小的服务。
  7. com.netflix.loadbalancer.RetryRule 先按照轮询的策略获取服务,如果获取服务失败则在指定的时间内会进行重试,获取可用服务。

配置此消费者嗲用任何服务都用某种负载均衡策略

示例:这里设置的是随机策略 ,这样的话这个消费者调用所有的服务负载均衡策略都是随机策略。
启动类中添加,当然你也可以是新建一个类并添加上@Configuration注解。


    /**
     * @description:往容器中方一个rule对象
     * 你访问任何一个提供者 都是这个算法
     * @author: wangwei
     * @date: 2023/7/31 8:49
     * @param: []
     * @return: com.netflix.loadbalancer.IRule
     **/
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }

}

访问不同的服务使用不同的算法规则

在yml文件中添加:

#访问不同的服务可以使用不同的算法规则
provider: #服务的应用名
  ribfatkunbon:
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #算法的全限定类名

示例:



server:
  port: 8082

spring:
  application:
    name: consumer


eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: true #设置为fasle 不往eureka-server注册
    fetch-registry: true #应用是否拉取服务列表到本地
    registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答


  instance: #实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    hostname: localhost #主机名称或者服务ip
    prefer-ip-address: true #以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔

#访问不同的服务可以使用不同的算法规则
provider: #服务的应用名
  ribfatkunbon:
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #算法的全限定类名

ribbon:
    eager-load:
        enabled: false #ribbon只有自己的话是不能做服务发现,需要借助eureka。如果为false表示懒加载,请求调用的时候开启。如果为true表示程序启动的时候开启
    eureka:
        enabled: true
    http: #我们使用ribbon用的是RestTemplate发请求。底层是java.net.HttpUrlConnection发的请求, 很方便但是不支持连接池
        client:  # 发送请求的工具有很多如:httpClient 它支持连接池,效率更好。如果你想该请求的工具,需要添加对应的依赖。
          enabled: false
    okhttp:   #这个也是请求工具,移动端用的比较多, 轻量级请求
        enabled: false

总结

  1. 通过对Ribbon的理论和实践的学习,让我对Ribbon的理解不再停留知道的层面上,而是切切实实的实践过。
  2. 相对整体和系统的对Ribbon进行了了解和学习,并且和其他微服务组件进行了链接。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Boot】Spring Boot 集成 RocketMQ 实现简单的消息发送和消费

文章目录 前言基本概念消息和主题相关发送普通消息 发送顺序消息RocketMQTemplate的API介绍参考资料&#xff1a; 前言 本文主要有以下内容&#xff1a; 简单消息的发送顺序消息的发送RocketMQTemplate的API介绍 环境搭建&#xff1a; RocketMQ的安装教程&#xff1a;在官网…

js-3:DOM常见的操作有哪些?

1、DOM 文档对象模型&#xff08;DOM&#xff09;是HTML和XML文档的编程接口。 它提供了对文档的结构化的表述&#xff0c;并定义了一种方式&#xff0c;可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构&#xff0c;样式跟内容。 任何HTML和XML文档都可以用DOM表…

解决object转换Date问题

文章目录 解决object转换Date问题源代码List<Object>转换List<Date>问题 解决object转换Date问题 源代码 /*** 解决object与Date转换问题*/Testpublic void t4() {Object o new Date();String formatDate DateFormatUtils.format((Date) o, com.alibaba.excel.u…

uniapp-疫情应急管理系统学生端

1 疫情资讯展示 <template><view class"container"><uni-section title"自定义卡片内容" type"line"><uni-card title"基础卡片" class"card-box" v-for"(item,index) in epidemicNewsList"…

CDN安全面临的问题及防御架构

CDN安全 SQL注入攻击&#xff08;各开发小组针对密码和权限的管理&#xff0c;和云安全部门的漏洞扫描和渗透测试&#xff09; Web Server的安全&#xff08;运营商和云安全部门或者漏洞纰漏第三方定期发布漏洞报告修复&#xff0c;例如&#xff1a;nginx版本号和nginx resol…

MONGODB ---- Austindatabases 历年文章合集

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

react中hooks的理解与使用

一、作用 我们知道react组件有两种写法一种是类组件&#xff0c;另一种是函数组件。而函数组件是无状态组件&#xff0c;如果我们要想改变组件中的状态就无法实现了。为此&#xff0c;在react16.8版本后官方推出hooks&#xff0c;用于函数组件更改状态。 二、常用API 1、use…

websocket+node实现直播(弱鸡版)

心血历程 这部分主要是写在写这些的时候遇到的问题以及换思路的过程&#xff0c;可以之间看正文 在之前我也写过直播功能&#xff0c;并且与websocket相结合实现了直播弹幕。只不过直播是使用的腾讯云的&#xff0c;而不是手写的直播推流拉流&#xff0c;这次又有一个新的项目…

【C# 基础精讲】C# 开发环境搭建(Visual Studio等)

安装C#开发环境是开始学习和使用C#编程的第一步。目前&#xff0c;最常用的C#开发环境是Microsoft Visual Studio&#xff0c;它是一套强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了丰富的工具和功能&#xff0c;使开发C#应用程序变得更加便捷。以下是安装…

Redis 和 Mysql 如何保证数据一致性

项目场景&#xff1a; 一般情况下&#xff0c;Redis 用来实现应用和数据库之间读操作的缓存层&#xff0c;主要目的是减少数据库 IO&#xff0c;还可以提升数据的 IO 性能。 如下图所示&#xff0c;这是它的整体架构。 当应用程序需要去读取某个数据的时候&#xff0c;首先会先…

Linux性能学习(4.4):网络_TCP三次握手内核参数优化

文章目录 1 三次握手2 参数优化2.1 tcp_syn_retries--->SYN重传次数2.2 tcp_synack_retries--->ACK重传次数2.3 tcp_retries2--->发送数据失败重传次数2.4 TCP keepalive--->保活机制2.5 tcp_max_syn_backlog/somaxconn--->半/全连接队列长度2.6 tcp_syncookies…

离散化的两种实现方式【sort或者map】

离散化 定义 把无限空间中有限的个体映射到有限的空间中去&#xff0c;以此提高算法的时空效率。通俗的说&#xff0c;离散化是在不改变数据相对大小的条件下&#xff0c;对数据进行相应的缩小。 适用范围&#xff1a;数组中元素值域很大&#xff0c;但个数不是很多。 比如将…

PHP8的表达式-PHP8知识详解

表达式是 PHP 最重要的基石。在 PHP8中&#xff0c;几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是"任何有值的东西"。 最基本的表达式形式是常量和变量。当键入"$a 5"&#xff0c;即将值"5"分配给变量 $a。&quo…

C++初阶——拷贝构造和运算符重载(const成员)

目录 1. 拷贝构造函数 1.2 拷贝构造函数特征&#xff1a; 2. 默认拷贝构造函数 2.1 未显式定义&#xff0c;编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝&#xff0c;这种拷贝叫做浅拷贝&#xff0c;或者值拷贝 3. 运算符重载 3.1…

Flink CEP(三)pattern动态更新

线上运行的CEP中肯定经常遇到规则变更的情况&#xff0c;如果每次变更时都将任务重启、重新发布是非常不优雅的。尤其在营销或者风控这种对实时性要求比较高的场景&#xff0c;如果规则窗口过长&#xff08;一两个星期&#xff09;&#xff0c;状态过大&#xff0c;就会导致重启…

vue-virtual-scroller的使用,展示巨量数据,长列表优化,虚拟列表

一、原理 计算显示区域的高度&#xff08;或宽度&#xff09; 和显示区域的起始位置&#xff08;scrollTop或scrollLeft&#xff09;根据每个元素的尺寸和总数目&#xff0c;计算出整个列表的高度&#xff08;或宽度&#xff09;显示区域的高度&#xff08;或宽度&#xff09…

基于Orangepi 3 lts 的云台相机

利用orangepi 3 lts 和arduino nano 制作了一个云台相机&#xff0c;可用于室内监控。 硬件&#xff1a; orangepi 3 ,arduino nano ,usb相机&#xff0c;180度舵机两个 WeChat_20230806213004 软件&#xff1a; 整体采用mqtt进行消息的中转。 相机采用python 利用opencv…

LeetCode每日一题Day5——21. 合并两个有序链表

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇&#xff08;C\C版&#xff09; &#x1f353;专栏&#xff1a;算法修炼之筑基篇&#xff08;C\C版&#xff09; &#x1f433;专栏&#xff1a;算法修炼之练气篇&#xff08;Python版&#xff09; …

第三章 图论 No.2单源最短路之虚拟源点,状压最短路与最短路次短路条数

文章目录 1137. 选择最佳线路1131. 拯救大兵瑞恩1134. 最短路计数383. 观光 dp是特殊的最短路&#xff0c;是无环图&#xff08;拓扑图&#xff09;上的最短路问题 1137. 选择最佳线路 1137. 选择最佳线路 - AcWing题库 // 反向建图就行 #include <iostream> #include…

C++ 类型兼容规则

类型兼容规则是指在需要基类对象的任何地方&#xff0c;都可以使用公有派生类的对象来替代。 通过公有继承&#xff0c;派生类得到了基类中除构造函数和析构函数之外的所有成员。这样&#xff0c;公有派生类实际就具备了基类的所有功能&#xff0c;凡是基类能解决的问题&#x…