当前位置:首页 > 技术分析 > 正文内容

「SpringCloud」(十二)OpenFeign+Ribbon实现负载均衡

ruisui883个月前 (02-03)技术分析25

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分支。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1180.html

标签: feign 使用
分享给朋友:

“「SpringCloud」(十二)OpenFeign+Ribbon实现负载均衡” 的相关文章

程序员开发必会之git常用命令,git配置、拉取、提交、分支管理

整理日常开发过程中经常使用的git命令![送心]git配置SSH刚进入项目开发中,我们首先需要配置git的config、配置SSH方式拉取代码,以后就免输入账号密码了!# 按顺序执行 git config --global user.name "自己的账号" git config -...

7 招教你轻松搭建以图搜图系统

作者 | 小龙责编 | 胡巍巍当您听到“以图搜图”时,是否首先想到了百度、Google 等搜索引擎的以图搜图功能呢?事实上,您完全可以搭建一个属于自己的以图搜图系统:自己建立图片库;自己选择一张图片到库中进行搜索,并得到与其相似的若干图片。Milvus 作为一款针对海量特征向量的相似性检索引擎,旨在...

一次Java内存占用高的排查案例,解释了我对内存问题的所有疑问

问题现象7月25号,我们一服务的内存占用较高,约13G,容器总内存16G,占用约85%,触发了内存报警(阈值85%),而我们是按容器内存60%(9.6G)的比例配置的JVM堆内存。看了下其它服务,同样的堆内存配置,它们内存占用约70%~79%,此服务比其它服务内存占用稍大。那为什么此服务内存占用稍大...

再来一波黑科技工具,低调使用

静读天下静读天下是一个特别优秀的电子书阅读器。它上面有多个在线书库,像古登堡计划,很多种优秀的书杂志,都可以下载来阅读。它还能智能识别章节功能,还支持外置的语音阅读功能。它支持多种文本格式,比如说txt,pdf,epub,mobi等等。为了便于阅读它还有10 种配色方式,还有夜间模式。不过免费版有广...

《暗黑破坏神 2:重制版》PC 版 2.3 版本发布,支持英伟达 DLSS

IT之家 12 月 3 日消息,暴雪为《暗黑破坏神 2:重制版》PC 版发布了更新 2.3 版本,添加了“离线难度缩放”滑块(玩家可以在单人游戏时增加挑战和奖励的级别)、多项辅助功能和用户界面改进,以及英伟达 DLSS 支持。玩法改进:玩家现在可以在离线游戏的选项菜单中使用“游戏难度等级”,它提供与...

JavaScript数组操作:掌握常用方法,提升开发效率

JavaScript数组操作:从增删改查到高级应用本文深入解析JavaScript中常用的数组方法,包括push、unshift、pop、shift、map、filter、reverse、at 和 slice。通过详细的例子和应用场景,帮助开发者快速掌握这些方法,提升代码效率和可读性。开篇点题作为J...