本篇文章主要介绍SpringCloud的客户端负载均衡组件Ribbon,以及Rest请求模板RestTemplate
Ribbon 介绍
SpringCloud Ribbon 是一个基于HTTP 和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松的,面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。
负载均衡在系统架构中很重要,负载均衡是对系统的高可用,网络压力的环节和处理能力扩容的重要手段。在高并发的web请求中,大量用户同时点击一个登陆按钮,导致短时间内网络带宽急剧增加,服务器负载过重,这个时候我们就要对这些大量的请求做一个引流,把这些请求分发到不同的服务器上去,在这个过程中,使用什么样的算法把这些请求分发到不同的服务器上去,这是负载均衡需要做的。
在Spring Cloud 构建的微服务集群中,不同服务之间的通信是通过HTTP的Rest请求完成的,可能出现A服务对B的大量Rest请求,这个时候就要对A服务做客户端的负载均衡,B服务要创建多个实例来就收这些负载均衡后的Rest请求。
在客户端负载均衡中,所有客户端节点都维护这自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心。
下面使用一个例子,来演示Ribbon的负载均衡这一过程 ,使用上面这图的架构来搭建
第一步:建立高可用的服务注册中心,使用SpringCloud组件之Eureka中创建的高可用注册中心,并在本地启动
第二步:创建一个接受负载均衡的SpringBoot服务(上面的B服务)
pom.xml文件
新建一个HellowordController类
新建一个HellowordMain启动类
application.yaml配置文件
需要配置eureka:instance:hostname 和prefer-ip-address以及instance-id这三个参数
spring.cloud.client.ipAddress 获取当前节点的IP地址
新版本的Spring Cloud使用spring.cloud.client.ip-address获取
将项目打包成jar文件,并且在本地启动两个不同端口的实例
java -jar springcloud_helloword-0.0.1-SNAPSHOT.jar --server.port=8011
java -jar springcloud_helloword-0.0.1-SNAPSHOT.jar --server.port=8012
查看EurekaUI 两个注册中心和两个HELLO-SERVICE服务实例已经启动
第三步:创建一个有负载均衡的SpringBoot服务(A服务),并且向B服务发送Rest请求
pom.xml文件和B服务相同
创建ConsumerMain类
创建一个返回值是RestTemplate的方法,并且使用@Bean注解,这样这个RestTemplate对象就会加载到Spring容器中。
使用@LoadBalanced注解,开启客户端的负载均衡,并且该注解使用在RestTemplate对象上,使得通过RestTemplate对象发送的Rest请求会实现客户端的负载均衡。这里使用Ribbon的默认负载均衡,轮询服务注册清单,分发Rest请求。
创建ConsumerController类
使用@Autowired注解将Spring容器中的RestTemplate对象注入进来
通过RestTemplate对象发送Rest请求给B服务,并获取响应结果
application.yaml配置
启动Consumer项目
在浏览器中输入http://localhsot:8013/ribbon/consumer
多次刷新这个请求 会在B服务的两个实例后台看到交替打印Hello word!!! 这就是A服务的负载均衡轮询B服务的两个实例
RestTemplate
RestTemplate:是一个REST请求的模板,封装了不同Rest请求类型,该对象会使用Ribbon的自动化配置,同时通过配置@LoadBalanced还能够开启客户端的负载均衡。下面介绍RestTemplate的不同请求类型
GET请求
RestTemplate restTemplate = new RestTemplate();
ResponseEntity
String body = responseEntity .getBody();
第一个参数:表示 Rest请求的URL 通常使用服务的服务名称,服务通过服务名称获取注册中心上该服务名称下的所有实例,在服务中心中保存着各个实例的元数据包括IP和端口号,这样就可以组成一个url,然后实行负载均衡。
第二个参数:表示Rest请求的响应返回值类型,上面这个例子表示返回值是String类型。当然也可以是一个实体类
第三个参数:便是URL中映射的参数值 可以使使用Map<参数名:参数值> 如果没有可以不填
getForEntity方法返回的是整个Rest请求响应的结果 包含响应的body 当然还有一些其他的参数 如响应状态,等信息。
getForObject()
对于只要求获取响应body的情况可以直接使用getForObject()方法,该方法在getForObject()方法的基础上封装,直接返回响应body值
RestTemplate restTemplate = new RestTemplate();
String body = restTemplate .getForObject(String “http://HELLO-SERVICE/helllo/hello?name={1}”,String.class,"李四");
POST请求
post请求和get请求类似
多了一个postForLocation()方法,该方法实现以POST请求提交资源,并返回新资源的URL
User user = new User("李四",33);
URI responseUrl = restTemplate.postForLocation(url,user);
该方法不需要指定返回值类型,因为返回值类型指定为URI
PUT请求
put请求和get请求类似
DELETE请求
delete请求和get请求类似
总结:
在微服务架构中使用客户端负载均衡调用是需要两个步骤
1:服务提供者只需要启动多个服务实例并注册到一个注册中心或者多个关联的注册中心
2:服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate对象实现面向服务的接口调用