Spring Cloud Ribbon

一、Ribbon介绍

1. Ribbon是提供客户端的负载均衡的插件。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

2. 负载均衡(LB)方案分类
       目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如Nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个可用的服务器。Ribbon就属于后者,集成于消费方进程,属于客户端的均衡负载,消费方通过它来获取到可用的服务器的地址。

3. Ribbon的主要组件(均为接口类型)
           1. ServerList: 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。
           2. ServerListFilter: 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。
           3. IRule: 负载均衡算法策略,选择一个最终的服务地址作为LB结果。算法策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。

4. Ribbon提供的主要负载均衡策略介绍
          1. 简单轮询负载均衡(RoundRobinRule):以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。
          2. 随机负载均衡 (RandomRule): 随机选择状态为UP的Server
          3. 加权响应时间负载均衡 (WeightedResponseTimeRule):根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。
          4. 区域感知轮询负载均衡(ZoneAvoidanceRule):复合判断server所在区域的性能和server的可用性选择server
          5. 带重试的轮询负载均衡(RetryRule):在失效时间deadline之前不断进行重试(重试时还是RoundRobinRule),超过了deadline还是没取到则返回null
          6. 带过滤的轮询均衡负载(PredicateBasedRule):先通过内部定义的过滤器过滤一部分服务实例,然后再采用线性轮询方法从过滤出来的结果中选取服务

5. Ribbon工作流程
            Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

二、Ribbon单独使用

导入依赖

<dependencies>
    <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-core</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.netflix.ribbon</groupId>
        <artifactId>ribbon-httpclient</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>

sample-client.properties配置文件

# Max number of retries
sample-client.ribbon.MaxAutoRetries=1

# Max number of next servers to retry (excluding the first server)
sample-client.ribbon.MaxAutoRetriesNextServer=1

# Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true

# Interval to refresh the server list from the source
sample-client.ribbon.ServerListRefreshInterval=2000

# Connect timeout used by Apache HttpClient
sample-client.ribbon.ConnectTimeout=3000

# Read timeout used by Apache HttpClient
sample-client.ribbon.ReadTimeout=3000

# Initial list of servers, can be changed via Archaius dynamic property at runtime
sample-client.ribbon.listOfServers=www.sohu.com:80,www.163.com:80,www.sina.com.cn:80

sample-client.ribbon.EnablePrimeConnections=true

RibbonMain代码

public class RibbonMain {
        public static void main( String[] args ) throws Exception {
            ConfigurationManager.loadPropertiesFromResources("sample-client.properties");//使用 Archaius ConfigurationManager 加载属性;
            System.out.println(ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers"));
            RestClient client = (RestClient)ClientFactory.getNamedClient("sample-client");//使用 ClientFactory 创建客户端和负载均衡器;
            /**
             * 使用 builder 构建 http 请求。注意我们只支持 URI 的 "/" 部分的路径,
             * 一旦服务器被负载均衡器选中,会由客户端计算出完整的 URI;
             */
            HttpRequest request = HttpRequest.newBuilder().uri(new URI("/")).build();
            for(int i = 0; i < 4; i ++) {
                HttpResponse response = client.executeWithLoadBalancer(request);
                System.out.println("Status for URI:" + response.getRequestedURI() + " is :" + response.getStatus());
            }
            //调用 API client.executeWithLoadBalancer(),不是 exeucte() API;
            ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer();
            System.out.println(lb.getLoadBalancerStats());
            //动态修正配置中的服务器池;
            ConfigurationManager.getConfigInstance().setProperty("sample-client.ribbon.listOfServers", "ccblog.cn:80,www.linkedin.com:80");
            //等待服务器列表刷新(配置文件中定义的刷新间隔是为 3 秒钟);
            Thread.sleep(3000);
            //打印出负载均衡器记录的服务器统计信息
            for(int i = 0; i < 3; i ++) {
                HttpResponse response = client.executeWithLoadBalancer(request);
                System.out.println("Status for URI:" + response.getRequestedURI() + " is :" + response.getStatus());
            }
            System.out.println(lb.getLoadBalancerStats());
        }
    }

三、Ribbon结合eureka使用

配置依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.1.1.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Brixton.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
</dependencies>

添加application.yml文件

server:
  port: 8081
spring:
  application:
    name: consumer                      #服务名
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka   #注册进eureka
    instance:
      instance-id: consumer_8081       #在注册中心的名字
      prefer-ip-address: true          #访问路径时显示ip地址

修改主启动类,通过@EnableDiscoveryClient注解来添加发现服务能力。创建RestTemplate实例,并通过@LoadBalanced注解开启均衡负载能力。

@SpringBootApplication
@EnableDiscoveryClient
public class RibbonApplication {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(RibbonApplication.class, args);
    }
}

调用Ribbon,创建Controller来消费服务。通过直接RestTemplate来调用服务。如果不想全部使用ribbon,可以不在RestTemplate上添加@LoadBalanced,而添加在Controller指定的方法上。

@RestController
public class ConsumerController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/user/info")
    public String add() {
        return restTemplate.getForEntity("http://xxx", String.class).getBody();
    }
}

转载于:https://my.oschina.net/u/4134962/blog/3074947

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值