微服务架构如何实现客户端负载均衡

 Spring Cloud Ribbon 是一一基于HTTP 和TCP 的客户端负载均衡工具,它基于NetflixRibbon实现。通过Spring Cloud 的封装,可以让我们轻松地将面向服务的REST 模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它儿乎存在于每一个SpringCloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过Ribbon 来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon 的理解和使用,对于我们使用Spring Cloud 来构建微服务非常重要。

在这里,我们将介绍如何使用Ribbon 来实现客户端的负载均衡,并且通过源码分析来了解Ribbon 实现客户端负载均衡的基本原理。

客户端负载均衡

负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间安装专门用于负载均衡的设备,比如F5 等; 而软件负载均衡则是通过在服务器上安装一些具有均衡负载功能或模块的软件来完成请求分发工作,比如Nginx 等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端负载均衡都能以架构方式构建起来:

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

而客户端负载均衡和服务端负我均衡最大的不同点在于上面所提到的服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心,比如Eureka 服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,只是这个步骤需要与服务注册中心配合完成。在Spring Cloud 实现的服务治理框架中,默认会创建针对各个服务治理框架的Ribbon 自动化整合配置,比如Eureka 中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAuto- Configurationo 在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。

通过SpringCloudRibbon 的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:

1.服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。

2. 服务消费者直接通过调用被@LoadBalanced 注解修饰过的RestTemplate来实现面向服务的接口调用。

  这样,我们就可以将服务提供者的高可用以及服务消费者的负载均衡调用一起实现了。  其中,我们使用了个非常有用的对象RestTemplate.该对象会使用Ribbon 的自动化配置,同时通过配置@LoadBalanced 还能够开启客户端负载均衡。之前我们演示了通过RestTemplate实现了最简单的服务访问,下面我们将详细介绍RestTemplate 针对几种不同请求类型和参数类型的服务调用实现。

  GET 请求

  在RestTemplate 中,对GET 请求可以通过如下两个方法进行调用实现。  第一种: getForEntity 函数。该方法返回的是ResponseEntity,该对象是Spring对HTTP 请求响应的封装,其中主要存储了HTTP 的几个重要元素,比如HTTP 请求状态马的枚举对象HttpStatus (也就是我们常说的404、500 这些错误码)、在它的父类ittpEntity中还存储着HTTP请求的头信息对象HttpHeaders 以及泛型类型的请求体时象。比如下面的例子,就是访问USER-SERVER服务的/user 请求,同时最后一个参数idi 会替换url 中的(1}占位符,而返回的ResponseEntity 对象中的body 内容类型:根据第二个参数转换为String类型。

    RestTemplate restTemplate 二newRestTemplate () ; 

   ResponseEntityStri xesponseEntity 一restTemplate.getFor ("http: //USER-RVICE/user?name={1}",string.class,"didi") ;  

String body= responseEntity.getBody () ;  

若我们希望返回的body是一个User对象类型,也可以这样实现: 

   Restremplate restTemplate= new Restremplate() ;  

  ResponseEntity responseEntity -restremplate.get "http: /USER-  vICE/user?name={1}",User.class,"didi") ;

  user body= responseEntity.getBody () ; 

 上面的例子是比较常用的方法

POST 请求

在RestTemplate 中,

对POST 请求时可以通过如下三个方法进行调用实现。

第一种: postEorEntity 函数。该方法同GET 请求中的getrorEntity 类似,会

在调用后返回ResponseEntity对象,其中T 为请求响应的body 类型。

比如下面这

个例子,使用postForEntity 提交POST请求到USER-SERVICE 服务的/user 接口,

提交的body 内容为user对象,请求响应返回的body 类型为String。

RestTemplate restTemplate= new RestTemplate () ;

User user = new User ("didi",30) ;

ResponseEntity responseEntity=

restTemplate.postForEntity ("http: //USER-SERVICE/user",user,String.class) ;

String body= responseEntity.getBody () ;

postForEntity 函数也实现了三种不同的重载方法。

PUT 请求

GResTemplate中,对PUT请求可以通过pot 方法进行调用实现,比如,    

   RestTemplaterestTemplate=new RestTemplate();

  Long id = 100011;

  User user=new User("didi",40);

  restemplate.put(http://USER-SERVICE/user/{1} ”,user,id ;

put 函数也实现了三种不同的重载方法:

1.put (string url,Object request,0bject...urlVariables)

2.put (Stringurl,Object request,Map urlVariables)

3.put (URI url,object request )

put函数为void类型,所以没有返回内容,也就没有其他函数定义的responserype参数,除此之外的其他传入参数定义与用法与postforobject基本一致。

DELETE 请求

在RestTemplate 中,对DELETE 请求可以通过delete 方法进行调用实现,比如:

RestTemplate restTemplate = new RestTemplate () ;

Long id = 10001L;restTemplate.delete ("http: //USER-SERVICE/user/ (1}",id) ;

delete 函数也实现了三种不同的重载方法:

1.delete (String url,0bject...urlVariables)

2.delete (String url,Map urlVariables)

3.delete (URi url)由于我们在进行REST请求时,通常都将DELETE 请求的唯一标识拼接在url 中,所DELETE 请求也不需要equest 的body信息,就如上面的三个函数实现一样,非常简单。1指定DELETE 请求的位置,urlVariables 绑定url 中的参数即可。

想学习更多更详细的知识的,在此我向大家推荐一个交流学习群:744642380 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

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

推荐阅读更多精彩内容