三废的日常--微服务的软负载Ribbon

二废:今天怎么还没下班呀?

小废:这不是在看微服务嘛,领导说我们要换架构,要适应互联网的“潮汐效应”,也不知道是不是跟风。

大废:不能这么讲,单从业务上来讲,微服务更容易横向扩展,也做到了关注点分离。

小废:那微服务多个服务之间是怎么做到负载均衡的呢?也是用Nginx嘛?

大废:当然不是,趁最近很热,正好蹭蹭空调,也给你们讲一讲 Ribbon,这个微服务的组件。

二废:别墨迹了,赶紧的,我还要回家带娃了。。

大废:。。。

大废:好了,我们先简单了解下如何会使用到Ribbon,Ribbon是Spring Cloud的一个微服务组件,主要负责的是客户端的软负载和服务调用。

小废:那和Nginx相比,有什么不同,它是怎么进行负载均衡的呢?

大废:不要心急嘛,Nginx是对外部请求做的负载均衡,客户端的所有请求都会交给Nginx,Ribbon更多的是对服务之间的调用做负载均衡。一个个请求被Ribbon代理后*,会通过拉取服务注册列表ServerList,根据负载均衡算法选择一个Server,发起请求,然后发送HTTP请求完成服务的调用。

大废:在微服务框架中,一般用Fegin来完成多个服务之间的调用,Fegin在Ribbon的基础上,进行了改进。采用接口的方式,只需要增加@FeginClient 即可,我们在@FeginCilent中是不用指定url,Fegin整合了Ribbon,具有了负载均衡能力,因此使用Fegin接口就默认用到了负载均衡。

小废:中秋节将至,祝大家中秋快乐。

(杭州旅行中)

总结:

Ribbon负载均衡的使用:

Ribbon可以通过使用@LoadBalanced注解来完成对RestTemplate请求的负载均衡。请求被Ribbon代理后会走如下流程:首先会被LoadBalancerInterceptor拦截,用于给RestTemplate做负载均衡。

@LoadBalanced注解定义如下所示

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}
可以看到这个注解被@Qualifier修饰,可以区分多个实现类。

Ribbon使用ServerList接口抽象服务实例列表,通过Eureka的服务发现,实现ServerList

Ribbon负载均衡的实现方式:

LoadBalancerClient 的实现类有一个 RibbonLoadBalancerClient,在实现类中有一个 choose 实现类。

public ServiceInstance choose(String serviceId, Object hint) {
Server server = this.getServer(this.getLoadBalancer(serviceId), hint);
return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
}
choose(serverid)内部调用getServer(ILoadBalancer loadBalancer, Object hint),getServer方法通过ILoadBalancer类进行了负载策均衡。

protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
}
接着通过实现ILoadBalancer接口的chooseServer(Object key)方法,实现类为BaseLoadBalancer。

protected IRule rule;

public Server chooseServer(Object key) {
if (this.counter == null) {
this.counter = this.createCounter();
}
this.counter.increment();
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;
}
}
}
通过IRule接口,自定义负载策略,总体来说,LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等,向EurekaClient获取注册列表信息,默认每10秒向EurekaClient发送一次“ping”,进而检查是否需要更新服务的注册列表信息。最后,在得到服务注册列表信息后,ILoadBalancer根据IRule的策略进行负载均衡。

你可能感兴趣的:(三废的日常--微服务的软负载Ribbon)