SpringCloudAlibaba-Nacos-Ribbon(四)

目录

一、负载均衡器

1.1 集中式负载均衡,服务端负载均衡

1.2 客户端负载均衡器

 二、Ribbon

 三、常见的负载均衡算法

 四、在Nacos中使用Ribbon

父pom文件

ribbon服务

pom文件

配置文件

FeignConfig

MyRuleConfig

AClient

RibbonController

启动类

a服务 

         pom文件

配置文件

AController

启动类

结果:

方式一、多个配置文件启动

方式二、配置文件读取机器的环境变量

手写一个负载均衡算法

MyRule

MyRuleConfig


一、负载均衡器

目前主流的负载方案分为以下两种:服务端负载均衡(nginx)、客户端负载均衡(ribbon);

1.1 集中式负载均衡,服务端负载均衡

在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。

例如Nginx,通过Nginx进行负载均衡,先发送请求,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配。

 1.2 客户端负载均衡器

客户端根据自己的请求情况做负载均衡,Ribbon 就属于客户端自己做负载均衡。

 二、Ribbon

Spring Cloud Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon客户端组件提供一系列的完善的配置,如超时,重试等。通过Load Balancer获取到服务提供的所有机器实例,Ribbon会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。

spring cloud中的ribbon,客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配。

 三、常见的负载均衡算法

如果使用的RestTemplate进行服务调用,那么创建RestTemplate的方法上面加@LoadBalanced注解就会开启Ribbon的负载均衡,Ribbon负载均衡有以下7中规则,默认轮询

  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;

  • 轮询,负载均衡默认实现方式,请求来之后排队处理;

  • 加权轮询,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个服务器的压力;

  • 地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度。 ip --->hash

  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上。 最小活跃数

 四、在Nacos中使用Ribbon

在此示例中使用ribbon服务去调用a服务,由于要使用ribbon并体验其负载均衡等算法。需要把a服务起两个端口并注册到注册中心中(详细见方式一、方式二),这样ribbon去调用时更能直观的看出负载算法调用结果。如下图;下面会在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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chensir</groupId>
    <artifactId>nacos-root</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nacos-root</name>
    <description>nacos-root</description>
    <properties>
        <java.version>1.8</java.version>
        <spring.cloud.version>Hoxton.SR3</spring.cloud.version>
    </properties>
    <packaging>pom</packaging>
    <dependencyManagement>
        <dependencies>


            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
                <optional>true</optional>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.3</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <modules>
        <module>nacos-spring-boot-config</module>
        <module>nacos-spring-cloud-config</module>
        <module>nacos-spring-cloud-discover-a</module>
        <module>nacos-spring-cloud-discover-b</module>
        <module>nacos-spring-cloud-openfeign-c</module>
        <module>nacos-spring-cloud-ribbon</module>
        <module>nacos-spring-cloud-gateway</module>
        <module>spring-cloud-hystrix</module>

    </modules>
</project>

ribbon服务

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>com.chensir</groupId>
        <artifactId>nacos-root</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>nacos-spring-cloud-ribbon</artifactId>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>

        </dependency>

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

     </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

配置文件

server.port=8073

spring.application.name=nacos-app-ribbon

spring.cloud.nacos.discovery.server-addr=localhost:8848


logging.level.com.chensir = debug

FeignConfig

@Configuration
public class FeignConfig
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}

MyRuleConfig

@Configuration
//全局
@RibbonClients(defaultConfiguration = MyRuleConfig.class)
//针对某个服务修改 手写ribbon时可使用
//@RibbonClient(name = "nacos-app-a",configuration = MyRuleConfig.class)
public class MyRuleConfig {

    @Bean
    public IRule rule(){
        // RandomRule() 随机
//        return new RandomRule();

        // RoundRobinRule() 轮询
        return new RoundRobinRule();

        // 自定义
//        return new MyRule();
    }
}

AClient

 RibbonController

 启动类

a服务 

由于需要测试负责均衡算法,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>com.chensir</groupId>
        <artifactId>nacos-root</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>nacos-spring-cloud-discover-a</artifactId>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

 配置文件

以方式一运行,方式二在本机只能起一个,起多个端口还需docker部署;

详细见方式一

AController

@RestController
@Slf4j
public class AController {

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

    @GetMapping("/echo")
    public String test(@RequestParam(value = "name",defaultValue = "这是默认值") String name) {
        String ip = NetUtil.getLocalhost().getHostAddress();

        return StrUtil.format("这是a应用({}:{})输出的结果:{}",ip,port,name);

    }
}

启动类

 结果:

若Ribbon服务中MyRuleConfig使用了轮询算法负载均衡,那么会循环调用 8097和8098端口;

方式一、多个配置文件启动

在配置文件中复制多个,除了端口号port不同外,其他配置信息均相同;

 在Edit Configurations中复制两个启动类,并在Active profiles中输入对应的端口号;然后分别启动两个启动类即可;

 方式二、配置文件读取机器的环境变量

此方式只需要一个配置文件即可;在配置文件中给port起一个名字,如下图:

 然后在Edit Configurations配置(也不用复制两个启动类)步骤如下:

 

 这样就配置好了,然后使用docker部署时可指定端口运行;

以上读取机器环境变量使用docker部署步骤:

1、配置文件server.port= ${APPPORT} 需要这样写;

2、在环境变量中加入对应key值;

3、dockerfile

 4、打包 构建镜像

 5、指定端口运行:

docker run -d --network=host --name a8031 -e APPPORT=8031 a:v1

 这样就运行了端口号为8031的a服务,若再以别的端口号运行 只需要该上方运行命令指定端口号即可(jar包不用修改,仍用同一个jar包)

手写一个负载均衡算法

经过使用轮询、随机等负载均衡算法可看,他们均继承了AbstractLoaBalancerRule抽象类,那么实现自己的负载均衡算法也需要继承与此类。详细可见下方;

MyRule

public class MyRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    //AtomicInteger计数器 是concurrent这个包下的,这个cut包下的全是线程安全的
    private static AtomicInteger count = new AtomicInteger(0);

    Server server = null;

    @SneakyThrows
    @Override
    public Server choose(Object key) {

        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        //获取到服务名
        String name = loadBalancer.getName();

        NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();

        //查询所以实例 name 服务名,true 健康的 可返回服务中ip 端口号
        List<Instance> instances = namingService.selectInstances(name, true);

        //将instances列表转换成数据流,然后取实例中权重最大值
        Instance instanceMax = instances.stream().max(Comparator.comparing(Instance::getWeight)).get();
        //取权重最小值
        Instance instanceMin = instances.stream().min(Comparator.comparing(Instance::getWeight)).get();

        //每次加1
        int i = count.getAndAdd(1);
        int mod = i % 5;
        if (mod == 0) {
            //取模除于5等于0时用权重最小那个服务 计数器为0 5 10 15等时用权重最小那个。
            server = new Server(instanceMin.getIp(), instanceMin.getPort());
        } else {
            //计数器除于5不等于0时 用权重最大那个!
            server = new Server(instanceMax.getIp(), instanceMax.getPort());
        }

        return server;
    }


    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
}

MyRuleConfig

@Configuration
//全局
//@RibbonClients(defaultConfiguration = MyRuleConfig.class)
//针对某个服务修改
@RibbonClient(name = "nacos-app-a",configuration = MyRuleConfig.class)
public class MyRuleConfig {

    @Bean
    public IRule rule(){
        // RandomRule() 随机
//        new RandomRule();
//        return new RandomRule();

        // RoundRobinRule() 轮询
//        new RoundRobinRule();
//        return new RoundRobinRule();

        // 自定义
        return new MyRule();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值