Spring Cloud Alibaba之负载均衡组件 - Ribbon

负载均衡

我们都知道在微服务架构中,微服务之间总是需要互相调用,以此来实现一些组合业务的需求。例如组装订单详情数据,由于订单详情里有用户信息,所以订单服务就得调用用户服务来获取用户信息。要实现远程调用就需要发送网络请求,而每个微服务都可能会存在有多个实例分布在不同的机器上,那么当一个微服务调用另一个微服务的时候就需要将请求均匀的分发到各个实例上,以此避免某些实例负载过高,某些实例又太空闲,所以在这种场景必须要有负载均衡器。

目前实现负载均衡主要的两种方式:

1、服务端负载均衡;例如最经典的使用Nginx做负载均衡器。用户的请求先发送到Nginx,然后再由Nginx通过配置好的负载均衡算法将请求分发到各个实例上,由于需要作为一个服务部署在服务端,所以该种方式称为服务端负载均衡。如图:

2、客户端侧负载均衡;之所以称为客户端侧负载均衡,是因为这种负载均衡方式是由发送请求的客户端来实现的,也是目前微服务架构中用于均衡服务之间调用请求的常用负载均衡方式。因为采用这种方式的话服务之间可以直接进行调用,无需再通过一个专门的负载均衡器,这样能够提高一定的性能以及高可用性。以微服务A调用微服务B举例,简单来说就是微服务A先通过服务发现组件获取微服务B所有实例的调用地址,然后通过本地实现的负载均衡算法选取出其中一个调用地址进行请求。如图:

我们来通过Spring Cloud提供的DiscoveryClient写一个非常简单的客户端侧负载均衡器,借此直观的了解一下该种负载均衡器的工作流程,该示例中采用的负载均衡策略为随机,代码如下:

package com.zj.node.contentcenter.discovery;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * 客户端侧负载均衡器
 *
 * @author 01
 * @date 2019-07-26
 **/
public class LoadBalance {

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 随机获取目标微服务的请求地址
     *
     * @return 请求地址
     */
    public String randomTakeUri(String serviceId) {
        // 获取目标微服务的所有实例的请求地址
        List<String> targetUris = discoveryClient.getInstances(serviceId).stream()
                .map(i -> i.getUri().toString())
                .collect(Collectors.toList());
        // 随机获取列表中的uri
        int i = ThreadLocalRandom.current().nextInt(targetUris.size());

        return targetUris.get(i);
    }
}

使用Ribbon实现负载均衡

什么是Ribbon:

  • Ribbon是Netflix开源的客户端侧负载均衡器
  • Ribbon内置了非常丰富的负载均衡策略算法

Ribbon虽然是个主要用于负载均衡的小组件,但是麻雀虽小五脏俱全,Ribbon还是有许多的接口组件的。如下表:

Ribbon默认内置了八种负载均衡策略,若想自定义负载均衡策略则实现上表中提到的IRule接口或AbstractLoadBalancerRule抽象类即可。内置的负载均衡策略如下:

  • 默认的策略规则为ZoneAvoidanceRule

Ribbon主要有两种使用方式,一是使用Feign,Feign内部已经整合了Ribbon,因此如果只是普通使用的话都感知不到Ribbon的存在;二是配合RestTemplate使用,这种方式则需要添加Ribbon依赖和@LoadBalanced注解。

这里主要演示一下第二种使用方式,由于项目中添加的Nacos依赖已包含了Ribbon所以不需要另外添加依赖,首先定义一个RestTemplate,代码如下:

package com.zj.node.contentcenter.configuration;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * bean 配置类
 *
 * @author 01
 * @date 2019-07-25
 **/
@Configuration
public class BeanConfig {

    @Bean
    @LoadBalanced  // 加上这个注解表示使用Ribbon
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

然后使用RestTemplate调用其他服务的时候,只需要写服务名即可,不需要再写ip地址和端口号。如下示例:

public ShareDTO findById(Integer id) {
    // 获取分享详情
    Share share = shareMapper.selectByPrimaryKey(id);
    // 发布人id
    Integer userId = share.getUserId();
    // 调用用户中心获取用户信息
    UserDTO userDTO = restTemplate.getForObject(
            "http://user-center/users/{id}",  // 只需要写服务名
            UserDTO.class, userId
    );

    ShareDTO shareDTO = objectConvert.toShareDTO(share);
    shareDTO.setWxNickname(userDTO.getWxNickname());

    return shareDTO;
}

如果不太清楚RestTemplate的使用,可以参考如下文章:


自定义Ribbon负载均衡配置

在实际开发中,我们可能会遇到默认的负载均衡策略无法满足需求,从而需要更换其他的负载均衡策略。关于Ribbon负载均衡的配置方式主要有两种,在代码中配置或在配置文件中配置。

Ribbon支持细粒度的配置,例如我希望微服务A在调用微服务B的时候采用随机的负载均衡策略,而在调用微服务C的时候采用默认策略,下面我们就来实现一下这种细粒度的配置。

1、首先是通过代码进行配置,编写一个配置类用于实例化指定的负载均衡策略对象:

@Configuration
public class RibbonConfig {

    @Bean
    public IRule ribbonRule(){
        // 随机的负载均衡策略对象
        return new RandomRule();
    }
}

然后再编写一个用于配置Ribbon客户端的配置类,该配置类的目的是指定在调用user-center时采用RibbonConfig里配置的负载均衡策略,这样就可以达到细粒度配置的效果:

@Configuration
// 该注解用于自定义Ribbon客户端配置,这里声明为属于user-center的配置
@RibbonClient(name = "user-center", configuration = RibbonConfig.class)
public class UserCenterRibbonConfig {
}

需要注意的是RibbonConfig应该定义在主启动类之外,避免被Spring扫描到,不然会产生父子上下文扫描重叠的问题,从而导致各种奇葩的问题。而在Ribbon这里就会导致该配置类被所有的Ribbon客户端共享,即不管调用user-center还是其他微服务都会采用该配置类里定义的负载均衡策略,这样就会变成了一个全局配置了,违背了我们需要细粒度配置的目的。所以需要将其定义在主启动类之外:

关于这个问题可以参考官方文档的描述:

https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_customizing_the_ribbon_client

2、使用配置文件进行配置就更简单了,不需要写代码还不会有父子上下文扫描重叠的坑,只需在配置文件中增加如下一段配置就可以实现以上使用代码配置等价的效果:

user-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

两种配置方式对比:

最佳实践总结:

  • 尽量使用配置文件配置,配置文件满足不了需求的情况下再考虑使用代码配置
  • 在同一个微服务内尽量保持单一性,例如统一使用配置文件配置,尽量不要两种方式混用,以免增加定位问题的复杂度


以上介绍的是细粒度地针对某个特定Ribbon客户端的配置,下面我们再演示一下如何实现全局配置。很简单,只需要把注解改为@RibbonClients即可,代码如下:

@Configuration
// 该注解用于全局配置
@RibbonClients(defaultConfiguration = RibbonConfig.class)
public class GlobalRibbonConfig {
}

Ribbon默认是懒加载的,所以在第一次发生请求的时候会显得比较慢,我们可以通过在配置文件中添加如下配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true
    # 为哪些客户端开启饥饿加载,多个客户端使用逗号分隔(非必须)
    clients: user-center

支持Nacos权重

以上小节基本介绍完了负载均衡及Ribbon的基础使用,接下来的内容需要配合Nacos,若没有了解过Nacos的话可以参考以下文章:

在Nacos Server的控制台页面可以编辑每个微服务实例的权重,服务列表 -> 详情 -> 编辑;默认权重都为1,权重值越大就越优先被调用:

权重在很多场景下非常有用,例如一个微服务有很多的实例,它们被部署在不同配置的机器上,这时候就可以将配置较差的机器上所部署的实例权重设置得比较低,而部署在配置较好的机器上的实例权重设置得高一些,这样就可以将较大一部分的请求都分发到性能较高的机器上。

但是Ribbon内置的负载均衡策略都不支持Nacos的权重,所以我们就需要自定义实现一个支持Nacos权重配置的负载均衡策略。好在Nacos Client已经内置了负载均衡的能力,所以实现起来也比较简单,代码如下:

package com.zj.node.contentcenter.configuration;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;

/**
 * 支持Nacos权重配置的负载均衡策略
 *
 * @author 01
 * @date 2019-07-27
 **/
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {

    @Autowired
    private  NacosDiscoveryProperties discoveryProperties;

    /**
     * 读取配置文件,并初始化NacosWeightedRule
     *
     * @param iClientConfig iClientConfig
     */
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        // do nothing
    }

    @Override
    public Server choose(Object key) {
        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        log.debug("lb = {}", loadBalancer);

        // 需要请求的微服务名称
        String name = loadBalancer.getName();
        // 获取服务发现的相关API
        NamingService namingService = discoveryProperties.namingServiceInstance();

        try {
            // 调用该方法时nacos client会自动通过基于权重的负载均衡算法选取一个实例
            Instance instance = namingService.selectOneHealthyInstance(name);
            log.info("选择的实例是:instance = {}", instance);

            return new NacosServer(instance);
        } catch (NacosException e) {
            return null;
        }
    }
}

然后在配置文件中配置一下就可以使用该负载均衡策略了:

user-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.zj.node.contentcenter.configuration.NacosWeightedRule

思考:既然Nacos Client已经有负载均衡的能力,Spring Cloud Alibaba为什么还要去整合Ribbon呢?

个人认为,这主要是为了符合Spring Cloud标准。Spring Cloud Commons有个子项目 spring-cloud-loadbalancer ,该项目制定了标准,用来适配各种客户端负载均衡器(虽然目前实现只有Ribbon,但Hoxton就会有替代的实现了)。

Spring Cloud Alibaba遵循了这一标准,所以整合了Ribbon,而没有去使用Nacos Client提供的负载均衡能力。


同一集群优先调用

Spring Cloud Alibaba之服务发现组件 - Nacos一文中已经介绍过集群的概念以及作用,这里就不再赘述,加上上一小节中已经介绍过如何自定义负载均衡策略了,所以这里不再啰嗦而是直接上代码,实现代码如下:

package com.zj.node.contentcenter.configuration;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 实现同一集群优先调用并基于随机权重的负载均衡策略
 *
 * @author 01
 * @date 2019-07-27
 **/
@Slf4j
public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        // do nothing
    }

    @Override
    public Server choose(Object key) {
        // 获取配置文件中所配置的集群名称
        String clusterName = discoveryProperties.getClusterName();
        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        // 获取需要请求的微服务名称
        String serviceId = loadBalancer.getName();
        // 获取服务发现的相关API
        NamingService namingService = discoveryProperties.namingServiceInstance();

        try {
            // 获取该微服务的所有健康实例
            List<Instance> instances = namingService.selectInstances(serviceId, true);
            // 过滤出相同集群下的所有实例
            List<Instance> sameClusterInstances = instances.stream()
                    .filter(i -> Objects.equals(i.getClusterName(), clusterName))
                    .collect(Collectors.toList());

            // 相同集群下没有实例则需要使用其他集群下的实例
            List<Instance> instancesToBeChosen;
            if (CollectionUtils.isEmpty(sameClusterInstances)) {
                instancesToBeChosen = instances;
                log.warn("发生跨集群调用,name = {}, clusterName = {}, instances = {}",
                        serviceId, clusterName, instances);
            } else {
                instancesToBeChosen = sameClusterInstances;
            }

            // 基于随机权重的负载均衡算法,从实例列表中选取一个实例
            Instance instance = ExtendBalancer.getHost(instancesToBeChosen);
            log.info("选择的实例是:port = {}, instance = {}", instance.getPort(), instance);

            return new NacosServer(instance);
        } catch (NacosException e) {
            log.error("获取实例发生异常", e);
            return null;
        }
    }
}

class ExtendBalancer extends Balancer {

    /**
     * 由于Balancer类里的getHostByRandomWeight方法是protected的,
     * 所以通过这种继承的方式来实现调用,该方法基于随机权重的负载均衡算法,选取一个实例
     */
    static Instance getHost(List<Instance> hosts) {
        return getHostByRandomWeight(hosts);
    }
}

同样的,想要使用该负载均衡策略的话,在配置文件中配置一下即可:

user-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.zj.node.contentcenter.configuration.NacosSameClusterWeightedRule

基于元数据的版本控制

在以上两个小节我们实现了基于Nacos权重的负载均衡策略及同一集群下优先调用的负载均衡策略,但在实际项目中,可能会面临多版本共存的问题,即一个微服务拥有不同版本的实例,并且这些不同版本的实例之间可能是互不兼容的。例如微服务A的v1版本实例无法调用微服务B的v2版本实例,只能够调用微服务B的v1版本实例。

而Nacos中的元数据就比较适合解决这种版本控制的问题,至于元数据的概念及配置方式已经在Spring Cloud Alibaba之服务发现组件 - Nacos一文中介绍过,这里主要介绍一下如何通过Ribbon去实现基于元数据的版本控制。

举个例子,线上有两个微服务,一个作为服务提供者一个作为服务消费者,它们都有不同版本的实例,如下:

  • 服务提供者有两个版本:v1、v2
  • 服务消费者也有两个版本:v1、v2

v1和v2是不兼容的。服务消费者v1只能调用服务提供者v1;消费者v2只能调用提供者v2。如何实现呢?下面我们来围绕该场景,实现微服务之间的版本控制。

综上,我们需要实现的主要有两点:

  • 优先选择同集群下,符合metadata的实例
  • 如果同集群下没有符合metadata的实例,就选择其他集群下符合metadata的实例

首先我们得在配置文件中配置元数据,元数据就是一堆的描述信息,以k - v形式进行配置,如下:

spring:
  cloud:
    nacos:
      discovery:
        # 指定nacos server的地址
        server-addr: 127.0.0.1:8848
        # 配置元数据
        metadata:
          # 当前实例版本
          version: v1
          # 允许调用的提供者实例的版本
          target-version: v1

然后就可以写代码了,和之前一样,也是通过负载均衡策略实现,具体代码如下:

package com.zj.node.contentcenter.configuration;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.utils.StringUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 基于元数据的版本控制负载均衡策略
 *
 * @author 01
 * @date 2019-07-27
 **/
@Slf4j
public class NacosFinalRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    private static final String TARGET_VERSION = "target-version";
    private static final String VERSION = "version";

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        // do nothing
    }

    @Override
    public Server choose(Object key) {
        // 获取配置文件中所配置的集群名称
        String clusterName = discoveryProperties.getClusterName();
        // 获取配置文件中所配置的元数据
        String targetVersion = discoveryProperties.getMetadata().get(TARGET_VERSION);

        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
        // 需要请求的微服务名称
        String serviceId = loadBalancer.getName();
        // 获取该微服务的所有健康实例
        List<Instance> instances = getInstances(serviceId);

        List<Instance> metadataMatchInstances = instances;
        // 如果配置了版本映射,那么代表只调用元数据匹配的实例
        if (StringUtils.isNotBlank(targetVersion)) {
            // 过滤与版本元数据相匹配的实例,以实现版本控制
            metadataMatchInstances = filter(instances,
                    i -> Objects.equals(targetVersion, i.getMetadata().get(VERSION)));

            if (CollectionUtils.isEmpty(metadataMatchInstances)) {
                log.warn("未找到元数据匹配的目标实例!请检查配置。targetVersion = {}, instance = {}",
                        targetVersion, instances);
                return null;
            }
        }

        List<Instance> clusterMetadataMatchInstances = metadataMatchInstances;
        // 如果配置了集群名称,需筛选同集群下元数据匹配的实例
        if (StringUtils.isNotBlank(clusterName)) {
            // 过滤出相同集群下的所有实例
            clusterMetadataMatchInstances = filter(metadataMatchInstances,
                    i -> Objects.equals(clusterName, i.getClusterName()));

            if (CollectionUtils.isEmpty(clusterMetadataMatchInstances)) {
                clusterMetadataMatchInstances = metadataMatchInstances;
                log.warn("发生跨集群调用。clusterName = {}, targetVersion = {}, clusterMetadataMatchInstances = {}", clusterName, targetVersion, clusterMetadataMatchInstances);
            }
        }

        // 基于随机权重的负载均衡算法,选取其中一个实例
        Instance instance = ExtendBalancer.getHost(clusterMetadataMatchInstances);

        return new NacosServer(instance);
    }

    /**
     * 通过过滤规则过滤实例列表
     */
    private List<Instance> filter(List<Instance> instances, Predicate<Instance> predicate) {
        return instances.stream()
                .filter(predicate)
                .collect(Collectors.toList());
    }

    private List<Instance> getInstances(String serviceId) {
        // 获取服务发现的相关API
        NamingService namingService = discoveryProperties.namingServiceInstance();
        try {
            // 获取该微服务的所有健康实例
            return namingService.selectInstances(serviceId, true);
        } catch (NacosException e) {
            log.error("发生异常", e);
            return Collections.emptyList();
        }
    }
}

class ExtendBalancer extends Balancer {
    /**
     * 由于Balancer类里的getHostByRandomWeight方法是protected的,
     * 所以通过这种继承的方式来实现调用,该方法基于随机权重的负载均衡算法,选取一个实例
     */
    static Instance getHost(List<Instance> hosts) {
        return getHostByRandomWeight(hosts);
    }
}

原文地址:https://blog.51cto.com/zero01/2424180

时间: 2024-10-01 02:52:41

Spring Cloud Alibaba之负载均衡组件 - Ribbon的相关文章

API网关spring cloud gateway和负载均衡框架ribbon实战

通常我们如果有一个服务,会部署到多台服务器上,这些微服务如果都暴露给客户,是非常难以管理的,我们系统需要有一个唯一的出口,API网关是一个服务,是系统的唯一出口.API网关封装了系统内部的微服务,为客户端提供一个定制的API.客户端只需要调用网关接口,就可以调用到实际的微服务,实际的服务对客户不可见,并且容易扩展服务. API网关可以结合ribbon完成负载均衡的功能,可以自动检查微服务的状况,及时剔除或者加入某个微服务到可用服务列表.此外网关可以完成权限检查.限流.统计等功能.下面我们将一一完

Spring Cloud Alibaba之服务发现组件 - Nacos

服务发现 为了实现多个微服务之间的调用,我们除了需要Feign这种调用组件外还得依赖服务发现组件.主要的原因是每个微服务所在的机器ip并非总是固定的,并且每个微服务都可能部署多个实例在不同的机器上,所以我们不能把依赖的微服务ip地址写在代码或配置文件里,我们需要有个组件去动态的管理,这就是为什么微服务架构里服务发现功能是必须的. 那么服务发现组件是怎么实现服务发现的呢?我们以大家比较熟悉的MySQL来做类比,通过MySQL简单说明一下服务发现机制的实现.如下图: 简单说明一下什么是服务提供者与服

Spring Cloud Alibaba之服务容错组件 - Sentinel [规则持久化篇]

规则持久化 - 拉模式 在Sentinel控制台对某个微服务的接口资源配置了流控.降级等规则后,若重启了该微服务,那么配置的相关规则就会丢失,因为Sentinel默认将规则存放在内存中.每次重启微服务都得重新配置规则显然是不合理的,所以我们需要将配置好的规则进行持久化存储,而Sentinel提供了两种规则持久化模式: 拉模式(pull) 推模式(push) 本小节先介绍一下拉模式(pull),该模式的架构图如下: Tips:规则在代码中实际上是一个对象,所以通常是转换成json字符串后再存储至本

客户端负载均衡Ribbon之一:Spring Cloud Netflix负载均衡组件Ribbon介绍

Netflix:['netfli?ks] ribbon:英[?r?b?n]美[?r?b?n]n. 带; 绶带; (打印机的) 色带; 带状物;v. 把…撕成条带; 用缎带装饰; 形成带状;     LB方案分类 目前主流的LB方案可分成两类: 一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方: 另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址

Spring Cloud Netflix负载均衡组件Ribbon介绍

Netflix:['netfli?ks] ribbon:英[?r?b?n]美[?r?b?n]n. 带; 绶带; (打印机的) 色带; 带状物;v. 把…撕成条带; 用缎带装饰; 形成带状;     LB方案分类 目前主流的LB方案可分成两类: 一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方: 另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址

spring cloud 之 客户端负载均衡 Ribbon

一.负载均衡 负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性.其意思就是分摊到多个操作单元上进行执行,例如Web服务器.FTP服务器.企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务. 1.服务端负载均衡:客户端请求到负载均衡服务器,负载均衡服务器根据自身的算法将该请求转给某台真正提供业务的服务器,该服务器将响应数据给负载均衡服务器,负载均衡服务器最

Spring Cloud之Zuul负载均衡

Zuul网关默认是实现负载均衡的,不需要任何配置.默认开启ribbon效果的 可以启启动两个服务端口,访问下. 原文地址:https://www.cnblogs.com/toov5/p/9972466.html

Spring Cloud Alibaba 新一代微服务解决方案

本篇是「跟我学 Spring Cloud Alibaba」系列的第一篇, 每期文章会在公众号「架构进化论」进行首发更新,欢迎关注. 1.Spring Cloud Alibaba 是什么 Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案,是阿里巴巴开源中间件与 Spring Cloud 体系的融合. 马老师左手双十一,右手阿里开源组件,不仅占据了程序员的购物车,还要攻占大家的开发工具. 先说说 Spring Cloud 提起微服务,不得不提 Spring Clou

Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)

Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移.服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了.功能类似于dubbo的注册中心,比如Zookeeper. Eureka包含两个组件: