当前位置: 首页 > 后端技术 > Java

SpringCloud微服务实战——搭建企业级开发框架(十二):OpenFeign+Ribbon实现负载均衡

时间:2023-04-01 19:25:15 Java

Ribbon是Netflix旗下的一个负载均衡项目,主要实现中间层应用的负载均衡。为Ribbon配置服务提供者地址列表后,Ribbon会根据一定的负载均衡算法自动帮助服务调用者请求。Ribbon默认提供了多种负载均衡算法,如roundrobin、random、weightedroundrobin等,你也可以为Ribbon实现自定义的负载均衡算法。Ribbon具有以下特点:负载均衡器,可以支持可插拔的负载均衡规则,提供对HTTP、TCP、UDP等多种协议的支持。集成负载均衡功能的客户端Feign使用Ribbon实现负载均衡过程:通过在启动类中添加@EnableFeignCleints注解使FeignCleint能够按照Feign规则实现接口,在接口定义中添加@FeignCleint注解。服务启动后,扫描带有@FeignCleint注解的类,将信息注入到ioc容器中作为接口方法调用,通过jdkRequesTemplate的代理生成具体的RequestTemplate,然后生成RequestRequest交给客户端进行处理。客户端可以是HttpUrlConnection、HttpClient或Okhttp。最后将Client封装到LoadBalanceClient类中。该类结合Ribbon类实现负载均衡。OpenFeign使用Ribbon做负载均衡,所以OpenFeign直接内置了Ribbon。引入OpenFeign依赖后,就不需要再专门引入Ribbon依赖了。接下来,我们以gitegg-service-base作为服务的调用者,启动两个不同端口的gitegg-service-system作为服务的被调用者,测试Ribbon的负载均衡。1、首先在gitegg-service-system项目中,新建一个调用的controller方法,返回系统配置的端口号,以区分调用了哪个服务。包com.gitegg.service.system.controller;导入com.gitegg.platform.boot.common.base.Result;导入com.gitegg.service.system.dto.SystemDTO;导入com.gitegg.service.system.service。ISystemService;导入io.swagger.annotations.Api;导入io.swagger.annotations.ApiOperation;导入lombok.RequiredArgsConstructor;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework.beans.factory.annotation.Value;导入org.springframework.cloud.context.config.annotation.RefreshScope;导入org.springframework.web.bind.annotation.*;导入javax.validation.Valid;@RestController@RequestMapping(value="system")@RequiredArgsConstructor(onConstructor_=@Autowired)@Api(tags="gitegg-system")@RefreshScopepublicclassSystemController{privatefinalISystemServicesystemService;@Value("${spring.datasource.maxActive}")privateStringnacosMaxActiveType;@Value("${server.port}")privateIntegerserverPort;@GetMapping(value="list")@ApiOperation(value="systemlistinterface")publicObjectlist(){returnsystemService.list();}@GetMapping(value="page")@ApiOperation(value="systempageInterface")publicObjectpage(){returnsystemService.page();}@GetMapping(value="exception")@ApiOperation(value="自定义异常并返回测试接口")publicResultexception(){returnResult.data(systemService.exception());}@PostMapping(value="valid")@ApiOperation(value="参数验证测试接口")publicResultvalid(@Valid@RequestBodySystemDTOsystemDTO){returnResult.data(systemDTO);}@PostMapping(value="nacos")@ApiOperation(value="Nacos读取配置文件测试接口")publicResultnacos(){returnResult.data(nacosMaxActiveType);}@GetMapping(value="api/by/id")@ApiOperation(value="FeginGet调用测试接口")publicResultfeginById(@RequestParam("id")stringid){returnResult.data(systemService.list());}@PostMapping(value="api/by/dto")@ApiOperation(value="FeginPostcalltestinterface")publicResultfeginByDto(@Valid@RequestBodySystemDTOsystemDTO){returnResult.data(systemDTO);}}@GetMapping("/api/ribbon")@ApiOperation(value="Ribbon调用测试接口")publicResulttestRibbon(){returnResult.data("现在要访问的服务端口是:"+服务器端口);}}2.在gitegg-service-system-api项目中,编写使用OpenFeign调用testRibbon的公共方法包com.gitegg.service.system.api。伪装;导入com.gitegg.platform.boot.common.base.Result;导入com.gitegg.service.system.api.dto.ApiSystemDTO;导入org.springframework.cloud.openfeign.FeignClient;导入org.springframework.web。bind.annotation.GetMapping;导入org.springframework.web.bind.annotation.PostMapping;导入org.springframework.web.bind.annotation.RequestBody;导入org.springframework.web.bind.annotation.RequestParam;@FeignClient(name="gitegg-service-system")publicinterfaceISystemFeign{/***OpenFeign测试Get**@paramid*@return*/@GetMapping("/system/api/by/id")ResultquerySystemById(@RequestParam("id")长id);/***OpenFeign测试Post**@paramapiSystemDTO*@returnApiSystemDTO*/@PostMapping("/system/api/by/dto")ResultquerySystemByDto(@RequestBodyApiSystemDTOapiSystemDTO);/***OpenFeign测试Ribbon负载均衡函数*@return*/@GetMapping("/system/api/ribbon")ResulttestRibbon();}3.在gitgg-service中添加测试Ribbon负载的Feign调用方法平衡基础包com.gitegg.service.base.controller;导入com.gitegg.platform.boot.common.base.Result;导入com.gitegg.service.system.api.dto.ApiSystemDTO;导入com.gitegg。service.system.api.feign.ISystemFeign;导入io.swagger.annotations.Api;导入io.swagger.annotations.ApiOperation;导入lombok.RequiredArgsConstructor;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework.cloud.context.config.annotation.RefreshScope;导入org.springframework.web.bind.annotation.*;导入javax.validation.Valid;@RestController@RequestMapping(value="base")@RequiredArgsConstructor(onConstructor_=@Autowired)@Api(tags="gitegg-base")@RefreshScopepublicclassBaseController{privatefinalISystemFeignsystemFeign;@GetMapping(value="api/by/id")@ApiOperation(value="FeginGet调用测试接口")publicResultfeginById(@RequestParam("id")Longid){returnResult.data(systemFeign.querySystemById(id));}@PostMapping(value="api/by/dto")@ApiOperation(value="FeginPost调试测试接口")publicResultfeginByDto(@Valid@RequestBodyApiSystemDTOsystemDTO){returnResult.data(systemFeign.querySystemByDto)(系统DTO));}@PostMapping(value="api/ribbon")@ApiOperation(value="Ribbon调用测试接口")publicResulttestRibbon(){returnResult.data(systemFeign.testRibbon());}}4.先启动gitegg-service-base服务,再启动gitegg-service-system服务,服务启动成功后,将gitegg-service-system下的bootstrap.yml中的server.port改为8011,然后点击启动,这样就启动了两个gitegg-service-system服务(如果两个服务都在运行,提示:gitegg-service-systemisnotallowedtoruninparallel.Wouldyouliketostoptherunningone?,此时在IDEA中点击Run-Editconfigurations-勾选Allowparallelrun),所有服务启动后,你可以点击Console窗口,可以看到三个服务的Console的三个服务:5.打开浏览器访问:http://127.0.0.1:8001/doc.html,点击Ribbon调用测试界面菜单,测试,点击Request,我们可以看到每次返回的端口都在变化,有时是8001,有时是8011,因为Ribbon负载均衡默认采用的是轮询策略。6、如果我们需要修改负载均衡策略或者自定义负载均衡策略,根据我们的架构设计,我们在GitEgg-Platform的子项目gitegg-platform-cloud中设置公共负载均衡策略,然后如果每个微服务需要不同的策略,可以在自己的项目中添加配置文件接下来在gitegg-platform-cloudpackagecom.gitegg.platform.cloud.ribbon.config;importcom.netflix.loadbalancer.IRule;importcom.netflix.loadbalancer.RandomRule;importorg.springframework中创建一个Ribbon配置类。context.annotation.Bean;importorg.springframework.context.annotation.Configuration;/***@DescriptionRibbon公共负载均衡策略配置*/@ConfigurationpublicclassRibbonConfig{/***负载均衡策略配置*@return*/@BeanpublicIRulerule(){//随机策略从所有可用的提供者中随机选择一个随机策略returnnewRandomRule();}}7.修改完成后,GitEgg_Platform项目重新执行安装,GitEgg_Cloud刷新导入的包,参考步骤5然后执行测试,此时我们发现微服务返回的端口不再是一个常规开关,但随机且不确定地出现。注意:这里RibbonConfig只是用来测试负载均衡策略,请不要在生产环境中使用,否则会出现问题:在微服务A中调用微服务B和微服务C,再调用微服务B,这是RibbonLoadBalancerClient时获取微服务,如果serviceId为null,会获取最后一个微服务,导致404错误。由于OpenFeign默认使用Ribbon提供的负载均衡策略,我们在实际应用中可以选择Nacos提供的NacosRule策略,使用Nacos权重进行负载均衡:#loadbalancingstrategyNFLoadBalancerRuleClassName:com.alibaba.cloud.nacos.ribbon。NacosRule本文源码在https://gitee.com/wmz1930/GitEgg的chapter-12分支。