1. 定义
命名:元数据(metadata)
归属:为服务实例的属性
类型:Map
作用:记录服务实例信息
生命周期:同服务实例生命周期
2. 作用
【metadata】通常服务于技术组件,根据自身需要对服务实例的 metadata 进行扩展,如下:
服务描述:服务名称、版本、IP、端口、环境。
标签分类:更加细粒度地管理相同服务的不同实例。
调整策略:调整负载均衡和路由策略。
优化路由:标记节点地理位置,可基于地理位置的路由优化路径。
版本控制:记录实例版本信息,仅访问相同版本的实例,可用于版本测试和灰度。
权限控制:可用于自定义管理服务的安全策略和访问权限。
故障恢复:重试配置、断路器配置等。
3. 初始化元数据
可通过 yaml 配置服务的通用 metadata,更细力度的单实例 metadata 配置可通过启动命令设置。
3.1. yaml 配置 - Nacos
spring: application: name: customer cloud: nacos: discovery: server-addr: 127.0.0.1:8848 # 元数据 metadata: # 自定义元数据 customFlag: green
复制代码
Nacos 配置的 metadata【customFlag=green】已配置至服务实例上,如图:
Nacos 支持 metadata 过滤以及在线编辑 metadata。
3.2. yaml 配置 - Consul
spring: application: name: contract cloud: # Consul consul: host: localhost port: 8500 serviceName: contract discovery: instanceId: contract metadata: customFlag: green
复制代码
Consul 配置的 metadata【customFlag=green】已配置至服务实例上,如图:
3.3. 启动命令配置
支持 JVM 和 SpringBoot 两种配置方式。
JVM 配置:
java -jar -Dspring.cloud.nacos.discovery.metadata.customFlag=fo customer-0.0.1-SNAPSHOT.jar
复制代码
SpringBoot 配置:
java -jar customer-0.0.1-SNAPSHOT.jar --spring.cloud.nacos.discovery.metadata.customFlag=ba
复制代码
4. Demo - 动态修改
该 demo 演示了修改被请求实例的 metadata,如下:
private final NacosDiscoveryProperties discoveryProperties;
/** * @Author Nacol(姚秋实) * @Date 2023/12/11 * @Title 修改 MetaData(打标更新) * @Description 此方法仅作为演示:修改被调用Instance的MetaData(可根据实际需要修改具体逻辑) */@PutMapping("/modify")@SneakyThrowspublic void updateMetadata(@RequestBody InstanceFlag instanceFlag) { // STEP 获取当前 NameSpace NamingService namingService = discoveryProperties.namingServiceInstance();
// STEP 获取 NameSpace 下的指定服务实例集合 List<Instance> instances = namingService.getAllInstances(instanceFlag.getServiceName());
// STEP 获取当前节点 Instance currentInstance = instances.stream() /** * STEP 过滤:获取当前节点,即:IP和端口相等 * 可根据实际需求更改逻辑 */ .filter(instance -> instance.getIp().equals(discoveryProperties.getIp()) && instance.getPort() == discoveryProperties.getPort()) .findFirst() .get(); Assert.notNull(currentInstance, () -> new RuntimeException("Not current instance found"));
// STEP 更新 MetaData // 获取当前节点当前 MetaData Map<String, String> metaData = new HashMap<>(currentInstance.getMetadata()); // 参数 MetaData 将当前 MetaData 更新 metaData.putAll(instanceFlag.getMetaData()); currentInstance.setMetadata(metaData);
// STEP 更新 Nacos namingService.registerInstance(instanceFlag.getServiceName(), currentInstance);}
复制代码
可根据自身需要修改指定实例的 metadata,例如:
5. Demo - 负载均衡
/** * @Author Nacol(姚秋实) * @Date 2023/12/11 * @Title 自定义负载均衡 * @Description 目的:该类仅演示负载均衡使用 Instance.MetaData 作为负载均衡条件 */public class CustomLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private final String serviceId; private final DiscoveryClient discoveryClient; private final Random random = new Random();
public CustomLoadBalancer(String serviceId, LoadBalancerClientFactory loadBalancerClientFactory) { this.serviceId = serviceId; this.discoveryClient = loadBalancerClientFactory.getLazyProvider(serviceId, DiscoveryClient.class).getIfAvailable(); }
/** * @Author Nacol(姚秋实) * @Date 2023/12/11 * @Title 自定义负载均衡 */ @Override public Mono<Response<ServiceInstance>> choose(Request request) { // 从Nacos获取服务实例列表 List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
/** * 过滤只对【customFlag=green】的节点进行负载均衡 * 此处可扩展自己的需求 */ instances = instances.stream() .filter(instance -> StrUtil.equals(instance.getMetadata().get("customFlag"), "green")) .collect(Collectors.toList());
if (instances.isEmpty()) { return Mono.empty(); }
// 随机选择一个实例 ServiceInstance instance = instances.get(random.nextInt(instances.size())); return Mono.just(new DefaultResponse(instance)); }
}
复制代码
6. Demo - 传送门
https://gitee.com/nacolgaga/registration
7. 总结
注册中心的元数据在微服务架构中扮演着核心角色,它提供了一种机制来描述和管理服务实例。通过元数据的标签分类支持服务发现、负载均衡、路由优化、版本控制、安全性管理,增强了服务的灵活性和可维护性。通过动态修改元数据,可以有效地调整服务行为和资源利用,实现高效的服务管理和运维。
评论