RestTemplate简介
RestTemplate是Spring Resources中一个访问第三方RestFul api接口的网络请求框架。RestTemplate 的设计原则和其他Spring Template(例如JdbcTemplate、JmsTemplate)类似,都是为执行复杂任务提供了一个具有默认行为的简单方法。
RestTemplate是用来消费REST服务的,所以RestTemplate的主要方法都与REST的Http协议的一些方法紧密相连,例如HEAD、GET、POST、PUT、DELETE、OPTIONS等方法,这些方法在RestTemplate类对应的方法为headForHeaders()、getForObject()、postForObject()、put()、delete()等。
maven依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
application启动类注入bean:
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
service层引用注入实例:
@Autowired
private RestTemplate restTemplate;
User user = restTemplate.getForObject("http://weather/getUser", User.class);
return user.getName();
RestTemplate的使用很简单,它支持xml、json数据格式,默认实现序列化,可以自动将JSON字符串转化为实体,如上代码,可以将返回的json字符串转换成User对象。
负载均衡是指将负载分摊到多个执行单元上,常见的负载均衡有两种方式,一种是独立进行单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如Ngnix。另一种是将负载均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提供者的信息列表,有了列表,通过负载均衡策略将请求分摊到多个服务提供者,从而达到负载均衡的目的。
LoadBalancerClient简介
负载均衡的核心类是LoadBalancerClient,它可以获取负载均衡的服务提供者的实例信息。比如注册一个服务weather,这个服务weather监听2个端口8770/8764,并启动这两个服务。那么在Eureka server上会注册2个实例,当你使用负载均衡的时候,LoadBalancerClient的choose("weather")方法可以轮流得到client的两个服务实例的信息,交替请求这两个服务。
8764实例
8770实例
访问eureka server,weather的2个实例已经注册成功
访问ribbon
我们发现,同样访问ribbon接口,结果是从8764和8770交替返回的结果,这样就实现了请求分发,负载均衡。
LoadBalancerClient接口继承了ServiceInstanceChooser,RibbonLoadBalancerClient实现了LoadBalancerClient,RibbonLoadBalancerClient是非常重要的类,最终的负载均衡请求处理由它来执行。choose()方法用于选择具体服务实例。choose()方法通过getServer()方法获取实例,经过源码跟踪最终通过ILoadBalancer类去选择实例。
IRule有很多具体的实现类,这些根据不同的算法和逻辑来处理负载均衡的策略。
IPing用于向server发送"ping",来判断该server是否有响应,从而判断server是否可用,它有一个isAlive()方法。
EurekaClient的实现类DiscoveryClient,DiscoveryClient具有服务注册、获取服务注册列表等功能。
Ribbon的使用,这里使用了@LoadBalanced负载均衡。
Ribbon结合RestTemplate
controller
Springcloud在封装Ribbon的时候,提供了OkHttpClient和HttpClient请求实例。
Ribbon实现负载均衡的三点是:
服务发现:就是依据服务的名字,把该服务下的所有实例都找出来
服务选择规则:依据规则策略,如何从多个服务中找出要使用的服务
服务监听:检测失效服务,做到高效剔除
Ribbon的主要组建有ServerList、IRule、ServerListFilter,整个首先会通过ServerList获得可用服务列表,再通过ServerListFilter,过滤掉一些地址,最后剩下的地址,通过IRule,作为最终目标结果。
ILoadBalance负载均衡器
ribbon作为一个客户端提供负载均衡功能的服务,内部提供一个ILoadBalance的接口,代表负载均衡的操作,比如添加服务器、选择服务器、获取所有服务器列表、获取可用服务器列表等等。
负载均衡器是从EurekaClient(EurekaClient的实现类是DiscoveryClient)获取服务信息,根据IRule去路由,并且根据Ping判断服务的可用性。负载均衡器平均10秒去EurekaClient获取服务注册信息。
完整过程是:
LoadBalancerClient(RibbonLoadBalancerClient是实现类)在初始化的时候(execute方法),会通过ILoadBalance(BaseLoadBalancer是实现类)向Eureka注册中心获取服务注册列表,并且每10s一次向EurekaClient发送“ping”,来判断服务的可用性,如果服务的可用性发生了改变或者服务数量和之前的不一致,则从注册中心更新或者重新拉取。LoadBalancerClient有了这些服务注册列表,就可以根据具体的IRule来进行负载均衡。
IRule是负载均衡器的策略对象
其中RandomRule表示随机策略,随机从服务器中选择一个
RoundRobinRule表示轮询策略(默认采用轮询策略),循环使用服务器,比如5台服务器a,b,c,d,e,轮循使用
WeightedResponseTimeRule表示加权策略,继承RoundRobinRule,开始的时候没有权重列表,采用父类的轮循方式,有一个默认30秒更新一次权重的定时任务,该任务根据实例反应时间来更新权重列表,choose方式做的事情是,用一个(0,1)的随机double数乘以最大的权重得到randomWeight,然后遍历权重列表,找出第一个比randomWeight更大的实例下标,返回该实例。
BestAvailableRule表示请求数最少策略等等
默认采用是轮询方式,如果想改变负载均衡策略,可以重新注入bean,这种方式对Feign也有效
@Bean
public IRule ribbonRule() {
return new BestAvailableRule();
}
总体有7种策略
策略名 | 策略声明 | 策略描述 | 实现说明 |
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
Ribbon架构图