zoukankan      html  css  js  c++  java
  • 一文详解:Spring Cloud Ribbon负载均衡

    今天的这篇文章来自蜗牛学院重庆校区刘颖聪老师。

    蜗牛学院资深导师,重庆邮电大学计算机专业学士学位,12年软件开发、管理及培训经验。精通开发和逆向编译技术。曾在天收网络技术有限公司担任逆向编译工程师,腾讯,盛大驱动保护项目合作。叁壹伍捌网络文化公司研发部项目经理,参与站群建设,SEO,反黑技术等工作。国内某IT培训机构资深项目经理,教学幽默风趣,注重案例与生活的结合,着重培养学员独立解决问题的思想及技术层次的扩展。

    ·  正  ·  文  ·  来  ·  啦  ·



    Spring Cloud是pivotal公司(Spring母公司)开源的一套微服务解决方案,也是当前最为流行的微服务落地解决方案。其中众多的组件主要是由国外知名视频点播公司NetFliex所贡献,这意味着,这些组件是经过生产环境考验,非常成熟。
    今天我们要谈到的Spring Cloud中的负载均衡组件Ribbon,也是由NetFliex贡献的久经沙场的成熟产品。但在开始之前,我们先来了解下负载均衡的概念。

     

    负载均衡

     

    负载均衡,英文名称为Load Balance,其含义就是指将工作任务(负载)进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。(引自百度百科)
    一种常见的负载均衡模式,是在执行工作任务的多台服务器前,加设一个负载均衡器。其结构如下:


     这里看到,从用户发送的三个请求ac被分别发送到服务器1,服务器2,服务器3。这样如果一台服务器的负载能力为100,那么三台服务器的负载能力就是300,有效提高了系统的整体负载。我们把这种模式称为集中式负载均衡。
    另一种模式则是将负载均衡的逻辑写在调用者的代码中。如下图


     同样的,a/b/c三个请求到达服务器1 时,服务器1中执行一段代码选出合适的服务器执行,最简单的情况下第1次选择了服务器4,第二次选择了服务器5,第三次选择了服务器6。同样也实现了负载均衡。这里没有用专门的负载均衡设备,而是使用代码逻辑实现,称为软负载,又称为进程内的负载均衡模式。
    上图中,我们将服务器1称为调用者,服务器4、5、6称为提供者。而我们今天的主角,Ribbon就是使用了后一种,进程内的负载均衡模式。它作为负载均衡组件,被加入调用者的代码逻辑中,负责选出合适的提供者服务来执行,进而实现负载均衡。

    负载均衡案例

     

    这里我们用一个例子来说明ribbon的作用。我们假设有一个电影网站movie,用户可以通过这个网站查看电影信息并且可以发表评论。这样我们开发了两个应用movie(电影网站)和review(评论服务),movie应用将会调用review服务来获取到某个电影的评论。为了提升负载能力,我们将review部署了三台服务器,最终的结构如下:显然,这里movie是调用者,review的三个服务是提供者,ribbon应该加入到movie中来选择具体调用哪个review服务。

    关于consul

     

    这里我们需要用到consul来作服务发现,或许你没有听过consul,但没关系,我们只需要启动它,其他的事情就可以不管了。
    下载合适你的版本的consul :https://www.consul.io/downloads.html
    解压后,在consul.exe 目录下执行 consul.exe agent -dev 启动consul。启动后,可以通过浏览器访问localhost:8500 查看consul的界面

    开发review

    接下来我们使用idea来开发spring-cloud应用 review。
    第一步,使用idea的spring initializar创建项目。选择如下review需要的依赖
    - spring-web-starter   用于使用SpringMVC开发web应用- spring-cloud-consul-discovery  用于consul服务发现- spring-boot-actuator  【可选】用于暴露应用健康状况
    具体操作见下图:


    第二步,接下来我们修改配置文件application.properties。#项目的名字,重要,spring.application.name=review# tomcat的端口,使用随机端口server.port=${random.int[8600,8900]}# 当前系统的注册到consul,可以被调用spring.cloud.consul.discovery.register=true server.port的配置我们使用了一个8600-8900之间的随机端口,以便于在本地部署多个review服务的时候,不会发生端口冲突。具体语法就是${random.int[开始数值,结束数值]

    第三步,我们来开发一个Web服务,暴露给movie项目调用。如果你有SpringMVC的开发经验,那么这一步也是易如反掌。

    稍加解释,@RestController意味着该Controller的所有方法都是返回Json对象的。


    我们定义了一个sayHello的方法处理请求路径为say的请求,返回的是一个从 Environment对象中获取到的本地端口路径(还记得我们的随机端口吗?这里就是返回它)。Environment是Spring Boot提供的一个对象,可以从中获取环境相关的信息。


    这样,Review就开发好了。不过问题来了,我们如何启动多个review的实例呢?大家回看我们的效果图,我们必须部署多个review实例才可以测试负载均衡。
    这就到了最后一步, spring boot的maven插件支持从命令行运行spring boot项目。具体操作是在review项目根目录下执行 mvn spring-boot:run 。但需要先启动consul,否则启动会失败。
    启动日志概略如下:

      

    多开几个命令行窗口,执行多次以上命令后,就实现了多个review实例。在consul上可以看到部署多个实例后的效果。下图是部署两个实例后的样子。

    开发Movie


    movie应用跟review最大区别在于,它是调用方。所以这边需要编写调用代码。
    第一步,仍然使用idea的spring initializar创建项目。选择如下movie需要的依赖:- spring-web-starter   用于使用SpringMVC开发web应用- spring-cloud-consul-discovery  用于consul服务发现- spring-cloud -netflix-ribbon  负载均衡组件ribbon
    大家一定留意到了今天的主角ribbon,ribbon将在movie项目中负责选择合适的review服务来执行调用。
    完整步骤如下图:


    第二步增加application.properties配置 # 这里是纯服务调用方,不需要向consul注册服务,但是可以调用服务spring.cloud.consul.discovery.register=false# 项目名称spring.application.name=movie 第三步编写代码。这里我们开发一个程序来调用并显示review的say服务。


    我们使用RestTemplate这个组件来请求review的服务。RestTemplate是Spring Web封装的一种请求Http服务的组件,简单好用。它可以自动发送请求、接受结果并自动封装返回结果为Java对象。
    首先我们在MovieApplication使用Java配置的方式声明一个RestTemplate的Spring Bean。并且将Ribbon加入到调用逻辑中。

    为了简单起见我们将配置写在MovieApplication中,@SpringBootApplication 注解本身是包含了@Configuration注解的,因此可以声明SpringBean。@Bean标记的方法返回值将会作为SpringBean处理,所以这里我们就声明了一个SpringBean。而@LoadBalanced注解则会启用Ribbon的功能,凡是通过这个RestTemplate实例调用的服务都会自动进行负载均衡。(对于Spring的Java配置风格不熟悉的可以参考这篇博文。)
    接下来,我们来编写调用的代码,与review相仿,仍然是SpringMVC风格。代码如下


    我们使用了restTemplate调用review服务。通常的Http请求是需要指定网页地址的,比如“https://www.baidu.com/s?wd=123”, 理论上我们应该填写review的地址,但是review并不是一个应用而是由三个相同实例组成的一个服务,我们的目标就是将请求均衡的分发给这三个实例。所以填写的地址就有讲究了,这里的地址填写的需要调用服务的名字,我们的开发review的时候配置了  spring.application.name 就是服务名了。根据目前配置,调用地址就是“http://review/say”了。这样,我们所有的开发工作都结束了。

    测试最终效果

    movie使用的是默认端口8080 ,所以当我们启动movie后,可以通过浏览器访问地址localhost:8080/show  就可以看见页面上显示一个端口,当你刷新端口就会改变,但当你刷新超过3次就会回到第1个端口,如此往复。
    背后的故事就是,我们访问movie,movie通过ribbon依次选择了review的三个实例中的一个来执行,所以端口各不相同。

    总结及思考

    Spring Cloud 选择了ribbon作为负载均衡器,实现方式是将ribbon加入到调用方的调用逻辑中。但为何要如此设计呢?


    回到微服务的实际场景,服务一定是非常多的,互相调用关系也非常复杂。那么就要求服务间的负载均衡应该是低成本、低消耗、透明化的,如果选用前文提到的集中式负载均衡,那么设置独立的负载均衡器成本会很高,消耗也会大,而且新部署的服务都需要配备新的负载均衡器。一方面运维成本倍增,另一方面增加了部署结构的复杂度,维护成本几何级增长。


    反之,通过良好的设计和编码,ribbon的使用成本几乎为0,仅仅在代码中加入@LoadBalanced注解,如果更进一步使用配套的Feign客户端则内置了ribbon,完全将负载均衡透明化了。ribbon本身只是一段代码逻辑,运行时消耗也非常少。低成本、低消耗、透明化,ribbon是微服务界,负载均衡的不二之选。 

  • 相关阅读:
    *Convert Sorted Array to Binary Search Tree
    *Count Complete Tree Nodes
    *Binary Tree Paths
    Invert Binary Tree
    *Kth Smallest Element in a BST
    **Lowest Common Ancestor of Two Nodes in a Binary Tree
    Lowest Common Ancestor of a Binary Search Tree
    *Sum root to leaf number
    subversion javahl
    mongodb从来没有说它写成功了。
  • 原文地址:https://www.cnblogs.com/woniuxy/p/11936866.html
Copyright © 2011-2022 走看看