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

升级最新版SpringCloud后,一个重要组件被弃用了!

时间:2023-04-01 18:17:47 Java

前不久,我全面升级了商城微服务的版本。通过Gateway调用其他服务时,出现ServiceUnavailable的问题。在排查原因的时候,发现作为负载均衡组件的Ribbon已经被废弃了。Ribbon作为Netflix的开源组件,目前已经进入维护状态。现在推荐使用Loadbalancer。今天我们就来说说Loadbalancer的使用!SpringCloud实战电商项目mall-swarm(8.8k+star)地址:https://github.com/macrozheng/mall-swarmLoadBalancer简介LoadBalancer是SpringCloud官方提供的一个负载均衡组件,可以用来替换丝带。它的用法基本兼容Ribbon,可以从Ribbon平滑过渡。下面使用介绍LoadBalancer的基本使用。我们将以Nacos作为注册中心,通过nacos-loadbalancer-service和nacos-user-service这两个服务的相互调用来进行演示。负载均衡我们将使用RestTemplate来演示LoadBalancer的负载均衡功能。首先在nacos-loadbalancer-service模块的pom.xml文件中添加LoadBalancer相关依赖;org.springframework.cloudspring-cloud-starter-loadbalancer然后创建Java配置类来配置RestTemplate,并使用@LoadBalanced注解赋予其负载平衡能力;/***RestTemplate相关配置*宏创建于2019/8/29。*/@ConfigurationpublicclassRestTemplateConfig{@Bean@ConfigurationProperties(prefix="rest.template.config")publicHttpComponentsClientHttpRequestFactorycustomHttpRequestFactory(){返回新的HttpComponentsClientHttpRequestFactory();}@Bean@LoadBalancedpublicRestTemplaterestTemplate(){返回新的RestTemplate(customHttpRequestFactory());}}在application中可以使用.yml中的自定义配置来配置RestTemplate的调用超时时间;rest:template:config:#RestTemplate调用超时配置connectTimeout:5000readTimeout:5000然后在Controller中使用RestTemplate进行远程调用;/***由201上的宏创建9/8/29。*/@RestController@RequestMapping("/user")publicclassUserLoadBalancerController{@AutowiredprivateRestTemplaterestTemplate;@Value("${service-url.nacos-user-service}")privateStringuserServiceUrl;@GetMapping("/{id}")publicCommonResultgetUser(@PathVariableLongid){returnrestTemplate.getForObject(userServiceUrl+"/user/{1}",CommonResult.class,id);}@GetMapping("/getByUsername")publicCommonResultgetByUsername(@RequestParamStringusername){returnrestTemplate.getForObject(userServiceUrl+"/user/getByUsername?username={1}",CommonResult.class,username);}@GetMapping("/getEntityByUsername")publicCommonResultgetEntityByUsername(@RequestParamStringusername){ResponseEntityentity=restTemplate.getForEntity(userServiceUrl+"/user/getByUsername?username={1}",CommonResult.class,用户名);如果(entity.getStatusCode().is2xxSuccessful()){returnentity.getBody();}else{returnnewCommonResult("操作失败",500);}}@PostMapping("/create")publicCommonResultcreate(@RequestBodyUseruser){returnrestTemplate.postForObject(userServiceUrl+"/user/create",user,CommonResult.class);}@PostMapping("/update")publicCommonResultupdate(@RequestBodyUseruser){returnrestTemplate.postForObject(userServiceUrl+"/user/update",user,CommonResult.class);}@PostMapping("/delete/{id}")publicCommonResultdelete(@PathVariableLongid){returnrestTemplate.postForObject(userServiceUrl+"/user/delete/{1}",null,CommonResult.class,id);}}我们在nacos-user-service中实现了这些接口,可以提供给nacos-loadbalancer-service进行远程调用;然后启动一个nacos-loadbalancer-service,和两个nacos-user-service,此时Nacos中会显示以下服务;此时通过nacos-loadbalancer-service调用接口测试,会发现两个nacos-user-services交替打印日志信息,采用轮询策略,访问地址:http://localhost:8308/user/1声明式服务调用当然,LoadBalancer除了使用RestTemplate进行远程调用外,还可以使用OpenFeign进行声明式服务调用。下面就来介绍一下。首先在nacos-loadbalancer-service模块的pom.xml文件中添加OpenFeign相关依赖;org.springframework.cloudspring-cloud-starter-openfeign然后在OpenFeign客户端接口中声明要调用的服务接口和调用方法;/***宏创建于2019/9/5。*/@FeignClient(value="nacos-user-service")publicinterfaceUserService{@PostMapping("/user/create")CommonResultcreate(@RequestBodyUseruser);@GetMapping("/user/{id}")CommonResultgetUser(@PathVariableLongid);@GetMapping("/user/getByUsername")CommonResultgetByUsername(@RequestParamStringusername);@PostMapping("/user/update")CommonResultupdate(@RequestBodyUser用户);@PostMapping("/user/delete/{id}")CommonResultdelete(@PathVariableLongid);}然后在Controller中使用OpenFeign客户端接口调用远程服务;/***宏创建于2019/8/29。*/@关于stController@RequestMapping("/userFeign")公共类UserFeignController{@AutowiredprivateUserServiceuserService;@GetMapping("/{id}")publicCommonResultgetUser(@PathVariableLongid){returnuserService.getUser(id);}@GetMapping("/getByUsername")publicCommonResultgetByUsername(@RequestParamStringusername){returnuserService.getByUsername(username);}@PostMapping("/create")publicCommonResultcreate(@RequestBodyUseruser){returnuserService.create(user);}@PostMapping("/update")publicCommonResultupdate(@RequestBodyUseruser){returnuserService.update(user);}@PostMapping("/delete/{id}")publicCommonResultdelete(@PathVariableLongid){returnuserService.delete(id);}}如果想设置OpenFeign的超时配置,可以在application.yml中添加如下内容;feign:client:config:default:#Feign调用超时配置connectTimeout:5000readTimeout:5000接下来通过测试接口调用远程服务,发现可以正常调用。访问地址:http://localhost:8308/userFei...服务实例缓存LoadBalancer为了提高性能,不会每次请求都使用,而是获取实例列表,缓存服务实例列表本地。默认缓存时间为35s。为了减少服务不可用时会被选中的可能性,我们可以进行如下配置。spring:cloud:loadbalancer:cache:#负载均衡缓存配置enabled:true#开启缓存ttl:5s#设置缓存时间capacity:256#设置缓存大小HTTP请求转换如果想在每次远程调用中传入一个自定义的For请求头,可以试试LoadBalancerRequestTransformer,通过LoadBalancerRequestTransformer可以对原请求进行一定程度的改造。首先,我们需要配置LoadBalancerRequestTransformer的Bean实例。这里我们把ServiceInstance的instanceId放到请求头X-InstanceId中;/***LoadBalancer相关配置*宏创建于2022/7/26。*/@ConfigurationpublicclassLoadBalancerConfig{@BeanpublicLoadBalancerRequestTransformertransformer(){returnnewLoadBalancerRequestTransformer(){@OverridepublicHttpRequesttransformRequest(HttpRequestrequest,ServiceInstanceinstance){返回新的HttpRequestWrapper(request){@OverridepublicHttpHeadersgetHeaders(){HttpHeadersheaders=newHttpHeaders();headers.putAll(super.getHeaders());headers.add("X-InstanceId",instance.getInstanceId());返回标题;}};}};}}然后修改nacos-user-service中的代码,打印获取到的请求头X-InstanceId信息;/***创建通过macro于2019/8/29。*/@RestController@RequestMapping("/user")公共类UserController{@GetMapping("/{id}")publicCommonResultgetUser(@PathVariableLongid){Useruser=userService.getUser(id);LOGGER.info("根据id获取用户信息,用户名为:{}",user.getUsername());ServletRequestAttributesservletRequestAttributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequest请求=servletRequestAttributes.getRequest();StringinstanceId=request.getHeader("X-InstanceId");if(StrUtil.isNotEmpty(instanceId)){LOGGER.info("获取自定义请求头:X-InstanceId={}",instanceId);}返回新的CommonResult<>(用户);}}接下来访问接口进行测试。nacos-user-service控制台会打印如下日志,发现自定义请求头已经成功通过。访问地址:http://localhost:8308/user/12022-07-2615:05:19.920INFO14344---[nio-8206-exec-5]c.macro.cloud.controller.UserController:根据id获取用户信息,用户名为:macro2022-07-2615:05:19.921INFO14344---[nio-8206-exec-5]c.macro.cloud.controller.UserController:获取自定义请求头:X-InstanceId=192.168.3.227#8206#DEFAULT#DEFAULT_GROUP@@nacos-user-service总结通过今天在LoadBalancer上的一波实践,我们可以发现使用LoadBalancer和Ribbon的区别其实不大,主要是一些配置是一样的。如果之前用过Ribbon,基本上可以无缝切换到LoadBalancer。参考官方文档:https://docs.spring.io/spring...项目源码地址https://github.com/macrozheng...