Ribbon是客户端的负载均衡器,消费者能够经过服务别名调用服务时,须要Ribbon作负载均衡来以某种机制访问实际的服务调用地址。java
简单类比,咱们去找Tony老师,通常理发店都会有多个Tony老师。可是也会有一个相似前台的工做人员为咱们安排有空的Tony老师理发。工做人员就是相似Ribbon,是按照顺序安排呢,仍是随机安排呢。算法
一样建立一个Ribbon的空模块,而后在Ribbon空模块下建立一个ribbon-consume9101
子模块。在父类也就是空模块的pom文件中加入依赖spring
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies>
当你引入了Eureka相关的依赖的时候其实就已经把Ribbon的依赖引入进来了,因此若是使用的是Ribbon + Eureka,能够不用写上面的依赖也能运行。服务器
建立完成后总体的项目结构如图所示app
application.yml
负载均衡
server: port: 9101 spring: application: name: ribbon-consume eureka: client: fetch-registry: true register-with-eureka: true service-url: defaultZone: http://localhost:8001/eureka/ instance: instance-id: ribbon-consume9101
注意咱们的服务的提供者是eureka-provide
服务,这个服务名字可能单取provide
更准确点,之后项目重构的时候可能会修改。dom
涉及到服务与服务之间的调用,通常会选择使用RestTemplate
,同时须要把它注入Spring容器中,因此选择使用配置类ide
@Configuration public class ApplicationContextConfig { @Bean @LoadBalanced //负载均衡须要的注解 public RestTemplate getRestTemplate() { return new RestTemplate(); } }
接下来就是主启动类测试
@SpringBootApplication @EnableEurekaClient @RestController public class RibbonConsume9101 { final String PROVIDE_URL = "http://eureka-provide"; RestTemplate restTemplate; public RibbonConsume9101(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/ribbon/consume") public String getInfo() { return "i am consumer, but actually invoke other service: [" + restTemplate.getForObject(PROVIDE_URL + "/eureka/provide", String.class) + "]"; } public static void main(String[] args) { SpringApplication.run(RibbonConsume9101.class, args); } }
EurekaServer8001
EurekaProvide7001
,EurekaProvide7002
, EurekaProvide7003
RibbonConsume9101
首先看下Eureka注册中心,能够看到3个服务提供者,1个消费者都已经注册到Eureka。fetch
接着消费端访问接口轮询,也是默认规则)。>http://localhost:9101/ribbon/...
上述调用服务的时候明显是轮询的方式,那若是想要其它方式去调用呢,这时候就须要自定义配置类。
Ribbon主要有6个组件
ServerList:
定义获取服务器列表ServerListFilter:
对ServerList列表进行二次过滤ServerListUpdater:
定义服务更新策略Iping:
检查服务列表是否存活IRlue:
根据算法选择调用服务列表中的某一个服务ILoadBalancer:
软件负载均衡器入口,整合以上全部的组件实现负载功能@Configuration public class RibbonCustomConfig { @Bean public IRule ribbonRule() { return new RandomRule(); } }
IRlue
接口就是以什么样的规则去调用服务提供者,能够看下该接口的实现类
怎么让这个配置文件被Ribbon感知到呢,就须要利用@RibbonClient
注解。创建一个空的注解类,加上注解和配置类就可以自定义Ribbon配置。
@Configuration @RibbonClient(name = "eureka-provide", configuration = RibbonCustomConfig.class) public class RibbonConfig { }
这里的名字就是咱们须要调用的服务端的配置文件中的springcloud.application.name
的值。须要注意的是,在官方文档里面有这样一段话
在这个例子中翻译过来就是RibbonCustomConfig
若是和主启动类在同一个包下,就会被扫描进Spring中,这样会致使配置文件会被全部的@RibbonClients
所共享。固然也能够用@ComponentScan
把配置文件排除在外。
重启RibbonConsume9101
服务,其它的不用动,一样调用消费端访问接口http://localhost:9101/ribbon/...
点的时候,啥,怎么一直调用的是7001端口,难道其它服务挂掉了,能够看到后面明显加快了点的速度,最后还好没有翻车,确实是改为了随机规则。
除了经过配置类来自定义Ribbon外,还能够经过配置文件来自定义
这里clientName
一样是须要调用的服务端的配置文件中的springcloud.application.name
的值。 若是是彻底本身写的类呢,须要实现对应的接口,这里一样采用Netflix写好的RandomRule
类。
把RibbonCustomConfig
和RibbonConfig
删掉或者所有注释掉均可以,修改配置文件
server: port: 9101 spring: application: name: ribbon-consume eureka: client: fetch-registry: true register-with-eureka: true service-url: defaultZone: http://localhost:8001/eureka/ instance: instance-id: ribbon-consume9101 #其实就是加了下面的内容 eureka-provide: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
其中eureka-provide
就是clientName。接着同样重启RibbonConsume9101
服务,其它的不用动,一样调用消费端访问接口http://localhost:9101/ribbon/...
值得注意的是,在配置文件中配置的变量是要比配置类中的优先级要高的。
上面是消费者端和服务端都注册进了Eureka,至关于消费者经过Eureka去找到了其它服务提供者的服务。那在真正业务中接受了新的消费者端,并无注册进Eureka,怎么解决这个问题呢?
先来看看没有注册进去会发生什么状况,想都不用想确定是直接报错了
一样在Ribbon父模块下面创建一个子模块
由于不用注册进Eureka,因此配置文件也要作相应的修改
server: port: 9102 spring: application: name: ribbon-consume-without-eureka #禁用掉Eureka,其实禁用不由用都不影响,由于根本就没导入 ribbon: eureka: enabled: false
一样须要导入RestTemplate
因此能够直接复制上一个子模块
@Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
主启动类也能够直接复制,不须要用到Eureka,去掉@EnableEurekaClient
注解并修改类名便可
@SpringBootApplication @RestController public class RibbonConsumeWithoutEureka9102 { final String PROVIDE_URL = "http://eureka-provide"; RestTemplate restTemplate; public RibbonConsumeWithoutEureka9102(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/ribbon/consume") public String getInfo() { return "i am consumer, but actually invoke other service: [" + restTemplate.getForObject(PROVIDE_URL + "/eureka/provide", String.class) + "]"; } public static void main(String[] args) { SpringApplication.run(RibbonConsumeWithoutEureka9102.class, args); } }
那怎样消费者调用的时候怎么知道去哪找提供者的服务呢,就须要动配置文件了
server: port: 9102 spring: application: name: ribbon-consume-without-eureka ribbon: eureka: enabled: false #如下为增长内容 eureka-provide: ribbon: listOfServers: localhost:7001, localhost:7002, localhost:7003
其中eureka-provide
就是须要调用的服务端的配置文件中的springcloud.application.name
的值
开启RibbonConsume9102
服务,其它的不用动,调用消费端访问接口http://localhost:9102/ribbon/... ,能够看到也是可以按照默认轮询的方式调用服务。
创做不易,若是对你有帮助,欢迎点赞,收藏和分享啦!
下面是我的公众号,有兴趣的能够关注一下,说不定就是你的宝藏公众号哦,基本2,3天1更技术文章!!!