Spring Cloud 入门Eureka -Consumer服务消费(Ribbon)(二)
前面一篇介绍了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)(二)的更多相关文章
- Spring Cloud 入门Eureka -Consumer服务消费(声明式Feign)(三)
Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口并用注解来配置它既可完成对Web服务接 ...
- Spring Cloud 入门Eureka -Consumer服务消费(一)
这里介绍:LoadBalancerClient接口,它是一个负载均衡客户端的抽象定义,下面我们就看看如何使用Spring Cloud提供的负载均衡器客户端接口来实现服务的消费. 引用之前的文章中构建的 ...
- Spring Cloud 入门教程(一): 服务注册
1. 什么是Spring Cloud? Spring提供了一系列工具,可以帮助开发人员迅速搭建分布式系统中的公共组件(比如:配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁 ...
- spring cloud深入学习(三)-----服务消费
在上一篇博文中简单实现了eureka-server以及eureka-provider,后面会实现eureka-cosumer,现在针对eureka做进一步的详解. 微服务整体架构 文字再美也没有图片直 ...
- Spring Cloud 系列之 Gateway 服务网关(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Gateway 服务网关(一) 本篇文章讲解 Gateway 网关的多种路由规则.动态路由规则(配合服务发现的路由规则 ...
- spring cloud 使用Eureka作为服务注册中心
什么是Eureka? Eureka是在AWS上定位服务的REST服务. Eureka简单示例,仅作为学习参考 在pom文件引入相关的starter(起步依赖) /*定义使用的spring cloud ...
- Spring Cloud Netflix Eureka【服务治理】
一.简介 二.使用 一.源码分析
- Spring Cloud 入门教程(四): 分布式环境下自动发现配置服务
前一章, 我们的Hello world应用服务,通过配置服务器Config Server获取到了我们配置的hello信息“hello world”. 但自己的配置文件中必须配置config serve ...
- Spring Cloud 入门教程(五): Ribbon实现客户端的负载均衡
接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端 ...
随机推荐
- 用 JS 做一个数独游戏(二)
用 JS 做一个数独游戏(二) 在 上一篇博客 中,我们通过 Node 运行了我们的 JavaScript 代码,在控制台中打印出来生成好的数独终盘.为了让我们的数独游戏能有良好的体验,这篇博客将会为 ...
- POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】
Optimal Milking Time Limit:2000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u Sub ...
- Java入门之JDK安装及环境变量配置
一.安装JDK 安装过程中会出现两次安装提示 .第一次是安装 jdk ,第二次是安装 jre .建议两个都安装在同一个java文件夹中的不同文件夹中. (注:若无安装目录要求,可全默认设置.无需做任何 ...
- 关于.Net WebAPI数据认证(包括登陆认证、模型认证)
1.登陆认证使用WebAPI自动认证 webApi自动认证继承类:AuthorizeAttribute 自动认证类使用在控制器上 [Authentication] public class Card ...
- IsBackground对线程的重要作用
要点: 1.当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的. 2.当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行 ...
- Android Studio 小技巧(1):如何导入AAR文件
1. 导入AAR.JAR文件 File- > New -> New Module 这样子AAR文件就导入了,然后在app中的build.gradle中做如下添加 dependencies ...
- SQL Server 2008 角色
固定服务器角色:按照从最低级别的角色(bulkadmin)到最高级别的角色(sysadmin)的顺序进行描述:Bulkadmin:这个服务器角色的成员可以运行BULK INSERT语句.这条语句允许从 ...
- 建立本地yum源
使用环境 服务器处于内网,需要更新 网络资源紧张,节约带宽 建立yum目录 mkdir -p /opt/opmgmt/yum rsync服务器列表 centos mirrors epel mirror ...
- ARM实验3 ——串口实验
uart串口实验 实验内容: 编写UART模块程序,通过串口将信息打印到终端. 实验目的: 熟悉开发环境的使用. 掌握exynos4412处理器的UART功能. 实验平台: FS4412开发板,ecl ...
- 指定类型的成员XX”不支持实体LINQ。只有初始化,成员单位,和实体导航性能的支持。
The specified type member 'DeleteFlag' is not supported in LINQ to Entities. Only initializers, enti ...