一起来学Spring Cloud(F版) | 第二篇:Ribbon软负载

文章目录

  1. 1. Ribbon

  2. 2. Try

    1. 2.3.1. 自定义 IRule

    2. 2.1. Eureka Server

    3. 2.2. Product Server

    4. 2.3. Order Server

  3. 3. 总结

  4. 4. 说点什么

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

Ribbon

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

  • 负载均衡

  • 容错

  • 多协议(HTTP,TCP,UDP)支持异步和反应模型

  • 缓存和批处理

交互图

一起来学Spring Cloud(F版) | 第二篇:Ribbon软负载-图片-1交互图

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

<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 相关配置信息

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 注解(默认采用轮训算法)

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:7703product-server:7704 这个时候它是如何知晓注册表中的信息呢?上一章中遗留了一个知识点就是 DiscoveryClient ,通过它就可以获得注册表中客户端的信息了,下列代码块演示了 DiscoveryClient 的简单用法,更多 API 可以自行尝试

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 了,而是写了一串字符,它是怎么做到的?

用通俗的概念来说,它就是编码与解码操作,还记得 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

 

一起来学Spring Cloud(F版) | 第二篇:Ribbon软负载-图片-2效果图

自定义 IRule

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

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 {

}

 

总结

目前很多大佬都写过关于 Spring Cloud 的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-cloud:Finchley.SR1 编写…

说点什么

全文代码:https://github.com/battcn/spring-cloud2-learning/tree/master/chapter2


推荐教程

Java设计模式

创建模式、结构模式、行为模式

Maven教程

Maven是一个项目管理和构建工具

Lucene教程

Lucene是一个开源的基于Java的搜索库

JUnit教程

JUnit是Java编程语言的单元测试框架

Java算法

排序、二叉树、红黑树

Log4j教程

log4j是一种用Java编写的可靠,快速和灵活的日志框架(API)

StringBoot教程

StringBoot实战操作演练

mybatis文档手册

Mybatis基础语法、实例讲解

SpringCloud教程

服务发现、断路器、智能路由

Guava教程

Guava是开源的Java工具库

Elasticsearch教程

一款强大的搜索引擎