【Spring Cloud 四】Ribbon负载均衡

news2024/11/17 17:53:01

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进行了了解和学习,并且和其他微服务组件进行了链接。

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

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

相关文章

Kubespray-offline v2.21.0-1 下载 Kubespray v2.22.1 离线部署 kubernetes v1.25.6

文章目录 1. 目标2. 预备条件3. vcenter 创建虚拟机4. 系统初始化4.1 配置网卡4.2 配置主机名4.3 内核参数 5. 打快照6. 安装 git7. 配置科学8. 安装 docker9. 下载介质9.1 下载安装 docker 介质9.2 下载 kubespray-offline-ansible 介质9.3 下载 kubernetes 介质 10. 搬运介质…

css, resize 拖拉宽度

效果如下&#xff1a; 可直接复制预览查看属性值: 关键样式属性&#xff1a; resize: horizontal; overflow-x: auto; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…

睿讯微带你深度了解汽车交流充电桩

这几年随着新能源汽车的普及&#xff0c;充电桩也越来越多的出现在我们的视野中。新能源纯电汽车就好比一种大号的电子产品&#xff0c;而充电桩则是它不可缺少的子系统&#xff0c;是新能源车主们的必要选择。 汽车充电桩分为直流和交流两种&#xff0c;2022年底全国公共充电桩…

华为防火墙会话表

会话表是设备转发报文的关键表项。所以当出现业务故障时&#xff0c;通常可以通过查看会话表信息&#xff0c;大致定位发生故障的模块或阶段。 当某个业务发生问题&#xff0c;例如流量不通或者断断续续时&#xff0c;通过查看会话表可以得出以下信息&#xff1a; 如果该项业…

Android 死机问题学习笔记

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、死机系统简图二、死机的可能原因三、死机问题需要分析哪些数据四 、Java Backtrace 分析五、常见 Java backtrace 举例六、Native Backtrace七、Ke…

单月涨粉90w,小红书科普视频引发高关注

为洞察小红书平台的内容创作趋势及品牌营销策略&#xff0c;新红推出7月月度榜单&#xff0c;从创作者、品牌、品类多方面入手&#xff0c;解析月榜数据&#xff0c;为从业者提供参考。 爆款笔记涨粉90w 科普视频引发高关注 据7月的『涨粉排行榜』TOP500数据显示&#xff0c;头…

在线LaTeX公式编辑器编辑公式

在线LaTeX公式编辑器编辑公式 在编辑LaTex文档时候&#xff0c;需要输入公式&#xff0c;可以使用在线LaTeX公式编辑器编辑公式&#xff0c;其链接为: 在线LaTeX公式编辑器&#xff0c;https://www.latexlive.com/home 图1 在线LaTeX公式编辑器界面 图2 在线LaTeX公式编辑器…

IDEA用Gradle构建项目时,lombok插件无效的解决办法

Lombok 可用来帮助开发人员消除 Java 的重复代码&#xff0c;尤其是对于简单的 Java 对象&#xff08;POJO&#xff09;&#xff0c;比如说getter/setter/toString等方法的编写。它通过注解实现这一目的。 正确使用姿势 一、安装Lombok插件 菜单栏File -> Settings ->…

C++继承——多继承导致的菱形继承

目录 单继承&#xff1a; 多继承&#xff1a; 菱形继承&#xff1a;菱形继承是多继承的一种特殊情况。 三.菱形继承的两种解决方式区别&#xff1a; 3.1采用作用域解决的菱形继承&#xff1a; 检测器运行图&#xff1a; 反汇编运行图&#xff1a; 3.1菱形虚继承&…

私募证券基金动态-23年7月报

成交量&#xff1a;7月日均8,481.84亿元 2023年7月A股两市日均成交8,481.84亿元&#xff0c;环比下降11.78%、同比下降15.77%。7月整体21个交易日&#xff0c;仅有月初第1个交易日单日成交金额过万亿&#xff0c;且成交量起伏较大&#xff0c;单日成交金额最低仅有6610.11亿元…

深度学习(32)——CycleGAN(1)

深度学习&#xff08;32&#xff09;——CycleGAN&#xff08;1&#xff09; 文章目录 深度学习&#xff08;32&#xff09;——CycleGAN&#xff08;1&#xff09;1. GAN原理2. CycleGAN&#xff08;1&#xff09;原理&#xff08;2&#xff09;核心思想&#xff08;3&#xf…

双环抱式“星环“座舱设计:比亚迪仰望U8内饰曝光,搭载骁龙8+车机

根据8月3日的消息&#xff0c;比亚迪车机先前使用的高通骁龙625芯片在网友中引发了一些批评&#xff0c;不过随着比亚迪将车机升级为骁龙665、骁龙690/695&#xff0c;这个问题得到了改善。 与此同时&#xff0c;大多数主流车企还在继续使用高通8155芯片&#xff08;相当于骁龙…

【Kubernetes】

目录 一、Kubernetes 概述1、K8S 是什么&#xff1f;2、为什么要用 K8S?3、Kubernetes 集群架构与组件 二、核心组件1、Master 组件2、Node 组件3、K8S创建Pod的工作流程&#xff1f;&#xff08;重点&#xff09;4、K8S资源对象&#xff08;重点&#xff09;5、Kubernetes 核…

基于Dockerfile构建镜像应用

目录 一、镜像概述 二、镜像构建方式 三、镜像构建案例 3.1、基于已有容器创建镜像 3.2、基于本地模板创建镜像 3.3、基于Dockerfile构建镜像 3.3.1、Docker 镜像结构 3.3.2、Dockerfile介绍 3.3.3、Dockerfile详解 3.3.4、Dockerfile构建SSHD镜像 3.3.5、Dockerfile…

基于Vue3的数据可视化低代码平台

经过技术调整与迁移&#xff0c;JNPF快速开发平台升级为Vue3.0技术。 Vue3.0作为最新版本的Vue.js框架&#xff0c;拥有更强大的性能和更丰富的功能&#xff0c;为低代码开发平台注入了全新的活力。而JNPF快速开发平台作为其应用的典范之一&#xff0c;利用Vue3.0的优势&#x…

VUE框架、UNIAPP框架:vue2转vue3全面细节总结(1)vue框架:路由模式、路由跳转;uniapp框架:存储数据写法、引入数据写法;

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人_python人工智能视觉&#xff08;opencv&#xff09;从入门到实战,前端,微信小程序-CSDN博客 最新的uniapp毕业设计专栏也放在下方了&#xff1a; https://blog.csdn.net/lbcy…

list删除重复元素几种思路

文章目录 list删除重复元素几种思路hashsetStream流删除所有重复元素 list删除重复元素几种思路 hashset List<String> list2 new ArrayList<>();list2.add("a");list2.add("b");list2.add("a");Set<String> set new HashS…

Unity | 编辑器运行时固定启动场景

1 简介 在多场景游戏的开发过程中&#xff0c;通常需要按照特定的顺序启动场景&#xff0c;以完成一些初始化工作。因此当我们想要在编辑器中运行某个中间场景时&#xff0c;必须先切换到第一个场景。这样的操作不仅繁琐&#xff0c;而且影响开发效率。利用 RuntimeInitialize…

google谷歌gmail邮箱账号注册手机号无法进行验证怎么办?此电话号码无法用于进行验证 或 此电话号码验证次数太多

谷歌gmail邮箱账号注册手机号无法进行验证怎么办? 使用手机号码注册谷歌gmail邮箱账号时会遇到&#xff1a;此电话号码无法用于进行验证 或 此电话号码验证次数太多。造成注册google谷歌gmail邮箱账号受阻&#xff0c;无法正常完成注册。 谷歌Gmail邮箱账号正确的注册方法与教…

MySQL数据库概述(一)

夕阳留恋的不是黄昏&#xff0c;而是朝阳 Mysql 新系列参考 尚硅谷 宋红康老师的教材文档&#xff0c;后续不再进行说明。 一. 为什么要使用数据库 主要是为了进行持久化。 持久化(persistence)&#xff1a;把数据保存到可掉电式存储设备中以供之后使用。大多数情况下&#…