其他
小白也能懂的 Nacos 服务模型介绍
The following article is from Kirito的技术分享 Author kiritomoe
前言
服务模型介绍
Dubbo。将接口三元组(接口名+分组名+版本号)映射为 Service,将实例 IP 和端口号定义为 Instance。一个典型的注册在 Nacos 中的 Dubbo 服务: providers:com.alibaba.mse.EchoService:1.0.0:DUBBO
Spring Cloud。将应用名映射为 Service,将实例 IP 和端口号定义为 Instance。一个典型的注册在 Nacos 中的 Spring Cloud 服务: helloApp
环境准备
快速开始
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "mse-xxxx-p.nacos-ans.mse.aliyuncs.com:8848");
String serviceName = "nacos.test.service.1";
String instanceIp = InetAddress.getLocalHost().getHostAddress();
int instancePort = 8080;
namingService.registerInstance(serviceName, instanceIp, instancePort);
System.out.println(namingService.getAllInstances(serviceName));
nacos.test.service.1
;定义了一个 instance,以本机 host 为 IP 和 8080 为端口号,观察实际的注册情况:属性 PropertyKeyConst.SERVER_ADDR
表示的是 Nacos 服务端的地址。创建一个 NamingService 实例,客户端将为该实例创建单独的资源空间,包括缓存、线程池以及配置等。Nacos 客户端没有对该实例做单例的限制,请小心维护这个实例,以防新建多于预期的实例。 注册服务 registerInstance
使用了最简单的重载方法,只需要传入服务名、IP、端口就可以。
Namespace:默认值是 public 或者空字符串,都可以代表默认命名空间。 Group:默认值是 DEFAULT_GROUP。 Cluster:默认值是 DEFAULT。
构建自定义实例
/**
* register a instance to service with specified instance properties.
*
* @param serviceName name of service
* @param groupName group of service
* @param instance instance to register
* @throws NacosException nacos exception
*/
void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException;
public class Instance {
/**
* unique id of this instance.
*/
private String instanceId;
/**
* instance ip.
*/
private String ip;
/**
* instance port.
*/
private int port;
/**
* instance weight.
*/
private double weight = 1.0D;
/**
* instance health status.
*/
private boolean healthy = true;
/**
* If instance is enabled to accept request.
*/
private boolean enabled = true;
/**
* If instance is ephemeral.
*
* @since 1.0.0
*/
private boolean ephemeral = true;
/**
* cluster information of instance.
*/
private String clusterName;
/**
* Service information of instance.
*/
private String serviceName;
/**
* user extended attributes.
*/
private Map<String, String> metadata = new HashMap<String, String>();
}
healthy 实例健康状态。标识该实例是否健康,一般心跳健康检查会自动更新该字段。 enable 是否启用。它跟 healthy 区别在于,healthy 一般是由内核健康检查更新,而 enable 更多是业务语义偏多,可以完全根据业务场景操控。例如在 Dubbo 中,一般使用该字段标识某个实例 IP 的上下线状态。 ephemeral 临时实例还是持久化实例。非常关键的一个字段,需要对 Nacos 有较为深入的了解才能够理解该字段的含义。区别在于,心跳检测失败一定时间之后,实例是自动下线还是标记为不健康。一般在注册中心场景下,会使用临时实例。这样心跳检测失败之后,可以让消费者及时收到下线通知;而在 DNS 模式下,使用持久化实例较多。在《一文详解 Nacos 高可用特性》中我也介绍过,该字段还会影响到 Nacos 的一致性协议。 metadata 元数据。一个 map 结构,可以存储实例的自定义扩展信息,例如机房信息,路由标签,应用信息,权重信息等。
Properties properties = new Properties();
// 指定 Nacos Server 地址
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "mse-xxxx-p.nacos-ans.mse.aliyuncs.com:8848");
// 指定命名空间
properties.setProperty(PropertyKeyConst.NAMESPACE, "9125571e-bf50-4260-9be5-18a3b2e3605b");
NamingService namingService = NacosFactory.createNamingService(properties);
String serviceName = "nacos.test.service.1";
String group = "DEFAULT_GROUP";
String clusterName = "cn-hangzhou";
String instanceIp = InetAddress.getLocalHost().getHostAddress();
int instancePort = 8080;
Instance instance = new Instance();
// 指定集群名
instance.setClusterName(clusterName);
instance.setIp(instanceIp);
instance.setPort(instancePort);
// 指定实例的元数据
Map<String, String> metadata = new HashMap<>();
metadata.put("app", "nacos-demo");
metadata.put("site", "cn-hangzhou");
metadata.put("protocol", "1.3.3");
instance.setMetadata(metadata);
// 指定服务名、分组和实例
namingService.registerInstance(serviceName, group, instance);
System.out.println(namingService.getAllInstances(serviceName));
构建自定义服务
/**
* Service name
*/
private String name;
/**
* Protect threshold
*/
private float protectThreshold = 0.0F;
/**
* Application name of this service
*/
private String app;
/**
* Service group which is meant to classify services into different sets.
*/
private String group;
/**
* Health check mode.
*/
private String healthCheckMode;
private Map<String, String> metadata = new HashMap<String, String>();
服务隔离:Namespace & Group & Cluster
服务发现:推拉模型
/**
* Get all instances of a service
*
* @param serviceName name of service
* @return A list of instance
* @throws NacosException
*/
List<Instance> getAllInstances(String serviceName) throws NacosException;
/**
* Get qualified instances of service
*
* @param serviceName name of service
* @param healthy a flag to indicate returning healthy or unhealthy instances
* @return A qualified list of instance
* @throws NacosException
*/
List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;
/**
* Select one healthy instance of service using predefined load balance strategy
*
* @param serviceName name of service
* @return qualified instance
* @throws NacosException
*/
Instance selectOneHealthyInstance(String serviceName) throws NacosException;
selectOneHealthyInstance
接口上,按照权重返回一个健康的实例。个人认为这个功能相对鸡肋,一般的 RPC 框架都有自身配套的负载均衡策略,很少会由注册中心 cover,事实上 Dubbo 和 Spring Cloud 都没有用到 Nacos 的这个接口。/**
* Subscribe service to receive events of instances alteration
*
* @param serviceName name of service
* @param listener event listener
* @throws NacosException
*/
void subscribe(String serviceName, EventListener listener) throws NacosException;
/**
* Unsubscribe event listener of service
*
* @param serviceName name of service
* @param listener event listener
* @throws NacosException
*/
void unsubscribe(String serviceName, EventListener listener) throws NacosException;
总结
﹀
﹀
﹀