Spring Cloud Ribbon入门
一、简介
Spring Cloud Ribbon是一个基于Http和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的。它不像服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个微服务的基础设施中。理解Ribbon对于我们使用Spring Cloud来讲非常的重要,因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。
在Spring Cloud中,有两种服务调用方式,一种是Ribbon+RestTemplate,另一种是Feign。文本先讲解下基于Ribbon+RestTemplate的用法。
当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。
二、入门案例
1、引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
注意:Eureka默认集成了Ribbon,只需引入Eureka JAR即可。
2、在启动类中注入配置
package com.mimaxueyuan.consumer.robbin; 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.Primary;
import org.springframework.web.client.RestTemplate; @SpringBootApplication
@EnableDiscoveryClient
public class RibbonConsumerApplication { @Bean
@LoadBalanced // 需要使用负载均衡,必须与Bean一同使用
public RestTemplate balanceRestTemplate() {
return new RestTemplate();
} @Primary //自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Bean //需要多个RestTemplate, 有的RestTemplate使用负载均衡,有的不使用,不使用的不增加@LoadBalanced注解
public RestTemplate noBalanceRestTemplate() {
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
} }
3、编写 Controller——演示使用负载均衡和不使用负载均衡的用法及区别
package com.mimaxueyuan.consumer.robbin.controller; import java.net.URI;
import java.net.URISyntaxException;
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import com.mimaxueyuan.consumer.entity.User; @RestController
public class RibbonController { // 注入restTemplate, 这个类已经在RibbonConsumerApplication中初始化,不使用负载均衡
@Autowired
private RestTemplate noBalanceRestTemplate; // 注入restTemplate, 这个类已经在RibbonConsumerApplication中初始化,并且使用负载均衡
@Autowired // 默认按照类型注入,如果需要按照名字注入需要使用@Qualifier注解
//@LoadBalanced //使用带有负载均衡的RestTemplate
@Qualifier("balanceRestTemplate")
private RestTemplate balanceRestTemplate; // 以下注入负载均衡客户端LoadBalancerClient是一个接口,下面只有一个RibbonLoadBalancerClient实现类
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RibbonLoadBalancerClient ribbonLoadBalancerClient; /**
* 不使用ribbon的旧调用方式
*
* @author Kevin
* @Title: old
* @return
* @return: String
*/
@GetMapping("/ribbon/old/get/{id}")
public String old(@PathVariable("id") String id) { // 使用noBalanceRestTemplate是非负载均衡的,所以没问题
String result = noBalanceRestTemplate.getForObject("http://localhost:9907/get/"+id, String.class);
System.out.println("[hardcode1]" + result); // 由于balanceRestTemplate已经使用了Ribbon做负载均衡,所以使用硬编码方式就不允许了,会提示:No instances available for localhost
result = balanceRestTemplate.getForObject("http://localhost:9907/get/"+id, String.class);
System.out.println("[hardcode2]" + result); return "result";
} /**
* ribbon使用
*
* @author Kevin
* @Title: ribbon
* @param id
* @return
* @return: String
*/
@GetMapping("/ribbon/get/{id}")
public String ribbon(@PathVariable("id") String id) {
// -----------------以下代码使用ribbon做客户端负载均衡
// 使用provider的instanceName替代ip和端口的硬编码
String result = balanceRestTemplate.getForObject("http://mima-cloud-producer/get/"+id, String.class);
System.out.println("[ribbon]" + result); System.out.println("[loadBalancerClient]choose的结果,代表负载均衡之后要选择的服务实例");
ServiceInstance instance = loadBalancerClient.choose("mima-cloud-producer");
System.out.println("host:" + instance.getHost() + ",port:" + instance.getPort() + ",serviceId=" + instance.getServiceId() + ",uri=" + instance.getUri()); System.out.println("[ribbonLoadBalancerClient]choose的结果,代表负载均衡之后要选择的服务实例");
instance = ribbonLoadBalancerClient.choose("mima-cloud-producer");
System.out.println("host:" + instance.getHost() + ",port:" + instance.getPort() + ",serviceId=" + instance.getServiceId() + ",uri=" + instance.getUri()); System.out.println("[ribbonLoadBalancerClient]choose的结果,代表负载均衡之后要选择的服务实例");
instance = ribbonLoadBalancerClient.choose("mima-cloud-producer");
System.out.println("host:" + instance.getHost() + ",port:" + instance.getPort() + ",serviceId=" + instance.getServiceId() + ",uri=" + instance.getUri());
try {
// 根据负载均衡后的服务,构建一个访问url
// 第二个参数不能为null
System.out.println("根据负载均衡后的服务,构建一个访问url");
URI reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI(""));
System.out.println("reconstructURI1-yes:" + reconstructURI);
// 拼写在请求地址后边,需要注意是否需要添加/
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("/ribbon/get"));
System.out.println("reconstructURI2-yes:" + reconstructURI);
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("http"));
System.out.println("reconstructURI3-no:" + reconstructURI);
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("https"));
System.out.println("reconstructURI4-no:" + reconstructURI);
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("test"));
System.out.println("reconstructURI5-no:" + reconstructURI);
// 使用http:/xxx、https:/xxx可以用于切换http协议还是https协议
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("http:/ribbin/get"));
System.out.println("reconstructURI6-yes:" + reconstructURI);
reconstructURI = ribbonLoadBalancerClient.reconstructURI(instance, new URI("https:/ribbin/get"));
System.out.println("reconstructURI7-yes:" + reconstructURI);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return "ribbon's demo,please to see console output";
} @GetMapping("/nobalance/get/{id}")
public String nobalance(@PathVariable("id") String id) {
// -----------------以下代码使用硬编码方式调用服务
// 如果restTemplate已经使用了Ribbon做负载均衡,也就是使用了@LoadBaleced注解,依然使用硬编码方式就不允许了,会提示:No instances available for localhost String result = noBalanceRestTemplate.getForObject("http://localhost:9907/get/"+id, String.class);
System.out.println("[noBalanceRestTemplate-hardcode1]" + result); //正常访问
result = noBalanceRestTemplate.getForObject("http://localhost:9908/get/"+id, String.class);
System.out.println("[noBalanceRestTemplate-hardcode2]" + result); //正常访问 try {
//异常访问,Ribbon负载均衡只能通过服务名调用
result = balanceRestTemplate.getForObject("http://localhost:9907/get/"+id, String.class);
System.out.println("[balanceRestTemplate-hardcode1]" + result);
//异常访问,Ribbon负载均衡只能通过服务名调用
result = balanceRestTemplate.getForObject("http://localhost:9908/get/"+id, String.class);
System.out.println("[balanceRestTemplate-hardcode2]" + result);
} catch (Exception e) {
System.out.println("使用balanceRestTemplate同时使用地址硬编码错误:" + e.getMessage());
}
return "ribbon's demo,please to see console output";
} @SuppressWarnings("unchecked")
@GetMapping("listAll")
public List<User> listAll() {
// restTemplate怎样返回一个List对象
List<User> list = balanceRestTemplate.getForObject("http://mima-cloud-producer/listAll", List.class);
return list;
} }
其中 mima-cloud-producer 为服务名,启动两个服务节点如下:
http://localhost:9907/
http://localhost:9908/
Spring Cloud Ribbon入门的更多相关文章
- Spring Cloud微服务笔记(四)客户端负载均衡:Spring Cloud Ribbon
客户端负载均衡:Spring Cloud Ribbon 一.负载均衡概念 负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容.因为负载均衡对系统的高可用性. 网络压力的缓解和处理能力的扩容的 ...
- Spring Cloud Alibaba入门实战之nacos(一)
Spring Cloud Alibaba入门实战之nacos(一) 前情介绍 Spring Cloud Alibaba 是阿里巴巴提供的新一代的微服务解决方案,相信会有越来越多采用微服务架构的公司 ...
- 撸一撸Spring Cloud Ribbon的原理-负载均衡器
在上一篇<撸一撸Spring Cloud Ribbon的原理>中整理发现,RestTemplate内部调用负载均衡拦截器,拦截器内最终是调用了负载均衡器来选择服务实例. 接下来撸一撸负载均 ...
- 笔记:Spring Cloud Ribbon 客户端配置详解
自动化配置 由于 Ribbon 中定义的每一个接口都有多种不同的策略实现,同时这些接口之间又有一定的依赖关系,Spring Cloud Ribbon 中的自动化配置能够很方便的自动化构建接口的具体实现 ...
- 笔记:Spring Cloud Ribbon 客户端负载均衡
Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,基于 Netflix Ribbon 实现,通过Spring Cloud 的封装,可以让我们轻松的将面向服 ...
- 为Spring Cloud Ribbon配置请求重试(Camden.SR2+)
当我们使用Spring Cloud Ribbon实现客户端负载均衡的时候,通常都会利用@LoadBalanced来让RestTemplate具备客户端负载功能,从而实现面向服务名的接口访问. 下面的例 ...
- Spring Cloud 快速入门
Spring Cloud快速入门 代码地址: https://gitee.com/gloryxu/spring-cloud-test EureKa:服务注册中心 添加依赖 <dependenc ...
- 基于Spring cloud Ribbon和Eureka实现客户端负载均衡
前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...
- 撸一撸Spring Cloud Ribbon的原理-负载均衡策略
在前两篇<撸一撸Spring Cloud Ribbon的原理>,<撸一撸Spring Cloud Ribbon的原理-负载均衡器>中,整理了Ribbon如何通过负载均衡拦截器植 ...
随机推荐
- stark组件开发之编辑功能实现
编辑功能.和添加一样! 唯一不同的就是, 需要编辑一个指定的 记录.这就需要,在列表页面, 渲染编辑的时候,添加一个 id 值: class UserInfoHandler(StartHandler ...
- Java最小化镜像制作
下载Oracle官网的JRE包,最终下载的包如下: jre-8u181-linux-x64.tar.gz 解压JRE包并删除不必要的文件 #解压 tar xf jre-8u181-linux-x64. ...
- sql-多表查询
一:外连接 1.左外连接(left join) select * from A left join B on A.id=B.a_id 结果如下 很明显,A表的所有数据都显示出来了 ...
- 设计模式 工厂模式 使用shared_ptr
参考http://blog.csdn.net/calmreason/article/details/50903729 所有产品继承同一基本类 由工厂保存基类指针 产生各类产品 代码 // 002.cp ...
- 基于akka-http搭建restfull框架
1.scala开发环境介绍 2.scala插件的demo模板介绍 3.akka-http提供demo研究 4.添加路由机制解析 package org.netsharp.rest import akk ...
- List,set,Map理解
集合 集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...
- Chapter3_操作符_方法调用中的别名问题
接下来展示方法调用中的别名问题,方法调用中的别名问题指的是,将一个对对象的引用传递给某一个方法时,方法操作的是这一个特定的引用而不是这个引用的拷贝. class Person{ float heigh ...
- Chapter3_操作符_别名机制
Java中的别名机制实际体现的是对于“=”这一类赋值操作符的使用规则和内涵.“=”的实际内涵是指将右边的变量的值(对于基本数据类型而言)或者某一个对象的引用(对于某个具体对象而言)复制到左边的变量名所 ...
- windows 函数
数组清零 ::ZeroMemory(首地址,大小);
- JAVA 8 主要新特性 ----------------(二)版本中数据结构的修改浅析
一.版本中数据结构的修改浅析1.HashMap.HashSet.ConcurrentHashMap的数据结构发生变化 (1)HashMap简介(结构:哈希表+链表) HashMap存储的数据是无序的, ...