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

1、ribbon

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

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

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

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId>
<artifactId>eurekaRibbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>eurekaRibbon</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

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

package com.example.demo;

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.web.client.RestTemplate; @EnableDiscoveryClient
@SpringBootApplication
public class EurekaRibbonApplication { @Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(EurekaRibbonApplication.class, args);
}
}

4、接口

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class ClientRibbonController { @Autowired
RestTemplate restTemplate; @GetMapping("/consumer")
public String all() {
// 发起REST请求
return restTemplate.getForObject("http://eurekaClient/all", String.class);
} }

  这里请求的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

/**
* Represents a client side load balancer
* @author Spencer Gibb
*/
public interface LoadBalancerClient extends ServiceInstanceChooser { /**
* execute request using a ServiceInstance from the LoadBalancer for the specified
* service
* @param serviceId the service id to look up the LoadBalancer
* @param request allows implementations to execute pre and post actions such as
* incrementing metrics
* @return the result of the LoadBalancerRequest callback on the selected
* ServiceInstance
*/
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException; /**
* execute request using a ServiceInstance from the LoadBalancer for the specified
* service
* @param serviceId the service id to look up the LoadBalancer
* @param serviceInstance the service to execute the request to
* @param request allows implementations to execute pre and post actions such as
* incrementing metrics
* @return the result of the LoadBalancerRequest callback on the selected
* ServiceInstance
*/
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException; /**
* Create a proper URI with a real host and port for systems to utilize.
* Some systems use a URI with the logical serivce name as the host,
* such as http://myservice/path/to/service. This will replace the
* service name with the host:port from the ServiceInstance.
* @param instance
* @param original a URI with the host as a logical service name
* @return a reconstructed URI
*/
URI reconstructURI(ServiceInstance instance, URI original);
}

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

2、Ribbon自动化配置:LoadBalancerAutoConfiguration

/**
* Auto configuration for Ribbon (client side load balancing).
*
* @author Spencer Gibb
* @author Dave Syer
* @author Will Tran
*/
@Configuration
@ConditionalOnClass(RestTemplate.class) //条件 : RestTemplate必须在工程的类路径下
@ConditionalOnBean(LoadBalancerClient.class) //条件: Spring 容器中必须包含LoadBalancerClient的实现,即RibbonLoadBalancerClient
@EnableConfigurationProperties(LoadBalancerRetryProperties.class) //启动重试功能,可以spring.cloud.loadbalancer.retry=false,取消重试,默认参数为true
public class LoadBalancerAutoConfiguration { @LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList(); //维护一个RestTemplate列表,通过LoadBalanced来注解。 @Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializer( //加载初始话自定义的restTeplate,实质是初始化InterceptingHttpAccessor具体调用
final List<RestTemplateCustomizer> customizers) {
return new SmartInitializingSingleton() {
@Override
public void afterSingletonsInstantiated() {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
}
};
} @Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); @Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
} @Configuration
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
} @Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return new RestTemplateCustomizer() {
@Override
public void customize(RestTemplate restTemplate) {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
};
}
} @Configuration
@ConditionalOnClass(RetryTemplate.class)
static class RetryAutoConfiguration {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate template = new RetryTemplate();
template.setThrowLastExceptionOnExhausted(true);
return template;
} @Bean
@ConditionalOnMissingBean
public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {
return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();
} @Bean
public RetryLoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
LoadBalancerRequestFactory requestFactory) {
return new RetryLoadBalancerInterceptor(loadBalancerClient, retryTemplate(), properties,
lbRetryPolicyFactory, requestFactory);
} @Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer( //自定义RestTemplate ,实质是初始化InterceptingHttpAccessor
final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
return new RestTemplateCustomizer() {
@Override
public void customize(RestTemplate restTemplate) {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
};
}
}
}

具体可以看下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. Junit使用过程中需要注意的诡异bug以及处理办法

    在开发过程中我们有时会遇到狠多的问题和bug,对于在编译和运行过程中出现的问题很好解决,因为可以在错误日志中得到一定的错误提示信息,从而可以找到一些对应的解决办法.但是有时也会遇到一些比较诡异的问题和 ...

  2. IT方面书籍下载整理

    最近翻看Redis相关的中文书籍时,发现了很多错误,包括翻译错误及理论错误,因此想搜集一些相关的外文书籍看看.以下几个链接,内容大同小异,均可免费下载相关的英文书籍PDF版,内容涵盖了IT的方方面面. ...

  3. activeMq 配置(一)

    基础知识补充 1.ActiveMQ从入门到精通(一)https://www.jianshu.com/p/ecdc6eab554c 2.ActiveMQ从入门到精通(二)https://www.jian ...

  4. 【转】linux之pmap命令!

    原贴:http://tonykorn97.itpub.net/post/6414/249221 linux之pmap命令! ====================================== ...

  5. 谷歌浏览器web worker出现cannot be accessed from origin 'null'错误

    cannot be accessed from origin 'null'百度翻译是:无法从原点"null"访问 在别的浏览器都可以,而在唯独在谷歌浏览器不行,查找了一些资料原因大 ...

  6. [持续更新] Linux基础的重要命令

    命令总结:100个左右 mkdir 方法一 [root@localhost ~]# mkdir /test && ls -ld /test 方法二 [root@localhost ~] ...

  7. Lync二次开发关于Lync启动退出问题

    以前使用C++开发的version.dll文件,由于各个用户环境的不同,造成某些用户加载不了我们开发的插件,并且写version.dll的同事还没找到好的解决办法,所以得换一种思路去解决这个问题,就是 ...

  8. SQLServer查询语句收集

    常用的SQLServer查询语句,有空可以多练习一下,增加记忆,可以提高工作效率! 1.数据操作 Select      --从数据库表中检索数据行和列Insert      --向数据库表添加新数据 ...

  9. C++ VS编译问题--LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    用VS编译时,当出现错误LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏: 这个问题的解决方案为: 1. 找到项目\xx属性\配置属性\清单工具\输 ...

  10. Android环信即时通讯集成坑爹 注册报错208解决

    第一种情况:    你用的环信APPkey 是授权模式的   只要改成开放模式就可以了 第二种情况:    上述情况在环信官网都有说明  但是这种情况  环信官网就没得说明   只说的是同步方法 注册 ...