网站首页 > 教程文章 正文
Ribbon是Netflix下的负载均衡项目,它主要实现中间层应用程序的负载均衡。为Ribbon配置服务提供者地址列表后,Ribbon就会基于某种负载均衡算法,自动帮助服务调用者去请求。Ribbon默认提供的负载均衡算法有多种,例如轮询、随机、加权轮训等,也可以为Ribbon实现自定义的负载均衡算法。
Ribbon有以下特性:
- 负载均衡器,可支持插拔式的负载均衡规则
- 对多种协议提供支持,如HTTP、TCP、UDP
- 集成了负载均衡功能的客户端
Feign利用Ribbon实现负载均衡的过程:
- 通过在启动类加@EnableFeignCleints注解开启FeignCleint
- 根据Feign的规则实现接口,并加在接口定义处添加@FeignCleint注解
- 服务启动后,扫描带有@ FeignCleint的注解的类,并将这些信息注入到ioc容器中
- 当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate
- RequesTemplate再生成Request
- Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
OpenFeign 中使用 Ribbon 进行负载均衡,所以 OpenFeign 直接内置了 Ribbon。在导入OpenFeign 依赖后,无需再专门导入 Ribbon 依赖。接下来,我们把gitegg-service-base作为服务的调用方,启动两个不同端口的gitegg-service-system作为服务的被调用方,测试Ribbon的负载均衡。
1、首先在gitegg-service-system工程中,新建被调用的controller方法,返回系统配置的端口号以区分是哪个服务被调用了。
package com.gitegg.service.system.controller;
import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.dto.SystemDTO;
import com.gitegg.service.system.service.ISystemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping(value = "system")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Api(tags = "gitegg-system")
@RefreshScope
public class SystemController {
private final ISystemService systemService;
@Value("${spring.datasource.maxActive}")
private String nacosMaxActiveType;
@Value("${server.port}")
private Integer serverPort;
@GetMapping(value = "list")
@ApiOperation(value = "system list接口")
public Object list() {
return systemService.list();
}
@GetMapping(value = "page")
@ApiOperation(value = "system page接口")
public Object page() {
return systemService.page();
}
@GetMapping(value = "exception")
@ApiOperation(value = "自定义异常及返回测试接口")
public Result<String> exception() {
return Result.data(systemService.exception());
}
@PostMapping(value = "valid")
@ApiOperation(value = "参数校验测试接口")
public Result<SystemDTO> valid(@Valid @RequestBody SystemDTO systemDTO) {
return Result.data(systemDTO);
}
@PostMapping(value = "nacos")
@ApiOperation(value = "Nacos读取配置文件测试接口")
public Result<String> nacos() {
return Result.data(nacosMaxActiveType);
}
@GetMapping(value = "api/by/id")
@ApiOperation(value = "Fegin Get调用测试接口")
public Result<Object> feginById(@RequestParam("id") String id) {
return Result.data(systemService.list());
}
@PostMapping(value = "api/by/dto")
@ApiOperation(value = "Fegin Post调用测试接口")
public Result<Object> feginByDto(@Valid @RequestBody SystemDTO systemDTO) {
return Result.data(systemDTO);
}
@GetMapping("/api/ribbon")
@ApiOperation(value = "Ribbon调用测试接口")
public Result<String> testRibbon() {
return Result.data("现在访问的服务端口是:" + serverPort);
}
}
2、在gitegg-service-system-api工程中,编写使用OpenFeign调用testRibbon的公共方法
package com.gitegg.service.system.api.feign;
import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.api.dto.ApiSystemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "gitegg-service-system")
public interface ISystemFeign {
/**
* OpenFeign测试Get
*
* @param id
* @return
*/
@GetMapping("/system/api/by/id")
Result<Object> querySystemById(@RequestParam("id") Long id);
/**
* OpenFeign测试Post
*
* @param apiSystemDTO
* @return ApiSystemDTO
*/
@PostMapping("/system/api/by/dto")
Result<ApiSystemDTO> querySystemByDto(@RequestBody ApiSystemDTO apiSystemDTO);
/**
* OpenFeign测试Ribbon负载均衡功能
* @return
*/
@GetMapping("/system/api/ribbon")
Result<String> testRibbon();
}
3、在gitegg-service-base中添加测试Ribbon负载均衡的Feign调用方法
package com.gitegg.service.base.controller;
import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.api.dto.ApiSystemDTO;
import com.gitegg.service.system.api.feign.ISystemFeign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping(value = "base")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Api(tags = "gitegg-base")
@RefreshScope
public class BaseController {
private final ISystemFeign systemFeign;
@GetMapping(value = "api/by/id")
@ApiOperation(value = "Fegin Get调用测试接口")
public Result<Object> feginById(@RequestParam("id") Long id) {
return Result.data(systemFeign.querySystemById(id));
}
@PostMapping(value = "api/by/dto")
@ApiOperation(value = "Fegin Post调用测试接口")
public Result<Object> feginByDto(@Valid @RequestBody ApiSystemDTO systemDTO) {
return Result.data(systemFeign.querySystemByDto(systemDTO));
}
@PostMapping(value = "api/ribbon")
@ApiOperation(value = "Ribbon调用测试接口")
public Result<Object> testRibbon() {
return Result.data(systemFeign.testRibbon());
}
}
4、先启动gitegg-service-base服务,再启动gitegg-service-system服务,服务启动成功之后,将gitegg-service-system下bootstrap.yml里面server.port改为8011,然后再点击启动,这样就启动了两个gitegg-service-system服务(如果运行两个服务时提示:gitegg-service-system is not allowed to run in parallel. Would you like to stop the running one?,这时,在IDEA中点击Run-Edit configurations-勾选Allow parallel run即可),服务全部启动完毕之后,可以在Console窗口里面看到三个服务的Console
三个服务:
5、打开浏览器访问:
http://127.0.0.1:8001/doc.html,点击Ribbon调用测试接口菜单,进行测试,点击请求,我们可以看到每次返回的端口都是变化的,8001端口和8011端口轮流出现,因为Ribbon负载均衡默认是使用的轮询策略
6、如果我们需要修改负载均衡策略或者自定义负载均衡策略,根据我们的架构设计,我们在GitEgg-Platform的子工程gitegg-platform-cloud中设置公共的负载均衡策略,然后每个微服务需要不同的策略的话,可以在自己的工程中添加配置文件。接下来,在gitegg-platform-cloud中新建Ribbon配置类
package com.gitegg.platform.cloud.ribbon.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Ribbon公共负载均衡策略配置
*/
@Configuration
public class RibbonConfig {
/**
* 负载均衡策略配置
* @return
*/
@Bean
public IRule rule(){
//随机策略 从所有可用的提供者中随机选择一个
return new RandomRule();
}
}
7、修改完成之后,GitEgg_Platform工程重新执行install,GitEgg_Cloud刷新导入的包,参照步骤5再执行测试,这时我们发现微服务返回的端口,不再是有规律的切换,而是随机不确定的出现。
注意:
这里RibbonConfig只用于测试负载均衡策略,请不要在生产环境中这样使用,否则会出现问题:在微服务A中调用微服务B和微服务C,然后再调用微服务B,这是RibbonLoadBalancerClient在获取微服务时,渠到的serviceId为null,就会获取到上次的微服务,进而导致404错误。因为OpenFeign默认使用的是Ribbon提供的负载均衡策略,我们在实际应用中可以选择Nacos提供的NacosRule策略,利用Nacos权重进行负载均衡:
#负载均衡策略
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
源码在
https://gitee.com/wmz1930/GitEgg的chapter-12分支。
猜你喜欢
- 2025-09-11 Spring Boot3 中 RESTful 接口调用全解析:从阻塞到响应式的实战指南
- 2025-09-11 springcloud实战:服务间通信OpenFeign熔断
- 2025-09-11 项目终于用上了动态Feign,真香!_feign动态服务名
- 2025-09-11 RestTemplate和Feign的区别_feign和httpclient的区别
- 2025-09-11 OpenFeign:让你的Java代码像本地调用一样简单
- 2025-09-11 【完结14章】SpringCloud+Netty集群实战千万级 IM系统
- 2025-09-11 Eureka服务发现框架和微服务调用组件Feign
- 2025-09-11 Spring Cloud OpenFeign - 远程调用
- 2025-09-11 微服务 - 服务接口调用 OpenFeign
- 2025-09-11 Sentinel 限流详解-Sentinel与OpenFeign服务熔断那些事
- 最近发表
-
- K8s 部署频繁出错?一套流程教你快速定位故障,工作效率翻倍
- 防火墙服务无法启用,显示灰色的解决办法
- 网络问题-电脑无法上网处理思路以及办法 (总集)
- Win10学院:Windows Denfender无法启动怎么办?
- Windows账户登录问题解决方案_登录windows账户什么意思
- IIS无法启动提示计算机上"."的服务W3SVC,一分钟搞定,抓紧收藏
- 已申请到免费顶级域名如何管理_顶级域名免费注册
- 网站被劫持了老是跳转怎么办_网站被劫持到其它网站如何解决
- 这些“常用药”被注销!涉及维生素、去痛片、眼药水等!快看看你家有吗?
- 《皕宋楼藏书志》清 藏书家陆心源与其门人李宗莲合编的藏书目录
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)