零.复习
其实,SpringCloud有点与之前学过的WebService相似。
SpringCloud构建项目的微服务框架,就是一个工具集,集Netfilx的开源组件进一步封装。
Eureka-Server、Eureka-Client、Ribbon
一.Eureka Client的高可用
- 启动eureka server注册中心
- 搭建服务的高可用
①准备服务提供者
②注意:同一个服务提供者的集群,服务的名字必须一致。
③同时向euraka注册 - 启动eureka server 启动多个服务实例即可
二.基于ribbon的负载均衡
Springcloud 中的默认的负载均衡策略是 轮询策略
restTemplate(类似httpClient协议的通信框架)+ ribbon组件(负载均衡)
<!--引入ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
-
rebbon组件如何进行负载均衡的呢?
当我们发起一个请求,这个请求调用服务,先去注册中心拿服务类表;区别于Dubbo,dubbo是在注册中心中,在服务提供方,设计了一系列负载均衡策略,当然消费方是可以覆盖服务方的负载均衡策略。(服务方提供负载均衡策略,消费方可覆盖服务方 )
Springcloud则不同,其所有的负载均衡均属”软负载均衡“。软负载均衡 — 基于客户端的负载均衡,与服务端无关。(ribbon是一个基于客户端的软负载均衡 )
当我们调用某个服务时,客户端向eureka server请求该服务实例,然后它会把这个服务的服务列表,全部返回给客户端,并缓存起来。(其中,客户端缓存列表会与服务器进行心跳检测,遇宕机会高效剔除 )即在客户端进行负载均衡,与服务提供者和注册中心没有关系。
所以可以使用@LoadBalanced注解,根据默认负载均衡策略拿到列表中的服务节点。 -
那么如何修改策略呢?
ribbon中轮询策略,是基于三大组件
-
ServerList ”用来获取服务列表“
根据指定的服务名,去拿取注册中心中的服务列表 -
ServerListFilter ”通过心跳机制,进行服务过滤“
为了保证服务的高可用,对拿到列表中的服务 与 eureka始终做”心跳机制“,去检测可用服务 -
IRule ”指定负载均衡规则“(修改处 )
拿到可用服务列表后,具体使用哪种负载均衡策略
- RibbonLoadBalancerClient.class 详情见 Ribbon负载均衡策略
public class RibbonLoadBalancerClient implements LoadBalancerClient {
//serviceId 服务唯一标识,通过get拿到真正的server
public ServiceInstance choose(String serviceId) {
Server server = this.getServer(serviceId);
return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
}
//chooseServer 取到ILoadBalancer组件
protected Server getServer(ILoadBalancer loadBalancer) {
return loadBalancer == null ? null : loadBalancer.chooseServer("default");
}
- ILoadBalancer
public interface ILoadBalancer {
//再从这去到BaseLoadBalancer实现类
Server chooseServer(Object var1);
- BaseLoadBalancer.class
public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {
//rule 默认RoundRobinRule() 轮询
private static final IRule DEFAULT_RULE = new RoundRobinRule();
//IRule 的实现类,就是哪些策略
protected IRule rule;
private final Counter createCounter() {
return Monitors.newCounter("LoadBalancer_ChooseServer");
}
public Server chooseServer(Object key) {
if (this.counter == null) {
//轮询需要计数,好知道哪台机器是否访问过
this.counter = this.createCounter();
}
//计的数,自增长
this.counter.increment();
//基于rule规则进行选择
if (this.rule == null) {
return null;
} else {
try {
return this.rule.choose(key);
} catch (Exception var3) {
logger.warn("LoadBalancer [{}]: Error choosing server for key {}", new Object[]{this.name, key, var3});
return null;
}
}
}
三.使用属性自定义ribbon客户端
在application.yml中
HELLO-SERVICE: #服务名,注意要与大小写一致。(restTemplate.getForObject的url)
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #规则要写全限定名