OpenFeign、RestTemplate支持自定义服务地址列表

2024-04-26 15:52

本文主要是介绍OpenFeign、RestTemplate支持自定义服务地址列表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • 一、背景
    • 二、解决思路
    • 三、定义通用配置
    • 四、定义通用StaticServiceInstanceListSuppler
    • 五、为指定serviceId定义专属的配置类
    • 六、通过@LoadBalancerClient为指定serviceId设置配置类
      • 6.1 OpenFeign
      • 6.2 RestTemplate
    • 七、Debug调试

一、背景

最近在支援项目时,项目组需要将后端服务部署为多个实例,且没有集成服务注册中心、反向代理、K8S等,如此提出需要客户端OpenFeign、RestTemplate等支持手动配置服务端地址列表,并支持在服务端实例间负载均衡,经过调研后给出如下基于Spring Cloud LoadBalancer的集成方案。

二、解决思路

OpenFeign、RestTemplate均是通过url对服务发起调用,具体url的负载均衡则是由Spring Cloud LoadBalancer负责,所以需要在LoadBalancer上做文章,查询相关文档后给出如下思路:

  • 通过@LoadBalancerClient(name, configuration)注解为不同服务标识指定相应的配置类
    • 服务标识 对应@FeignClient.name,或 RestTemplate调用url http://serviceId/path中的serviceId
  • 然后在相应的配置类中注册自定义的ServiceInstanceListSupplier
  • 最后在自定义的ServiceInstanceListSupplier中返回该服务标识手动配置的服务端地址列表

接下来给出核心实现代码。

三、定义通用配置

首先,自定义配置属性如下:

import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 负载均衡静态配置** @author luohq* @date 2024-04-25 9:35*/
@ConfigurationProperties(prefix = LoadBalancerStaticProps.PREFIX)
public class LoadBalancerStaticProps {public static final String PREFIX = "spring.cloud.loadbalancer.clients";/*** 客户端ServiceId到静态地址列表的映射*/private Map<String, List<String>> staticUris = new HashMap<>();public Map<String, List<String>> getStaticUris() {return staticUris;}public void setStaticUris(Map<String, List<String>> staticUris) {this.staticUris = staticUris;}@Overridepublic String toString() {return "LoadBalancerStaticProps{" +"staticUris=" + staticUris +'}';}
}

后续可通过如下示例配置,手动指定不同服务标识对应的服务端地址列表:

spring:cloud:loadbalancer:clients:# 配置负载均衡静态地址static-uris:# app-rbac服务的静态地址列表app-rbac:- http://localhost:8081- http://localhost:8082# app-atom服务的静态地址列表app-atom:- http://localhost:9081- http://localhost:9082

四、定义通用StaticServiceInstanceListSuppler

StaticServiceInstanceListSuppler实现了ServiceInstanceListSupplier接口,
这个接口是Spring Cloud LoadBalancer的一部分,是一个通用的客户端负载均衡器。
StaticServiceInstanceListSuppler支持自定义serviceId对应的服务地址列表serviceStaticUriList,
同时提供create方法,支持从前文定义的配置属性LoadBalancerStaticProps 中(即从配置文件中)获取serviceId对应的服务地址列表。

import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;import java.net.URI;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;/*** 静态服务地址提供器** @author luohq* @date 2024-04-25*/
public class StaticServiceInstanceListSuppler implements ServiceInstanceListSupplier {/*** 服务标识*/private final String serviceId;/*** 服务地址列表*/private final List<String> serviceStaticUriList;public StaticServiceInstanceListSuppler(String serviceId, List<String> serviceStaticUriList) {Assert.notNull(serviceId, "serviceId may not be null");Assert.notEmpty(serviceStaticUriList, "serviceStaticUriList may not be null");this.serviceId = serviceId;this.serviceStaticUriList = serviceStaticUriList;}@Overridepublic String getServiceId() {return serviceId;}@Overridepublic Flux<List<ServiceInstance>> get() {List<ServiceInstance> defaultServiceInstanceList = IntStream.range(0, serviceStaticUriList.size()).mapToObj(i -> {DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();defaultServiceInstance.setServiceId(this.serviceId);defaultServiceInstance.setInstanceId(this.serviceId + i);defaultServiceInstance.setUri(URI.create(serviceStaticUriList.get(i)));return defaultServiceInstance;}).collect(Collectors.toList());return Flux.just(defaultServiceInstanceList);}public static StaticServiceInstanceListSuppler create(String serviceId, LoadBalancerStaticProps loadBalancerStaticProps) {return new StaticServiceInstanceListSuppler(serviceId, loadBalancerStaticProps.getStaticUris().get(serviceId));}
}

五、为指定serviceId定义专属的配置类

如下实现即对应serviceId=app-rbac服务的专属配置类,
不同的serviceId可再单独定义相应的配置类。

import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
/*** RBAC客户端负载均衡静态配置** @author luohq* @date 2024-04-25 9:35*/
public class RbacClientLoadBalancerStaticConfiguration {public static final String SERVICE_ID = "app-rbac";@Bean@Primarypublic ServiceInstanceListSupplier serviceInstanceListSupplier(LoadBalancerStaticProps loadBalancerStaticProps) {return StaticServiceInstanceListSuppler.create(SERVICE_ID, loadBalancerStaticProps);}
}

六、通过@LoadBalancerClient为指定serviceId设置配置类

6.1 OpenFeign

如果项目中使用的是OpenFeign,以下配置已足够:

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Configuration;/*** RBAC客户端负载均衡静态配置** @author luohq* @date 2024-04-25 9:35*/
@Configuration
@LoadBalancerClients({//自定义RBAC服务配置@LoadBalancerClient(name = RbacClientLoadBalancerStaticConfiguration.SERVICE_ID,configuration = RbacClientLoadBalancerStaticConfiguration.class)
})
@EnableConfigurationProperties({LoadBalancerStaticProps.class})
public class LoadBalancerStaticConfiguration2 {}

6.2 RestTemplate

如果项目中使用的是RestTemplate,那么还需要通过@LoadBalanced注解设置RestTemplate支持负载均衡,
具体配置代码如下:

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;/*** RBAC客户端负载均衡静态配置** @author luohq* @date 2024-04-25 9:35*/
@Configuration
@LoadBalancerClients({//自定义RBAC服务配置@LoadBalancerClient(name = RbacClientLoadBalancerStaticConfiguration.SERVICE_ID,configuration = RbacClientLoadBalancerStaticConfiguration.class)
})
@EnableConfigurationProperties({LoadBalancerStaticProps.class})
public class LoadBalancerStaticConfiguration2 {/*** 通过@LoadBalanced注解开启RestTemplate负载均衡能力*/@LoadBalanced@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

七、Debug调试

Spring Cloud LoadBalancer默认使用的是RoundRobinLoadBalancer,可重点关注RoundRobinLoadBalancer中获取服务实例的代码。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


参考:
https://spring.io/guides/gs/spring-cloud-loadbalancer
https://juejin.cn/post/7266315019294490661
https://docs.spring.io/spring-cloud-commons/docs/3.1.8/reference/html/#spring-cloud-loadbalancer

这篇关于OpenFeign、RestTemplate支持自定义服务地址列表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/937999

相关文章

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3