本文转载自微信公众号“Java中文社区”,作者雷哥。转载本文请联系Java中文社区公众号。我前两天遇到一个问题。Nacos中的永久服务无法删除。折腾了一番,终于顺利解决了。以下是原因分析及解决方法,建议先收藏,以备不时之需。临时实例和持久化实例是Nacos1.0.0的新特性。临时实例和持久实例最大的区别在于健康检查方式:临时实例采用客户端主动上报的健康检查方式,而持久实例采用服务端反向检测方式。也就是说,如果是临时实例,客户端需要主动上报自身的健康状态,而持久化实例则需要Nacos服务器反向检测实例的健康状态。在这两个实例中,临时实例可以自动删除不健康的实例,当所有临时实例被删除时,Nacos中的服务也会自动删除,即临时服务的删除过程。但是对于持久化实例,就没那么简单了。因此,即使持久化实例处于不健康状态,实例和服务也不会被自动删除。这时候我们需要手动删除服务。PS:持久化实例还有另外一个名字,叫做永久实例。需要注意的是,在Nacos2.0之前,一个服务中的实例可以是临时实例,也可以是持久实例,但是Nacos2.0做了一些小的调整。在Nacos2.0之前,服务中的一个实例既可以是临时实例,也可以是永久实例,这会给运维人员带来很大的困惑和复杂性。同时,从系统架构上看,一个服务既有持久化实例又有非持久化实例的场景存在一定的矛盾。这导致了这个能力没有被广泛使用的事实。为了简化Nacos服务数据模型,降低运维人员的复杂度,提高Nacos的易用性,在Nacos2.0中,将持久化数据抽象到服务层面,不再允许一个服务拥有同时有一个持久化实例和非持久化实例,也就是从Nacos2.0开始,临时实例变成了临时服务,持久化实例变成了持久化服务。一个服务的整个生命周期中只能有一个实例类型。为什么我们需要两种类型的服务?以淘宝为例,在双十一促销期间,流量会比平时高很多。没有必要继续使用,使用临时实例比较合适。对于一些常备实例的服务,使用永久实例更为合适。问题重现,但是持久化服务在手动删除的时候会报错,如下图:当我们在Nacos控制台点击该服务的“删除”按钮时,提示“caused:ServiceDEFAULT_GROUP@@XXX不为空,不能删除。请先注销实例;”,表示不能删除,请先退出服务下的实例,这样我们进入服务实例列表,如图下图:服务实例中没有注销按钮,只有“离线”按钮,是在服务的“编辑”页面吗?于是我们再次点击编辑按钮,看到如下信息:服务编辑页面仍然没有注销按钮。我们要“离线”所有实例吗?于是我们尝试将所有实例“下线”如下图:然后回到服务列表页面,点击“删除”按钮,发现原来的提示信息还是:Howcanthisbedone,can'一次操作不删除?我们知道的解决方案是,除了控制台,还可以通过NacosSDK或者OpenAPI来操作Nacos,而且OpenAPI的操作成本是最低的,所以赶紧找出NacosOpenAPI官方文档,看看如何退出一个通过API的服务实例。果然功夫不负有心人,成功在官方文档中找到了取消的API,如下图:OpenAPI地址:https://nacos.io/zh-cn/docs/open-api.htmlPS:在此感谢好友@二师兄提供的思路。OpenAPI的内容如下:于是根据API文档建立一个删除命令:curl-XDELETE'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=spring-cloud-nacos-producer&groupName=DEFAULT_GROUP&namespaceId=public&ip=10.0.24.8&clusterName=DEFAULT&port=8081&ephemeral=false'在Nacos服务器上执行上述命令的结果如下图:服务器返回结果“OK”,打开Nacos服务实例列表查看实例是否正常注销:确实有效,持久化实例成功注销,所以用同样的方法注销实例2,如下图:我注销了服务下的所有实例后,我去Nacos控制台发现服务也消失了,如下图:细心的朋友会发现之前的服务并没有马上消失,而是变成了空服务。需要手动切换“Hideemptyservice”才能显示出来,但是有和没有效果是一样的,我们可以创建一个和它同名的临时实例,和删除效果一样,如果它没有被删除,就不能创建临时实例,所以从逻辑上,我们可以认为它已经被删除了。总结一下,Nacos中有两种实例:临时实例和持久化实例(永久实例)。Nacos2.0之后,每个服务只能保存一种实例类型,即实例类型升级为服务类型。对于临时服务,不需要删除。当临时服务中的所有实例都被删除时,临时服务也会被自动删除;对于永久服务,需要先通过OpenAPI注销所有实例。当所有实例都注销时,该服务也将被删除。被删除了。
