Ribbon 工具 —— RestTemplate 负载均衡调用服务
Eureka 用来搭建服务注册中心,主要包括服务注册和服务发现,服务的发现由eureka客户端实现,而服务的消费由Ribbon实现,也就是说服务的调用需要eureka客户端和Ribbon两者配合起来才能实现;
1.Ribbon是什么?
Ribbon是一个基于HTTP 和 TCP 的客户端负载均衡器,当使用Ribbon对服务进行访问的时候,它会扩展Eureka客户端的服务发现功能,实现从Eureka注册中心中获取服务端列表,并通过Eureka客户端来确定服务端是否己经启动。Ribbon在Eureka客户端服务发现的基础上,实现了对服务实例的选择策略,从而实现对服务的负载均衡消费。
Spring Cloud对Ribbon做了二次封装,可以让我们使用RestTemplate的服务请求,自动转换成客户端负载均衡的服务调用。
Ribbon支持多种负载均衡算法,还支持自定义的负载均衡算法。
Ribbon只是一个工具类框架,不像服务注册中心、配置中心、API网关那样需要独立部署,Ribbon只需要在代码直接使用即可;
2.Ribbon实现负载均衡
在Spring Cloud中,Ribbon主要与RestTemplate对象配合起来使用,Ribbon会自动化配置RestTemplate对象,通过@LoadBalanced
开启RestTemplate对象调用时的负载均衡。
负载均衡策略
说明 | |
---|---|
RandomRule | 随机 |
RoundRobinRule | 轮询(默认) |
AvailabilityFilteringRule | 先过滤掉多次访问故障的服务,以及并发连接数超过阈值的服务,然后对剩下的服务按照轮询策略进行访问; |
WeightedResponseTimeRule | 根据平均响应时间计算所有服务的权重,响应时间越快服务权重就越大被选中的概率即越高,如果服务刚启动时统计信息不足,则使用RoundRobinRule策略,待统计信息足够会切换到该WeightedResponseTimeRule策略; |
RetryRule | 先按照RoundRobinRule策略分发,如果分发到的服务不能访问,则在指定时间内进行重试,分发其他可用的服务; |
BestAvailableRule | 先过滤掉多次访问故障的服务,然后选择一个并发量最小的服务; |
ZoneAvoidanceRule | 综合判断服务节点所在区域的性能和服务节点的可用性,来决定选择哪个服务; |
设置负载均衡
也可直接把restTemplate方法写在入口类中
@Configuration
public class ConsumerConfig {
@Bean
@LoadBalanced /*给RestTemplate加 负载均衡注解,因为是通过RestTemplate去实现的服务之间的调用*/
public RestTemplate getResttemplate(){
return new RestTemplate();
}
// 设置ribbon负载均衡策略为 随机策略(默认是 轮询)
@Bean
public IRule getRule(){
return new RandomRule();
}
}
如果要自己写策略,则继承IRule 接口,并重写方法
3.RestTemplate四种请求
RestTemplate:Spring封装的远程调用的模板对象,发送 http 的 restful api 请求操作
GET请求 –获取数据
- getForEntity
/**
* 方法名称:
* getForEntity(String url,Class responseType):返回值ResponseEntity<T>
* getForEntity(String url,Class responseType,Object... objs):返回值ResponseEntity<T>
* getForEntity(String url,Class responseType,Map params):返回值ResponseEntity<T>
* 参数列表:
* 参数1,url请求地址
* 参数2,响应的字节码类型
* 参数3,封装的参数,可以用可变参数封装,也可以通过Map集合的键值对进行封装
* 返回值:ResponseEntity<T> 对象,包含
* 响应消息体boby
* 响应头
* 响应状态码
* 响应状态码对应的值
*/
//举例
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class);
String body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
Object [] params={1,”张三”};
restTemplate.getForEntity("http://SPRINGCLOUD-SERVICE-PROVIDER/service/hello?id={0}&name={1}", String.class, params).getBody();
Map<String, Object> paramMap = new ConcurrentHashMap<>();
paramMap.put("id", 1);
paramMap.put("name", "张三");
restTemplate.getForEntity("http://SPRINGCLOUD-SERVICE-PROVIDER/service/hello?id={id}&name={name}", String.class, paramMap).getBody();
- getForObject()
- 在getForEntity基础上进行了再次封装,只返回响应中body体信息
- 其它包括重载方法和getForEntity类似
POST请求 –添加数据
- restTemplate.postForObject()
- restTemplate.postForEntity()
- restTemplate.postForLocation()
/** postForEntity(String url,Object request,Class responseType)
* 参数列表:
* 参数1,url请求地址
* 参数2,封装到请求体中的数据
* 参数3,响应的字节码类型
*/
//服务消费者
Map<String,Object> request = new HashMap<>();
request.put("loginName","wangwu");
ResponseEntity<R> entity = restTemplate.postForEntity("http://EUREKA-CLIENT-PROVIDER/provider/test/{id}?age=22", request, R.class, paramsMap);
//服务提供者
@PostMapping("/test/{id}")
public void provider04(@PathVariable Integer id, // @PathVariable 获取restful风格请求的数据
@RequestParam String age, // @RequestParam 获取携带的参数
@RequestBody Map<String,Object> requestBody){ //@RequestBody 获取请求体中的数据,如上面的request Map集合
- 地址栏中的参数 @PathVariable
- 地址栏中的键值对 @RequestParam
- 请求体重的参数 @RequestBody
PUT请求 – 修改数据
/**返回值void,如果进行修改,想要获取提供者的返回值,请使用post方式
* put(String url,Object request,Class responseType)
* put(String url,Object request,Object... objs)
* put(String url,Object request,Map params)
* 参数列表:
* 参数1,url请求地址
* 参数2,封装到请求体中的数据
* 参数3,封装的参数,可以用可变参数封装,也可以通过Map集合的键值对进行封装
*/
DELETE请求 –删除数据
/**返回值void,如果进行删除,想要获取提供者的返回值,请使用get方式
* delete(String url)
* delete(String url,Object... objs)
* delete(String url,Map params)
* 参数列表:
* 参数1,url请求地址
* 参数2,封装的参数,可以用可变参数封装,也可以通过Map集合的键值对进行封装
*/