Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的RES模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上是通过Ribbon来实现的,包括后续我们将要学习的Feign,它也是基于Ribbon实现的工具。

一、客户端负载均衡

负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们常说的负载均衡是指服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点中回见安装专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些具有负载均衡功能或模块的软件来完成请求分发工作,比如Nginx等,不论是采用硬件负载均衡还是软件负载均衡,只要是服务端负载均衡都能以类似如下图的架构方式构建起来。

硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点,当客户端发送请求道负载均衡设备的时候,该设备按某种算法(eg:线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。

客户端负载均衡和服务端负载均衡最大的不同点在于上面所提及的服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护这自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心。通服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,这个步骤要与服务注册中心配合完成、在Spring Cloud实现的服务治理框架中,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Euruka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.apringframework.cloud.consul.discovery.RibbonCounsulAutoConn。在实际使用的时候,我们通过查看这两个类的实现,以找到他们的配置详情来帮助我们更好的使用它。

通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:

  • 服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。
  • 服务消费者直接通过调用被@LocdBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。

二、RestTemplate详解

RestTemplate针对不同请求类型和参数类型的服务调用实现。

1、GET请求

在RestTemplate中,对GET请求可以通过如下两个方法进行调用实现

第一种:getForEntity函数,该方法返回的是ResponseEntity,该对象时Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象HttpStatus、在它的服了你HttpEntity中还存储着HTTP请求头信息对象HttpHeaders已经泛型类型的请求体对象。eg:访问USER-SERVER服务的/user请求,同时最后一个参数didi会替换url中的{1}占位符,而返回的ResponseEntity对象中的body内容类型会根据第二个参数转换为String类型。

 RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}",String.class,"didi");
String body = responseEntity.getBody();

如果我们希望返回的body是一个User对象类型,也可以如下:

 RestTemplate restTemplate = new RestTemplate();
ResponseEntity<User> responseEntiry = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}",User.class,"didi");
User body = responseEntity.getBody();

上述是比较常用的方法,getForEntity函数实际上提供了以下三种不同的重载实现:

getForEntity(String url,Class responseType,Object ... urlVariables):该方法提供;额三个参数,其中url为请求的地址,responseType为请求相应提body的包装类型,urlVariables为url中的参数绑定。GET请求的参数绑定通常使用url中拼接的方式,比如:http://USER-SERVICE/user?name=didi.我们可以像这样将自己的参数拼接到url中,但是更好的方式是在url中使用占位符并配合参数urlVariable参数实现GET请求的参数绑定,比如url定义为http://USER-SERVICE/user?name={1},调用的时候使用getForEntity{"http://USER-SERVICE/user?name={1}",String.class,"didi"}其中第三个参数didi会替换url中的{1}占位符。

getForEntity(String url,Class responseType,Map urlVariables):该方法中,只有urlVariables的参数类型与上述的方法不同。这里使用了Map类型,所以使用该方法进行参数绑定时需要在占位符中指定Map中参数的key值,比如url定义为http://USER-SERVICE/user?name=${name}在Map类型的urlVariables中,我们就需要put一个key为name的参数来绑定url中{name}占位符的值

eg:

 RestTemplate restTemplate = new RestTemplate();
Map<String,String> params = new HashMap<>();
params.put("name","data");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={name}",String.class ,params);

getForEntity(URI  url ,Class ResponseType):该方法使用URI对象来代替之前的url和urlVariables参数来指定访问地址和参数绑定。URI是JDK java.net包下的一个类,它表示一个统一资源标识符引用

 RestTemplate restTemplate = new RestTemplate();
UriComponents uriComponents = UriComponentsBuilder.fromriString("http://USER-SERVICE/user?name=${name}").build().expand("dodo").encode();
URI uri = uriComponents.toUri();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url,String.class).getBody();

第二种:getForObject函数

该方法可以理解为getForEntity的进一步封装,通过HttpMessageConvertExtractor对HTTP的请求响应体body内容进行转接,实现请求直接返回包装好的对象内容。eg:

 RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri,String.class)

当body是一个User对象时,可以直接这样实现eg:

 RestTemplate restTemplate = new RestTemplate();
User result = restTemplate.getForObject(uri,User.class);

当不需要关注请求响应除body外的其他内容时,该函数非常好用,可以少有从Response中获取body的步骤。它与getForEntity函数类似,也提供了三种不同的重载实现

getForObject(String url,Class responseType,Object...urlVariables):与getForEntity的方法类似,url参数指定访问的地址,responseType参数定义该方法的返回类型,url参数指定访问的地址,responseType参数定义该方法的返回类型,urlVariables参数为url中占位符对应的参数

getForObject(String url,Class responseType,Map urlVariables):在该甘薯中,使用Map类型的urlVariable替代上面数组形式的urlVariable,因此使用时在url中需要将占位符的名称与Map类型的key一一对应设置

getForObject(URI url,Class responseType):该方法使用URI对象来代替之前的url和urlVariable参数使用。

2、POST请求

在RestTemplate中,对POST请求时可以通过如下三个方法进行调用实现。

第一种:postForEntity函数。该方法同GET请求中的getForEntity类型,会在调用后返回ResponseEntity<T>对象,其中T为请求响应的body类型,eg:使用postForEntity提交POST请求道USER--SERVICE服务的/user接口,提交的body内容为user对象,请求响应返回的body类型为String.

 RestTemplate restTemplate = new RestTemplate();
User user = new User("didi",);
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://USER-SERVICE/user",user,String.class);
String body = responseEntity.getBody();

postForEntity函数也实现了三种不同的重载方法

postForEntity(String url,Object request,Class responseType,Object...urlVariables)

posrForEntity(String url,Object request,Class  responseType,Map uriVariables)

postForEntity(URI uri ,Object request,Class responseType)

第二种:postForObject函数,该方法也跟getForObject的类型类似,它的作用是简化postForEntity的后续处理。通过直接将请求响应的body内容包装成对象类返回使用,eg:

 RestTemplate restTemplate = new RestTemplate()l
User user = new User("didi",);
String postResult = restTemplate.postForObject("http://USER-SERVICE/user",user,String.class);

postForObject函数也实现了三种不同的重载方法

postForObject(String url,Object request,Class responseType,Object...urlVariables)

postForObject(String url,Object request,Class  responseType,Map uriVariables)

postForObject(URI uri ,Object request,Class responseType)

第三种:postForLocation函数,该方法实现了以POST请求提交资源,并返回新资源的URI,比如下面的例子

 User user = new User("didi",);
URI responseURI = restTemplate.postForLocation("http://USER-SERVICE/user",user);

postForLocation函数也实现了三种不同的重载方法

postForLocation(String url,Object request,bject...urlVariables)

postForLocation(String url,Object request,Class  responseType,Map uriVariables)

postForLocation(URI uri ,Object request,Class responseType)

3、PUT请求

在RestTemplate中,对PUT请求可以通过put方法进行调用实现,比如:

 RestTemplate restTemplate = new RestTemplate();
Long id = 1000L;
User user = new User("didi",);
restTemplate.put("http://USER-SERVICE/user/{1}",user,id);

put函数三种不同的重载方法:

put(String url,Object request,bject...urlVariables)

put(String url,Object request,Map uriVariables)

put(URI uri ,Object request)

put函数为void类型,所以没有返回内容,也就没有其他函数定义的responseType参数,除此之外的其他传入参数定义与用法与postForObject基本一致。

4、DELETE请求

在RestTemplate中,对DELETE请求可以通过delete请求方法进行调用实现,eg:

 RestTemplate restTemplate = new RestTemplate();
Long id = 1000L;
restTemplate.delete("http://USER-SERVICE/user/{1}",id);

delete函数三种不同的重载:

delete(String url,bject...urlVariables)

delete(String url,Map uriVariables)

delete(URI uri )

由于我们在进行REST请求时,通常将DELETE请求的唯一标识拼接在url中,所以DELETE请求也不需要request的body信息。url指定DELETE请求的位置,urlVariables绑定url中的参数即可。

【SpringCloud微服务实战学习系列】客户端负载均衡Spring Cloud Ribbon的更多相关文章

  1. 【SpringCloud微服务实战学习系列】服务治理Spring Cloud Eureka

    Spring Cloud Eureka是Spring Cloud Netflix微服务中的一部分,它基于NetFlix Sureka做了二次封装,主要负责完成微服务架构中的服务治理功能. 一.服务治理 ...

  2. 【SpringCloud微服务实战学习系列】配置详解

    前言 Spring Boot针对常用的开发场景提供了一系列自动化配置来减少原本复杂而又几乎很少改动的模板化配置内容. 一.配置文件 Spring Boot的默认配置文件位置为src/main.reso ...

  3. 【SpringCloud微服务实战学习系列】创建应用及解析

    一.创建应用 使用官方Spring Initializr工具生成基础项目(http://start.spring.io/) 导入Intellij idea中 目录结构如下: 二.目录结构说明: src ...

  4. SpringCloud---客户端负载均衡---Spring Cloud Ribbon

    1.概述 1.1 Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具: 基于Netflix Ribbon实现: 通过Spring Cloud的封装,可以轻松将面向服务 ...

  5. SpringCloud学习(SPRINGCLOUD微服务实战)一

    SpringCloud学习(SPRINGCLOUD微服务实战) springboot入门 1.配置文件 1.1可以自定义参数并在程序中使用 注解@component @value 例如 若配置文件为a ...

  6. springcloud微服务实战--笔记

    目前对Springcloud对了解仅限于:“用[注册服务.配置服务]来统一管理其他微服务” 这个水平.有待提高 Springcloud微服务实战这本书是翟永超2017年5月写的,时间已经过去了两年,略 ...

  7. SpringCloud微服务实战——搭建企业级开发框架(十二):OpenFeign+Ribbon实现负载均衡

      Ribbon是Netflix下的负载均衡项目,它主要实现中间层应用程序的负载均衡.为Ribbon配置服务提供者地址列表后,Ribbon就会基于某种负载均衡算法,自动帮助服务调用者去请求.Ribbo ...

  8. SpringCloud微服务实战——第三章服务治理

    Spring Cloud Eureka 服务治理 是微服务架构中最核心最基本的模块.用于实现各个微服务实例的自动化注册与发现. 服务注册: 在服务治理框架中,都会构建一个注册中心,每个服务单元向注册中 ...

  9. SpringCloud微服务实战——第一章序言读书笔记

    什么是微服务架构 是系统架构上的一种设计风格,将独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间基于HTTP的RESTful API进行通信协作. 每个小型服务都围绕各自的 ...

随机推荐

  1. C# 获取文件名及扩展名【转】

    https://www.cnblogs.com/libushuang/p/5794976.html C# 获取文件名及扩展名 string aFirstName = aFile.Substring(a ...

  2. android:如何通过自定义工程模板让新建的工程都默认支持lambda表达式

    首先参考这篇文章:自定义Android Studio工程模板,了解如何自定义模板   然后结合我们上一篇文章 android: 在android studio中使用retrolambda的步骤的要点, ...

  3. .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)

    本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...

  4. 通过action传过来的值在option获取进行验证

    通过action传过来的值在option获取进行验证的方法: for(var i=0;i<document.getElementById("ufacilityType").o ...

  5. (原)IOU的计算

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/9043395.html 参考网址: https://github.com/deepinsight/ins ...

  6. 基于window自带功能生成目录树

    在写文档时,生成目录树是非常有必要的,可以清晰明了地用图阐释一些事情. 1 生成目录树 1.1 方案1:操作繁(只显示文件夹) 1 - win + R 2 - 输入 “CMD” ,打开命令提示窗口“ ...

  7. Java线上问题排查思路及Linux常用问题分析命令学习

    前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...

  8. Atitit  Uncaught (in promise) SyntaxError Unexpected token < in JSON at position 0

    Atitit  Uncaught (in promise) SyntaxError  Unexpected token < in JSON at position 0  Uncaught (in ...

  9. Socket网络编程--简单Web服务器(2)

    上一小节通过阅读开源的Web服务器--tinyhttpd.大概知道了一次交互的请求信息和应答信息的具体过程.接下来我就自己简单的实现一个Web服务器. 下面这个程序只是实现一个简单的框架出来.这次先实 ...

  10. 菜鸟教程之工具使用(八)——EGit禁止自动转换回车换行符

    众所周知,Windows和Linux系统的回车换行是不一样的.想要进一步了解它们的可以阅读下面的介绍,不感兴趣的可以直接跳过. 产生背景 关于“回车”(carriage return)和“换行”(li ...