zoukankan      html  css  js  c++  java
  • Ribbon软负载 (F版)

    Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态)。使用Spring Cloud开发人员可以快速地完成实现这些模式的服务和应用程序。它们在任何分布式环境中都能很好地工作

    Ribbon

    Ribbon 是 Netflix 开源的基于 HTTP 和 TCP 的客户端负载均衡器框架,目前也已被 Spring Cloud 团队集成在 spring-cloud-netflix子项目下,主要用于客户端软负载功能,内部已实现了 随机轮训权重减压(选取压力最小的) 等常见的负载算法,同时也提供了 ILoadBalance 与 IRule 两个接口方便我们自己编写适合自己的负载算法

    • 负载均衡
    • 容错
    • 多协议(HTTP,TCP,UDP)支持异步和反应模型
    • 缓存和批处理

    交互图

    交互图交互图

    Try

    要尝试 Spring Cloud Ribbon 首要的就是准备一个服务注册中心,还不太清楚的可以在回头看看上一章 认识Eureka ,这里就不做过多赘述了,准备 eureka-server(回顾上一章)product-serverorder-server 三个项目,后面的两个可以理解为上一章的 eureka-client

    Eureka Server

    详情参考上一章,或从文末的 GITHUB 链接获取对应篇幅的完整代码

    Product Server

    一个普通的 Eureka Client 即可,详情参考上一章,或从文末的 GITHUB 链接获取对应篇幅的完整代码

    Order Server

    一个普通的 Eureka Client

    依赖

    细心的小伙伴会发现,这和一个普通的 Eureka Client 也没啥区别啊,没任何额外依赖的,那是因为在 spring-cloud-starter-netflix-eureka-client 中已经帮我们依赖过 spring-cloud-starter-netflix-ribbon 了。假如使用 consulzookeeperetcd 等容器为服务发现为者时,就必须依赖 spring-cloud-starter-netflix-ribbon 包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <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>
    </dependencies>

    配置文件

    在 src/main/resources 目录下创建一个 bootstrap.yml 的文件,写上 eureka 相关配置信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    server:
    port: 7072
    spring:
    application:
    name: order-server
    eureka:
    instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
    client:
    service-url:
    defaultZone: http://localhost:7071/eureka/

    主函数

    各位小伙伴对 Spring Boot 中的 RestTemplate 应该都不陌生,它是由 Spring Boot 提供而不是 Spring Cloud ,无负载功能,为了方便开发者,Spring Cloud 团队提供了一个 @LoadBalanced 注解(默认采用轮训算法)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package com.battcn;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    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;

    /**
    * @author Levin
    */
    @EnableDiscoveryClient
    @SpringBootApplication
    public class OrderApplication {

    @Configuration
    class MyConfiguration {
    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
    return new RestTemplate();
    }
    }

    public static void main(String[] args) {
    SpringApplication.run(OrderApplication.class, args);
    }
    }

    控制器

    客户端(order-server:7702)从 Eureka Server 同步了 product-server:7703 和 product-server:7704 这个时候它是如何知晓注册表中的信息呢?上一章中遗留了一个知识点就是 DiscoveryClient ,通过它就可以获得注册表中客户端的信息了,下列代码块演示了 DiscoveryClient 的简单用法,更多 API 可以自行尝试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    package com.battcn.controller;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;

    import java.util.List;

    /**
    * @author Levin
    * @since 2018/9/28 0028
    */
    @RestController
    @RequestMapping("/orders")
    public class OrderController {

    private final RestTemplate restTemplate;
    private final DiscoveryClient discoveryClient;

    @Autowired
    public OrderController(RestTemplate restTemplate, DiscoveryClient discoveryClient) {
    this.restTemplate = restTemplate;
    this.discoveryClient = discoveryClient;
    }

    @GetMapping
    public String query() {
    final List<String> services = discoveryClient.getServices();
    for (String service : services) {
    List<ServiceInstance> list = discoveryClient.getInstances(service);
    for (ServiceInstance instance : list) {
    System.out.println(instance.getUri() + "/" + service + " - " + instance.getServiceId());
    }
    }
    return restTemplate.getForObject("http://PRODUCT-SERVER/products", String.class);
    }
    }

    Why

    有的小伙伴对上面的内容会存在一些疑问,为什么没有写 IP:PORT 了,而是写了一串字符,它是怎么做到的?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    用通俗的概念来说,它就是编码与解码操作,还记得 Eureka Server UI Application 吗? 
    编码:根据 spring.application.name 设置 serviceId
    Server ID:PRODUCT-SERVER
    Client A :http://localhost:7073/products
    Client B :http://localhost:7074/products

    解码:通过 serviceId 找到对应的客户端,
    然后根据客户端配置的负载算法从对应集合中
    找出符合当前算法条件的结果,最后拼接出相应的 http 地址即可

    解码前:http://PRODUCT-SERVER/products
    那么将 http://PRODUCT-SERVER 替换成 instance.getUri() 内容是不是就出来了
    http://localhost:7073/products http://localhost:7074/products

    效果图效果图

    自定义 IRule

    假如我们不想使用轮训了,换换口味改成随机算法,又或者想自己写一套适合自己的负载算法,可以用下面这种方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.battcn.config;

    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    /**
    * @author Levin
    * @since 2018/9/28 0028
    */
    @Configuration
    public class RibbonRuleConfiguration {

    @Bean
    public IRule ribbonRule() {
    return new RandomRule();
    }
    }

    @RibbonClient(name = "ribbonRule",configuration = RibbonRuleConfiguration.class)
    public class OrderController {

    }
  • 相关阅读:
    分享一个详情页
    ES6初探,变量的声明
    ES6初探,什么是ES6
    提问回顾
    个人阅读&个人总结
    结对项目-数独程序扩展
    个人作业Week3-案例分析
    个人作业Week2-代码复审
    个人作业1
    【个人项目】数独
  • 原文地址:https://www.cnblogs.com/lywJ/p/10715646.html
Copyright © 2011-2022 走看看