SpringCloud入门学习之负载均衡(二)

简介: SpringCloud入门学习之负载均衡(二)

负载均衡策略


Ribbon常见的负载均衡策略


// RoundRobinRule 轮询,默认策略,按序获取provider
// RandomRule 随机
// AvailabilityFilteringRule : 可用性敏感策略,会先过滤掉,跳闸,访问故障的服务~,对剩下的进行轮询~
// RetryRule : 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内进行,重试
//WeightedResponseTimeRule 权重轮询策略,根据每个Provider的响应时间分配一个权重,响应时间越长权重越小,被选中的可能性就越低,初次会使用轮询策略,直到分配好权重
//BestAvailableRule 最少并发数策略,选择正在请求中并发数量小的provider,除非这个provider在熔断中
复制代码


如果想要更换负载均衡策略,在本例中,需要修改服务消费者项目中的 MyConfig 配置文件,内容如下:


@Bean
    public IRule getRule(){
        return new RandomRule();
    }
复制代码


增加对 RandomRule 类的注入,使得 Ribbon 优先选择随机策略。


Ribbon自定义负载均衡策略


在实际生产中,我们可能需要根据公司实际需求设计专门的负载均衡策略,接下来我们来设计相关代码。


新建一个文件夹,结构如下:


7.jpg


模仿随机策略的类进行修改,自定义 MyRandomRule 类


public class MyRandomRule extends AbstractLoadBalancerRule {
    private int count = 0;  //每个服务执行次数
    private int providerNum = 0;    //当前哪个服务被执行
    public MyRandomRule(){
    }
    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            Server server = null;
            while(server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
                List<Server> upList = lb.getReachableServers(); //获得活着的服务
                List<Server> allList = lb.getAllServers(); //获得全部的服务
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }
                //核心部分
//                int index = this.chooseRandomInt(serverCount);
//                server = (Server)upList.get(index);
                //我们定义属于自己的执行策略,目前我们有3个provider,那么决定每个provider执行3次,然后接着执行下一个provider
                if(count<3){
                    server = (Server)upList.get(providerNum);
                    count++;
                }else{
                    count = 0;
                    providerNum++;
                    if(providerNum>=serverCount){
                        providerNum = 0;
                    }
                    server = (Server)upList.get(providerNum);
                }
                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }
                    server = null;
                    Thread.yield();
                }
            }
            return server;
        }
    }
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }
    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}
复制代码


RuleConfig


@Configuration
public class RuleConfig {
    @Bean
    public IRule getRule(){
        return new MyRandomRule();
    }
}
复制代码


最后在入口类上增加注解,启动该策略。


@SpringBootApplication
@EnableEurekaClient
//在微服务启动时去加载我们自定义的负载均衡策略
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = RuleConfig.class)
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}
复制代码


关于上述 myrule 文件夹的位置,原因在于:RuleConfig 不能在主应用程序上下文的@ComponentScan中,否则将由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免包含(例如将其放在一个单独的,不重叠的包中,或者指定要在@ComponentScan)。


Feign


spring cloud feign 基于Netfix Feign实现,整合了spring cloud Ribbonspring cloud Hystrix, 是声明式的 web service 客户端,它让微服务之间的调用变得更简单了,类似 controller 调用 service。SpringCloud 集成了 Ribbon 和 Eureka,可在使用 Feign 时提供负载均衡的 http 客户端。


Feign能做什么


我们在上一节讲述 Ribbon 的使用时,利用它对 RestTemplate 的请求拦截来实现对依赖服务的接口调用,而 RestTemplate 已经实现了对 http 请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以我们需要针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用,模块化的代码重复出现在每一个客户端中,代码量会比较大。


比如我们之前案例中使用到的 springcloud-consumer-dept-80 项目,其中的 DeptConsumerController 类封装了对 http 请求的处理方法,如果我们此时再新建一个服务消费者,同样需要处理 dept 对象的相关逻辑,则需要复制一份 DeptConsumerController 代码。


而  spring cloud feign在此基础上做了进一步封装,由它来帮助我们定义和实现依赖服务接口的定义。在spring cloud feign的实现下,我们只需创建一个接口并调用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了使用spring cloud ribbon时自动封装服务调用客户端的开发量。

实现



首先我们需要在 springcloud-api  项目中增加实现了 Feign 的接口类。


1、导入依赖


<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
</dependencies>
复制代码


2、增加一个 service 接口类


DeptFeignService


package com.msdn.service;
import com.msdn.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@Service
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptFeignService {
    @PostMapping("/dept/add")
    boolean addDept(@RequestBody Dept dept);
    @GetMapping("/dept/get/{id}")
    Dept queryDept(@PathVariable("id") long id);
    @GetMapping("/dept/list")
    List<Dept> queryAll();
}
复制代码


参考 springcloud-consumer-dept-80 项目新建一个名为  springcloud-consumer-dept-80-feign 的 maven 项目,大体内容不变,修改少许内容。


1、导入依赖


<dependencies>
    <dependency>
        <groupId>com.msdn</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
</dependencies>
复制代码


2、DeptConsumerController 文件


@RestController
public class DeptConsumerController {
    @Autowired
    DeptFeignService service;
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept getDept(@PathVariable("id") long id) {
        return service.queryDept(id);
    }
    @RequestMapping("/consumer/dept/list")
    public List<Dept> queryAll() {
        return service.queryAll();
    }
    @RequestMapping(name = "/consumer/dept/add")
    public boolean addDept(Dept dept) {
        return service.addDept(dept);
    }
}
复制代码


3、入口类增加 EnableFeignClients 注解


@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class,args);
    }
} 
复制代码


4、启动3个注册中心,3个服务提供者,然后启动新的服务消费者,访问 http://localhost/consumer/dept/list,多次刷新该页面,发现 consumer 的调用顺序是按序执行的,即轮询策略。



相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
2天前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
203 0
|
2天前
|
缓存 负载均衡 算法
【微服务 SpringCloud】实用篇 · Ribbon负载均衡
【微服务 SpringCloud】实用篇 · Ribbon负载均衡
9 0
|
2天前
|
Java Nacos 微服务
全面学习SpringCloud框架指南
V 哥建议:如果你正在学习SpringCloud,你可以把这篇文章作为学习指南,如果你已经学过了,可以查漏补缺,因为 V 哥这篇文章全面介绍了SpringCloud的方方面面,当然你还需要结合官方文档的细节和源码部分去学习,成功拿下SpringCloud不是问题。加油兄弟!
|
2天前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
|
2天前
|
负载均衡 算法
SpringCloud&Ribbon负载均衡原理与实践
SpringCloud&Ribbon负载均衡原理与实践
20 3
|
2天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
2天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
2天前
|
负载均衡 网络协议 Java
构建高效可扩展的微服务架构:利用Spring Cloud实现服务发现与负载均衡
本文将探讨如何利用Spring Cloud技术实现微服务架构中的服务发现与负载均衡,通过注册中心来管理服务的注册与发现,并通过负载均衡策略实现请求的分发,从而构建高效可扩展的微服务系统。
|
2天前
|
SpringCloudAlibaba 负载均衡 Java
【二】SpringCloud Alibaba之Nacos整合篇(配置负载均衡)
【二】SpringCloud Alibaba之Nacos整合篇(配置负载均衡)
324 0
|
2天前
|
负载均衡 算法 应用服务中间件
面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
字节跳动面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
49 0