Spring Cloud Ribbon —— 客户端负载均衡

客户端负载均衡

负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。

  • 硬件负载均衡,eg:F5
  • 软件负载均衡,eg:Nginx

通过下挂一个可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按照某种算法(线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。

Ribbon通过使用@LoadBalanced注释修饰过的RestTemplate来实现接口调用。

RestTemplate

GET请求

getForObject()是对getForEntity()的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,返回包装好的对象内容。

  • getForObject(String url, Class responseType, Object... uriVariables)
public String getUserByName(String name) {
  return restTemplate.getForObject("http://USER-SERVICE/user?name={1}", String.class, "Huffam");
}
  • getForObject(String url, Class responseType, Map<String, ?> uriVariables)
public String getUserByName(String name) {
  Map<String, String> params = new HashMap<>();
  params.put("name", name);
  return restTemplate.getForObject("http://USER-SERVICE/user?name={1}", String.class, params);
}
  • getForObject(URI url, Class responseType)
public String getUserByName(String name) {
  UriComponents uriComponents = UriComponentsBuilder.fromUriString(
      "http://USER-SERVICE/user?name={1}")
      .build()
      .expand("Huffam")
      .encode();
  URI uri = uriComponents.toUri();
  return restTemplate.getForObject(uri, String.class);
}

POST请求

  • postForObject(String url, Object request, Class responseType, Object... uriVariables)
  • postForObject(String url, Object request, Class responseType, Map<String, ?> uriVariables)
  • postForObject(URI url, Object request, Class responseType)

PUT请求

  • put(String url, Object request, Object... uriVariables)
  • put(String url, Object request, Map<String, ?> uriVariables)
  • put(URI url, Object request)

DELETE请求

  • delete(String url, Object... uriVariables)
  • delete(String url, Map<String, ?> uriVariables)
  • delete(URI url)

源码分析

从@LoadBalanced注解源码的注释中,我们可以知道该注解用来给RestTemplate标记,以使用负载均衡的客户端(LoadBalancerClient)来配置它。

源码分析有篇文章总结的比较全,这里是传送门

负载均衡器

Ribbon的负载均衡,主要通过LoadBalancerClient来实现的,而LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等信息,并向EurekaClient获取注册列表的信息,默认10秒一次向EurekaClient发送“ping”,进而检查是否更新服务列表,最后,得到注册列表后,ILoadBalancer根据IRule的策略进行负载均衡。

负载均衡策略

RandomRule

通过rand.nextInde(serverCount)函数获取一个随机数,并将该随机数作为upList的索引值来返回具体实例。

RoundRobinRule

该策略实现了按照线性轮询的方式依次选择每个服务实例的功能。

RetryRule

该策略实现了一个具备重试机制的实例选择功能。其内部还定义了一个IRule对象,默认使用了RoundRobinRule实例。

WeightedResponseTimeRule

该策略是对RoundRobinRule的扩展,增加了根据实例的运行情况来计算权重,并根据权重来挑选实例,以达到更优的分配效果。

eg: 耗时情况
A: 10ms
B: 20ms
C: 30ms
weight = totalTime - time[i]
[0, 50], (51, 90], (91, 120]

ClientConfigEnabledRoundRobinRule

默认采用RoundRobinRule,我们一般不会直接使用这个策略,下面的高级策略都是基于这个策略实现的。

BestAvailableRule

选出当前并发最低的实例策略

PredicateBasedRule

这是一个抽象策略,这是一个基于Predicate实现的策略,Predicate是Google Guava Collection工具对集合进行过滤的条件接口。策略是先过滤清单,再轮询选择。而如何过滤需要在子类中实现apply方法来确定具体的过滤策略。以下两个策略是本策略的两种实现。

AvailabilityFilteringRule

该策略通过线性抽样的方式直接尝试寻找可用且较空闲的实例来使用,优化了父类每次都要遍历所有实例的开销。

ZoneAvoidanceRule

这是一个组合过滤条件,以ZoneAvoidancePredicate为主过滤条件,AvailabilityPredicate为次过滤条件。

重试策略

由于Spring Cloud Eureka实现的服务治理机制强调CAP原理中的AP,即可用性和可靠性,与Zookeeper这类强调CP(一致性、可靠性)的区别在于,Eureka为了实现更高的服务可用性,牺牲了一定的一致性。在极端情况下它宁愿接受故障实例也不丢掉“健康”实例(保护机制)。

从Camden SR2版本开始,Spring Cloud整合了Spring Retry来增强RestTemplate的重试能力。

spring.cloud.loadbalancer.retry.enabled=true

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000

hello-service.ribbon.ConnectTimeout=250
hello-service.ribbon.ReadTimeout=1000
hello-service.ribbon.OkToRetryOnAllOperations=true
hello-service.ribbon.MaxAutoRetriesNextServer=2
hello-service.ribbon.MaxAutoRetries=1

Reference
Spring Cloud源码分析(二)Ribbon
Ribbon源码解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容