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")
@SneakyThrows
public 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. 总结
注册中心的元数据在微服务架构中扮演着核心角色,它提供了一种机制来描述和管理服务实例。通过元数据的标签分类支持服务发现、负载均衡、路由优化、版本控制、安全性管理,增强了服务的灵活性和可维护性。通过动态修改元数据,可以有效地调整服务行为和资源利用,实现高效的服务管理和运维。
评论