Nacos 1.0.1是GA之后的第一个版本,除了修复1.0.0一些bug以外,还在社区反馈的基础上,吸收了大量的社区共建PR。这个版本中除了原有的贡献者外,新增了13名社区的贡献者,总计合入了43个PR。这一次,社区一起定义Nacos。或许你觉得Nacos很多槽点,或许你觉得Nacos应该支持某些牛逼的功能,此时请不要隐藏你的才华,贡献你在Nacos的第一PR吧。
Nacos 1.0.1主要新增特性介绍
服务发现SDK新增服务的运维接口
@chuntaojun
Nacos的服务模式是由服务-集群-实例组成的三层模型,和以往的Eureka、Consul等注册中心有所区别,这样虽然增加了对更多场景的支持,但是目前只能通过控制台去操作服务和集群的配置,包括创建、更新和删除服务。为了能让用户更加方便的使用Nacos的数据模型,我们在1.0.1版本支持了SDK侧的服务的编辑操作,包含的接口可以参考代码NamingMaintainService:
这个类的使用方法也很简单,与NamingService的使用类似,如下:
NamingMaintainService namingMaintainService = NamingMaintainFactory.createMaintainService(serverAddr);
Service preService = new Service();
preService.setName(serviceName);
preService.setGroupName(Constants.DEFAULT_GROUP);
preService.setProtectThreshold(1.0f);
Map<String, String> metadata = new HashMap<String, String>();
metadata.put(serviceName, "this is a register metadata");
preService.setMetadata(metadata);
ExpressionSelector selector = new ExpressionSelector();
selector.setExpression("CONSUMER.label.A=PROVIDER.label.A &CONSUMER.label.B=PROVIDER.label.B");
System.out.println("service info : " + preService);
namingMaintainService.createService(preService, selector);
更多详细的用法,可以参考代码。
健康检查插件
@xcxcxcxcx
1.0.0版本及以前Nacos支持mysql、tcp、http三种健康检查方式,并且允许关闭健康检查。
为了方便用户使用多样化的健康检查方式,例如用户可能使用了Spring Cloud组件来构建微服务应用,想要对接Spring Cloud Actuator健康检查endpoint,那么就需要给Nacos健康检查做出自定义的实现,在1.0.1版本新增了插件式的可扩展的健康检查。
功能介绍:基于SPI机制,用户通过实现特定的接口和继承特定的抽象类来构建用户自定义的健康检查插件,并通过jvm命令引入插件包,此时Nacos启动后,用户可以在前端页面看到用户自定义的健康检查选项,方便灵活的定制化Nacos健康检查方式。
扩展流程:
- 创建一个maven工程,并引入依赖
//Please correspond to the version currently in use
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-naming</artifactId>
<version>${nacos.version}</version>
</dependency>
- 继承AbstractHealthChecker抽象类,构造自定义心跳实体类,getType()方法返回的是自定义心跳的类型名,必须全局唯一
- 实现HealthCheckProcessor接口,构造自定义心跳处理器类,getType()方法返回的是自定义心跳的类型名,必须全局唯一,且需要与上一步骤的心跳实体类的type相同。
- 使用命令
mvn clean package
将maven工程打包为jar,并将jar移至%NACOS_HOME%/plugins/health路径下,%NACOS_HOME%表示下载的nacos根路径 - 启动Nacos,插件自动生效,Nacos提供的运行脚本中已将%NACOS_HOME%/plugins/health中的插件包加入到JVM运行环境
验证和使用:
-
查看当前生效的健康检查实体类
- 请求接口:/v1/ns/health/checkers
- 请求类型:GET
- 请求参数样例:[空]
- 返回值样例:{"TCP":{"type":"tcp"}, "HTTP":{"type":"http", "path":"xxxx"},"TEST":{"type":"test"}}
-
给服务指定健康检查类型
- 请求接口:/v1/ns/cluster
- 请求类型:PUT
- 请求参数样例:serviceName=DEFAULT_GROUP%40%40appName&clusterName=DEFAULT&metadata=&checkPort=80&useInstancePort4Check=true&healthChecker=%7B%22type%22%3A%22TCP%22%7D&namespaceId=3767dfeb-ec5f-4611-97bb-ee530d19ef89
- 返回值样例:ok
这里的例子表示给组名DEFAULT_GROUP中的服务名为appName的cluster为DEFAULT的应用实例们指定健康检查类型为HTTP,检查端口为80,并且心跳实体类的JSON为{"type":"HTTP","path":"1","headers":"2"}
详细流程及更多注意事项请参考demo工程:nacos-health-plugin-example
控制台集群状态显示
@universefeeler
在集群机器比较多的时候,不方便通过Log来确定当前集群各节点的状态,通过控制可以查看当前集群所有节点状态,可由此判断服务运行情况。只需打开控制台,点击左侧栏 集群管理->节点列表 就可以看到当前集群所处的状态,示例图如下:
服务发现控制台示例代码
@yongchao9
Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理,服务提供者使用 原生SDK、OpenAPI注册 Service 后,服务消费者可以使用HTTP&API查找和发现服务。为了能让用户更加方便的使用,我们在Nacos1.0.1版本中新增了服务使用示例代码,支持在服务列表控制台中直接进行查看,能够让新手快速使,大幅降低新手使用门槛。目前,我们提供基于Java、Spring、Spring Boot、Spring Cloud的使用示例代码,后期我们将逐步完善其余使用场景示例代码。如下图所示:
历史配置保留天数可配置
@rushsky518
历史配置文件保留天数默认是 30 天,现在可以通过 nacos.config.retention.days 参数进行设置,调整保留的天数。
Config客户端重连机制优化
@chuntaojun
Nacos Config模块通过一个长轮询任务LongPollingRunnable
不断向 Config Server询问自己感兴趣的配置是否更新,无论本次任务执行成功还是出现异常,都是直接再次放回Executor中再次执行;因此如果当 Config Server 出现无法服务时,会导致LongPollingRunnable
打印大量的错误日志。
为了改善 Config 客户端与 Config Server 出现连接异常时的大量错误日志打印以及频繁的请求重试,我们在1.0.1版本对 Config 客户端重连机制做了两方面的优化,第一个优化是当任务LongPollingRunnable
在执行时出现异常,将对任务采取延迟执行的惩罚策略,推迟该任务的下一次被调度执行的时间,主要逻辑代码如下
class LongPollingRunnable implements Runnable {
private int taskId;
public LongPollingRunnable(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
List<CacheData> cacheDatas = new ArrayList<CacheData>();
List<String> inInitializingCacheList = new ArrayList<String>();
try {
...
// check server config
List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
...
inInitializingCacheList.clear();
executorService.execute(this);
} catch (Throwable e) {
// If the rotation training task is abnormal, the next execution time of the task will be punished
LOGGER.error("longPolling error : ", e);
executorService.schedule(this, taskPenaltyTime, TimeUnit.MILLISECONDS);
}
}
}
第二个优化是ServerHttpAgent
中执行 Http 请求的重试机制优化,在1.0.1版本中,加入了 Config Server 地址列表轮训次数的限制;在1.0.1版本之前,认为 Http 请求遇到ConnectException
或者SocketTimeoutException
时,应在 timeout 时间内进行重试;但是可能会导致一个问题,如果 Config Server 不可用(宕机或者无法响应客户端请求),会导致在 timeout 时间内Config客户端因为重试发送大量的请求给 Config Server,但是这些请求其实都是无法成功的;因此为了避免此情况,加入了 Config Server 轮训次数限制,如果对 Config Server 地址列表轮训次数达到maxRetry
,则默认请求失败,抛出异常,主要逻辑代码如下
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSSL = false;
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
do {
try {
List<String> newHeaders = getSpasHeaders(paramValues);
if (headers != null) {
newHeaders.addAll(headers);
}
...
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result;
}
} catch (ConnectException ce) {
LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {}", currentServerAddr);
} catch (SocketTimeoutException stoe) {
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}", currentServerAddr, stoe.getMessage());
} catch (IOException ioe) {
LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe);
throw ioe;
}
if (serverListMgr.getIterator().hasNext()) {
currentServerAddr = serverListMgr.getIterator().next();
} else {
maxRetry --;
if (maxRetry < 0) {
throw new ConnectException("[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached");
}
serverListMgr.refreshCurrentServerAddr();
}
} while (System.currentTimeMillis() <= endTime);
...
}
同时,为了方便使用者,以上优化点涉及的几个参数:taskPenaltyTime
——任务惩罚执行时间、timeout
——请求超时时间、maxRetry
——最大重试次数,都可以有使用者自行设置,配置的方法很简单,代码如下
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:" + port);
// 设置长轮询请求超时时间(最小为10s)
properties.put(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT, "20000");
// 设置任务惩罚时间
properties.put(PropertyKeyConst.CONFIG_RETRY_TIME, 3000);
// 设置最大重试次数
properties.put(PropertyKeyConst.MAX_RETRY, 5);
configService = NacosFactory.createConfigService(properties);
具体的优化效果可以参考代码。
如何共建
为了实现这一目标,你需要积极参与Nacos社区。如果您在文档中发现拼写错误,在代码中发现错误,或想要新功能或想要提供建议,您可以在GitHub上创建一个issues。
如果您想开始着手,可以选择github仓库中有以下标签的issues。
- good first issue:对于新手来说是非常好的入门issues。
- contribution welcome:非常需要解决的问题和非常重要的模块,但目前缺少贡献者,欢迎贡献者来贡献。
蓬勃发展的 Nacos 社区
DISS is cheap, show me your hand
比吐槽更重要的是搭把手,参与社区一起发展Nacos
- 作为用户关注和加入 Nacos 社区
Nacos 社区正在蓬勃发展,截止到发文为止,Nacos 已经有 9 个微信群,其中 7 个已满员,1个QQ群,1个钉钉群,关注 Nacos 的社区人数已经近5000人,在 Nacos 群里跟 “道(基)友” 切磋技术,交流经验,招聘交友,抢抢红包...不亦乐乎。
- 作为代码贡献者加入 Nacos 社区
为了能够与代码贡献者更方便的交流,我们组建了钉钉群“Nacos社区核心贡献小组(23335652)”,这个群里都是都是对Nacos贡献非常感兴趣的小伙伴,如果你也想成为Nacos贡献者,甚至成为Committer,欢迎加入这个群和群里的小伙伴一起切磋!
在Nacos官网 nacos.io 中,已经添加团队介绍页,里面包括Nacos的开发者角色定义及职责划分,同时包含了Naocs的开发者们介绍和靓照哦,欢迎大家加入Nacos社区,贡献社区。用Apache的话说,“社区高于代码”!
新人时刻 - "什么是Nacos?"
还不知道什么是Nacos? 没关系,在github上star一下跟程序猿兄弟打个招呼吧!!
Nacos 是阿里巴巴于2018年7月份新开源的项目,Nacos的主要愿景是期望通过提供易用的 动态服务发现
、服务配置管理
、服务共享与管理
的基础设施,帮助用户在云原生时代更好的构建、交付、管理自己的微服务平台。
github项目地址在 这里