前面一篇介绍了LoadBalancerClient来实现负载均衡, 这里介绍Spring cloud ribbon

1、ribbon

  Spring Cloud Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的。它不像服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个微服务的基础设施中理解Ribbon对于我们使用Spring Cloud来讲非常的重要,因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。

  它内部提供了一个叫做ILoadBalance的接口代表负载均衡器的操作,比如有添加服务器操作、选择服务器操作、获取所有的服务器列表、获取可用的服务器列表等等。

2、这里我们复制上一章consumer工程,修改pom.xml,增加ribbon依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5.  
  6. <groupId>com.example</groupId>
  7. <artifactId>eurekaRibbon</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. <packaging>jar</packaging>
  10.  
  11. <name>eurekaRibbon</name>
  12. <description>Demo project for Spring Boot</description>
  13.  
  14. <parent>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-parent</artifactId>
  17. <version>1.4.0.RELEASE</version>
  18. <relativePath /> <!-- lookup parent from repository -->
  19. </parent>
  20.  
  21. <properties>
  22. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  23. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  24. <java.version>1.8</java.version>
  25. </properties>
  26.  
  27. <dependencies>
  28. <dependency>
  29. <groupId>org.springframework.cloud</groupId>
  30. <artifactId>spring-cloud-starter-eureka</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework.cloud</groupId>
  34. <artifactId>spring-cloud-starter-ribbon</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-web</artifactId>
  39. </dependency>
  40.  
  41. <dependency>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-starter-test</artifactId>
  44. <scope>test</scope>
  45. </dependency>
  46. </dependencies>
  47.  
  48. <dependencyManagement>
  49. <dependencies>
  50. <dependency>
  51. <groupId>org.springframework.cloud</groupId>
  52. <artifactId>spring-cloud-dependencies</artifactId>
  53. <version>Dalston.SR3</version>
  54. <type>pom</type>
  55. <scope>import</scope>
  56. </dependency>
  57. </dependencies>
  58. </dependencyManagement>
  59.  
  60. <build>
  61. <plugins>
  62. <plugin>
  63. <groupId>org.springframework.boot</groupId>
  64. <artifactId>spring-boot-maven-plugin</artifactId>
  65. </plugin>
  66. </plugins>
  67. </build>
  68.  
  69. </project>

3、修改主类,为RestTemplate增加@LoadBalanced注解

  1. package com.example.demo;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  6. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.web.client.RestTemplate;
  9.  
  10. @EnableDiscoveryClient
  11. @SpringBootApplication
  12. public class EurekaRibbonApplication {
  13.  
  14. @Bean
  15. @LoadBalanced
  16. public RestTemplate restTemplate() {
  17. return new RestTemplate();
  18. }
  19.  
  20. public static void main(String[] args) {
  21. SpringApplication.run(EurekaRibbonApplication.class, args);
  22. }
  23. }

4、接口

  1. package com.example.demo.controller;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import org.springframework.web.client.RestTemplate;
  7.  
  8. @RestController
  9. public class ClientRibbonController {
  10.  
  11. @Autowired
  12. RestTemplate restTemplate;
  13.  
  14. @GetMapping("/consumer")
  15. public String all() {
  16. // 发起REST请求
  17. return restTemplate.getForObject("http://eurekaClient/all", String.class);
  18. }
  19.  
  20. }

  这里请求的host位置并没有使用一个具体的IP地址和端口的形式,而是采用了服务名的方式组成。Spring Cloud Ribbon有一个拦截器,它能够在这里进行实际调用的时候,自动的去选取服务实例,并将实际要请求的IP地址和端口替换这里的服务名,从而完成服务接口的调用,进而实现自动化:

  然而Ribbon要实现负载均衡自动化配置需要满足如下两个条件:

   1、ConditionalOnClass(RestTemplate.class):RestTemplate类必须存在于当前工程的环境中

   2、ConditionalOnBean(LoadBalancerClient.class):使用@LoadBalanced注解用来给RestTemplate做标记,以使用负载均衡的客户端(LoadBalancerClient)来配置RestTemplate。

  在自动化配置中主要做三件事:

  • 创建一个LoadBalancerInterceptor的Bean,用于实现对客户端发起请求时进行拦截,以实现客户端负载均衡。
  • 创建一个RestTemplateCustomizer的Bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器。
  • 维护了一个被@LoadBalanced注解修饰的RestTemplate对象列表,并在这里进行初始化,通过调用RestTemplateCustomizer的实例来给需要客户端负载均衡的RestTemplate增加LoadBalancerInterceptor拦截器。

1、条件二LoadBalancerClient

  1. /**
  2. * Represents a client side load balancer
  3. * @author Spencer Gibb
  4. */
  5. public interface LoadBalancerClient extends ServiceInstanceChooser {
  6.  
  7. /**
  8. * execute request using a ServiceInstance from the LoadBalancer for the specified
  9. * service
  10. * @param serviceId the service id to look up the LoadBalancer
  11. * @param request allows implementations to execute pre and post actions such as
  12. * incrementing metrics
  13. * @return the result of the LoadBalancerRequest callback on the selected
  14. * ServiceInstance
  15. */
  16. <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
  17.  
  18. /**
  19. * execute request using a ServiceInstance from the LoadBalancer for the specified
  20. * service
  21. * @param serviceId the service id to look up the LoadBalancer
  22. * @param serviceInstance the service to execute the request to
  23. * @param request allows implementations to execute pre and post actions such as
  24. * incrementing metrics
  25. * @return the result of the LoadBalancerRequest callback on the selected
  26. * ServiceInstance
  27. */
  28. <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
  29.  
  30. /**
  31. * Create a proper URI with a real host and port for systems to utilize.
  32. * Some systems use a URI with the logical serivce name as the host,
  33. * such as http://myservice/path/to/service. This will replace the
  34. * service name with the host:port from the ServiceInstance.
  35. * @param instance
  36. * @param original a URI with the host as a logical service name
  37. * @return a reconstructed URI
  38. */
  39. URI reconstructURI(ServiceInstance instance, URI original);
  40. }

  我们可以知道 choose()方法根据传入的serviceId服务Id,从负载均衡器选择一个一个对应的服务实例。execute()方法根据serviceId服务ID和请求request来执行请求内容。reconstructURI()方法构建出一个合适的Host:Port的URI。而 RibbonLoadBalancerClient就是LoadBalancerClient的具体实现

2、Ribbon自动化配置:LoadBalancerAutoConfiguration

  1. /**
  2. * Auto configuration for Ribbon (client side load balancing).
  3. *
  4. * @author Spencer Gibb
  5. * @author Dave Syer
  6. * @author Will Tran
  7. */
  8. @Configuration
  9. @ConditionalOnClass(RestTemplate.class) //条件 : RestTemplate必须在工程的类路径下
  10. @ConditionalOnBean(LoadBalancerClient.class) //条件: Spring 容器中必须包含LoadBalancerClient的实现,即RibbonLoadBalancerClient
  11. @EnableConfigurationProperties(LoadBalancerRetryProperties.class) //启动重试功能,可以spring.cloud.loadbalancer.retry=false,取消重试,默认参数为true
  12. public class LoadBalancerAutoConfiguration {
  13.  
  14. @LoadBalanced
  15. @Autowired(required = false)
  16. private List<RestTemplate> restTemplates = Collections.emptyList(); //维护一个RestTemplate列表,通过LoadBalanced来注解。
  17.  
  18. @Bean
  19. public SmartInitializingSingleton loadBalancedRestTemplateInitializer( //加载初始话自定义的restTeplate,实质是初始化InterceptingHttpAccessor具体调用
  20. final List<RestTemplateCustomizer> customizers) {
  21. return new SmartInitializingSingleton() {
  22. @Override
  23. public void afterSingletonsInstantiated() {
  24. for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
  25. for (RestTemplateCustomizer customizer : customizers) {
  26. customizer.customize(restTemplate);
  27. }
  28. }
  29. }
  30. };
  31. }
  32.  
  33. @Autowired(required = false)
  34. private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
  35.  
  36. @Bean
  37. @ConditionalOnMissingBean
  38. public LoadBalancerRequestFactory loadBalancerRequestFactory(
  39. LoadBalancerClient loadBalancerClient) {
  40. return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
  41. }
  42.  
  43. @Configuration
  44. @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
  45. static class LoadBalancerInterceptorConfig {
  46. @Bean
  47. public LoadBalancerInterceptor ribbonInterceptor(
  48. LoadBalancerClient loadBalancerClient,
  49. LoadBalancerRequestFactory requestFactory) {
  50. return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
  51. }
  52.  
  53. @Bean
  54. @ConditionalOnMissingBean
  55. public RestTemplateCustomizer restTemplateCustomizer(
  56. final LoadBalancerInterceptor loadBalancerInterceptor) {
  57. return new RestTemplateCustomizer() {
  58. @Override
  59. public void customize(RestTemplate restTemplate) {
  60. List<ClientHttpRequestInterceptor> list = new ArrayList<>(
  61. restTemplate.getInterceptors());
  62. list.add(loadBalancerInterceptor);
  63. restTemplate.setInterceptors(list);
  64. }
  65. };
  66. }
  67. }
  68.  
  69. @Configuration
  70. @ConditionalOnClass(RetryTemplate.class)
  71. static class RetryAutoConfiguration {
  72. @Bean
  73. public RetryTemplate retryTemplate() {
  74. RetryTemplate template = new RetryTemplate();
  75. template.setThrowLastExceptionOnExhausted(true);
  76. return template;
  77. }
  78.  
  79. @Bean
  80. @ConditionalOnMissingBean
  81. public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {
  82. return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();
  83. }
  84.  
  85. @Bean
  86. public RetryLoadBalancerInterceptor ribbonInterceptor(
  87. LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
  88. LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
  89. LoadBalancerRequestFactory requestFactory) {
  90. return new RetryLoadBalancerInterceptor(loadBalancerClient, retryTemplate(), properties,
  91. lbRetryPolicyFactory, requestFactory);
  92. }
  93.  
  94. @Bean
  95. @ConditionalOnMissingBean
  96. public RestTemplateCustomizer restTemplateCustomizer( //自定义RestTemplate ,实质是初始化InterceptingHttpAccessor
  97. final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
  98. return new RestTemplateCustomizer() {
  99. @Override
  100. public void customize(RestTemplate restTemplate) {
  101. List<ClientHttpRequestInterceptor> list = new ArrayList<>(
  102. restTemplate.getInterceptors());
  103. list.add(loadBalancerInterceptor);
  104. restTemplate.setInterceptors(list);
  105. }
  106. };
  107. }
  108. }
  109. }

具体可以看下https://www.cnblogs.com/duanxz/p/7504947.html,源码介绍

Spring Cloud 入门Eureka -Consumer服务消费(Ribbon)(二)的更多相关文章

  1. Spring Cloud 入门Eureka -Consumer服务消费(声明式Feign)(三)

    Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口并用注解来配置它既可完成对Web服务接 ...

  2. Spring Cloud 入门Eureka -Consumer服务消费(一)

    这里介绍:LoadBalancerClient接口,它是一个负载均衡客户端的抽象定义,下面我们就看看如何使用Spring Cloud提供的负载均衡器客户端接口来实现服务的消费. 引用之前的文章中构建的 ...

  3. Spring Cloud 入门教程(一): 服务注册

    1.  什么是Spring Cloud? Spring提供了一系列工具,可以帮助开发人员迅速搭建分布式系统中的公共组件(比如:配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁 ...

  4. spring cloud深入学习(三)-----服务消费

    在上一篇博文中简单实现了eureka-server以及eureka-provider,后面会实现eureka-cosumer,现在针对eureka做进一步的详解. 微服务整体架构 文字再美也没有图片直 ...

  5. Spring Cloud 系列之 Gateway 服务网关(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Gateway 服务网关(一) 本篇文章讲解 Gateway 网关的多种路由规则.动态路由规则(配合服务发现的路由规则 ...

  6. spring cloud 使用Eureka作为服务注册中心

    什么是Eureka?  Eureka是在AWS上定位服务的REST服务. Eureka简单示例,仅作为学习参考 在pom文件引入相关的starter(起步依赖) /*定义使用的spring cloud ...

  7. Spring Cloud Netflix Eureka【服务治理】

    一.简介 二.使用 一.源码分析

  8. Spring Cloud 入门教程(四): 分布式环境下自动发现配置服务

    前一章, 我们的Hello world应用服务,通过配置服务器Config Server获取到了我们配置的hello信息“hello world”. 但自己的配置文件中必须配置config serve ...

  9. Spring Cloud 入门教程(五): Ribbon实现客户端的负载均衡

    接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端 ...

随机推荐

  1. 用 JS 做一个数独游戏(二)

    用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...

  2. POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】

    Optimal Milking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Sub ...

  3. Java入门之JDK安装及环境变量配置

    一.安装JDK 安装过程中会出现两次安装提示 .第一次是安装 jdk ,第二次是安装 jre .建议两个都安装在同一个java文件夹中的不同文件夹中. (注:若无安装目录要求,可全默认设置.无需做任何 ...

  4. 关于.Net WebAPI数据认证(包括登陆认证、模型认证)

    1.登陆认证使用WebAPI自动认证  webApi自动认证继承类:AuthorizeAttribute 自动认证类使用在控制器上 [Authentication] public class Card ...

  5. IsBackground对线程的重要作用

    要点: 1.当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的. 2.当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行 ...

  6. Android Studio 小技巧(1):如何导入AAR文件

    1. 导入AAR.JAR文件 File- > New -> New Module 这样子AAR文件就导入了,然后在app中的build.gradle中做如下添加 dependencies ...

  7. SQL Server 2008 角色

    固定服务器角色:按照从最低级别的角色(bulkadmin)到最高级别的角色(sysadmin)的顺序进行描述:Bulkadmin:这个服务器角色的成员可以运行BULK INSERT语句.这条语句允许从 ...

  8. 建立本地yum源

    使用环境 服务器处于内网,需要更新 网络资源紧张,节约带宽 建立yum目录 mkdir -p /opt/opmgmt/yum rsync服务器列表 centos mirrors epel mirror ...

  9. ARM实验3 ——串口实验

    uart串口实验 实验内容: 编写UART模块程序,通过串口将信息打印到终端. 实验目的: 熟悉开发环境的使用. 掌握exynos4412处理器的UART功能. 实验平台: FS4412开发板,ecl ...

  10. 指定类型的成员XX”不支持实体LINQ。只有初始化,成员单位,和实体导航性能的支持。

    The specified type member 'DeleteFlag' is not supported in LINQ to Entities. Only initializers, enti ...