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

相关文章

公共筛选组件(二次封装antd)支持代码提示

如果项目是基于antd组件库为基础搭建,可使用此公共筛选组件 使用到的库 npm i antdnpm i lodash-esnpm i @types/lodash-es -D /components/CommonSearch index.tsx import React from 'react';import { Button, Card, Form } from 'antd'

(超详细)YOLOV7改进-Soft-NMS(支持多种IoU变种选择)

1.在until/general.py文件最后加上下面代码 2.在general.py里面找到这代码,修改这两个地方 3.之后直接运行即可

通过高德api查询所有店铺地址信息

通过高德api查询所有店铺地址电话信息 需求:通过高德api查询所有店铺地址信息需求分析具体实现1、申请高德appkey2、下载types city 字典值3、具体代码调用 需求:通过高德api查询所有店铺地址信息 需求分析 查询现有高德api发现现有接口关键字搜索API服务地址: https://developer.amap.com/api/webservice/gui

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

springboot家政服务管理平台 LW +PPT+源码+讲解

3系统的可行性研究及需求分析 3.1可行性研究 3.1.1技术可行性分析 经过大学四年的学习,已经掌握了JAVA、Mysql数据库等方面的编程技巧和方法,对于这些技术该有的软硬件配置也是齐全的,能够满足开发的需要。 本家政服务管理平台采用的是Mysql作为数据库,可以绝对地保证用户数据的安全;可以与Mysql数据库进行无缝连接。 所以,家政服务管理平台在技术上是可以实施的。 3.1

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

时间服务器中,适用于国内的 NTP 服务器地址,可用于时间同步或 Android 加速 GPS 定位

NTP 是什么?   NTP 是网络时间协议(Network Time Protocol),它用来同步网络设备【如计算机、手机】的时间的协议。 NTP 实现什么目的?   目的很简单,就是为了提供准确时间。因为我们的手表、设备等,经常会时间跑着跑着就有误差,或快或慢的少几秒,时间长了甚至误差过分钟。 NTP 服务器列表 最常见、熟知的就是 www.pool.ntp.org/zo

开启青龙 Ninja 扫码功能失效后修改成手动填写CK功能【修正Ninja拉库地址】

国内:进入容器docker exec -it qinglong bash #获取ninjagit clone -b main https://ghproxy.com/https://github.com/wjx0428/ninja.git /ql/ninja#安装cd /ql/ninja/backend && pnpm install cp .env.example .env

局域网内vue2 配置本地IP地址访问项目

在日常开发中同事可能需要访问你的前端项目,可以通过配置实现通过ip访问 一.首先找到config文件夹目录下的 index.js文件             将此处的host的值修改为0.0.0.0(即 host: 0.0.0.0) // Various Dev Server settings//host: 'localhost' //将localhost进行替换成 0.0.0.0host:

Python分解多重列表对象,isinstance实现

“”“待打印的字符串列表:['ft','bt',['ad',['bm','dz','rc'],'mzd']]分析可知,该列表内既有字符对象,又有列表对象(Python允许列表对象不一致)现将所有字符依次打印并组成新的列表”“”a=['ft','bt',['ad',['bm','dz','rc'],'mzd']]x=[]def func(y):for i in y:if isinst