芭比扣了!Nacos中服務(wù)刪除不了,腫么辦?
本文轉(zhuǎn)載自微信公眾號(hào)「Java中文社群」,作者磊哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java中文社群公眾號(hào)。
前兩天遇到了一個(gè)問題,Nacos 中的永久服務(wù)刪除不了,折騰了一番,最后還是順利解決了。以下是原因分析和解決方案,建議先收藏,以備不時(shí)之需。
臨時(shí)實(shí)例和持久化實(shí)例是 Nacos 1.0.0 中新增了一個(gè)特性。臨時(shí)實(shí)例和持久化實(shí)例最大的區(qū)別是健康檢查的方式:臨時(shí)實(shí)例使用客戶端主動(dòng)上報(bào)的健康檢查模式,而持久化實(shí)例使用服務(wù)端反向探測(cè)的模式。也就是說,如果是臨時(shí)實(shí)例,那么客戶端需要主動(dòng)上報(bào)自己的健康狀況,而持久化實(shí)例需要 Nacos 服務(wù)器端反向探測(cè)實(shí)例的健康狀況。
而在這兩種實(shí)例中,臨時(shí)實(shí)例是可以自動(dòng)刪除非健康實(shí)例的,并且當(dāng)所有的臨時(shí)實(shí)例被刪除之后,Nacos 中的服務(wù)也會(huì)被自動(dòng)刪除,這是臨時(shí)服務(wù)的刪除流程。但對(duì)于持久化實(shí)例來說,就沒有那么簡(jiǎn)單了,因此持久化實(shí)例即使是非健康狀態(tài),也不會(huì)自動(dòng)刪除實(shí)例和服務(wù),這個(gè)時(shí)候就需要我們手動(dòng)刪除服務(wù)了。
PS:持久化實(shí)例也有另一種叫法,叫做永久實(shí)例。
需要注意的是,在 Nacos 2.0 之前,一個(gè)服務(wù)中的實(shí)例既可以是臨時(shí)實(shí)例也可以是持久化實(shí)例,但在 Nacos 2.0 時(shí)有了?些細(xì)微的調(diào)整。在 Nacos 2.0 之前,一個(gè)服務(wù)中的實(shí)例既可以是臨時(shí)實(shí)例也可以是永久實(shí)例會(huì)給運(yùn)維人員帶來極大的困惑和運(yùn)維復(fù)雜度。
與此同時(shí),從系統(tǒng)架構(gòu)來看,?個(gè)服務(wù)同時(shí)存在持久化及非持久化實(shí)例的場(chǎng)景也是存在?定矛盾的。這就導(dǎo)致該能力事實(shí)上并未被廣泛使用。為了簡(jiǎn)化 Nacos 的服務(wù)數(shù)據(jù)模型,降低運(yùn)維人員的復(fù)雜度,提升 Nacos 的易用性,在 Nacos 2.0 中將是否持久化的數(shù)據(jù)抽象至服務(wù)級(jí)別,且不再允許?個(gè)服務(wù)同時(shí)存在持久化實(shí)例和非持久化實(shí)例,也就是從 Nacos 2.0 之后,臨時(shí)實(shí)例就變成了臨時(shí)服務(wù),持久化實(shí)例就變成了持久化服務(wù),一個(gè)服務(wù)的整個(gè)生命周期只能有一種實(shí)例類型。
為什么需要兩種服務(wù)類型?
以淘寶為例,雙十一大促期間,流量會(huì)比平常高出很多,此時(shí)服務(wù)肯定需要增加更多實(shí)例來應(yīng)對(duì)高并發(fā),而這些實(shí)例在雙十一之后就無需繼續(xù)使用了,采用臨時(shí)實(shí)例比較合適。而對(duì)于服務(wù)的一些常備實(shí)例,則使用永久實(shí)例更合適。
問題重現(xiàn)
但持久化服務(wù)在手動(dòng)刪除時(shí)候會(huì)報(bào)錯(cuò),如下圖所示:
當(dāng)我們?cè)?Nacos 控制臺(tái)點(diǎn)擊服務(wù)的“刪除”按鈕時(shí),提示“caused: Service DEFAULT_GROUP@@XXX is not empty, can't be delete. Please unregister instance first;”,意思是不能刪除,請(qǐng)先注銷服務(wù)下的實(shí)例,于是我們進(jìn)入服務(wù)實(shí)例列表,如下圖所示:
服務(wù)實(shí)例里面沒有注銷按鈕,只有“下線”按鈕,難道在服務(wù)的“編輯”頁面里面?于是我們又點(diǎn)擊編輯按鈕,看到如下信息:
服務(wù)編輯頁面還是沒有注銷按鈕,難道要把實(shí)例全部“下線”?于是我們嘗試將所有的實(shí)例“下線”如下圖所示:
然后再返回服務(wù)列表頁面,點(diǎn)擊“刪除”按鈕,發(fā)現(xiàn)還是原來的提示信息:
這可咋整嘞,一頓操作還是刪除不了?
解決方案
我們知道除了控制臺(tái)之外,還可以通過 Nacos SDK 或 OpenAPI 來操作 Nacos,而 OpenAPI 的操作成本是最低的,于是趕緊找出 Nacos 官方的 OpenAPI 文檔,看一下如何通過 API 注銷服務(wù)實(shí)例。果然,功夫不負(fù)有心人,在官方文檔中順利的找到了注銷的 API,如下圖所示:
OpenAPI 地址:https://nacos.io/zh-cn/docs/open-api.html
PS:在這里感謝好友@二師兄,提供的思路。
OpenAPI 內(nèi)容如下:
于是照著 API 文檔構(gòu)建了刪除命令:
curl -X DELETE '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 服務(wù)器執(zhí)行的結(jié)果如下圖所示:
服務(wù)器返回了結(jié)果“OK”,打開 Nacos 服務(wù)實(shí)例列表看一下實(shí)例是否被正常注銷:
果然有效果,持久化實(shí)例被順利的注銷了,于是使用同樣的方法把實(shí)例 2 也注銷一下,如下圖所示:
當(dāng)我把服務(wù)下的所有實(shí)例都注銷之后,再去 Nacos 控制臺(tái)發(fā)現(xiàn)服務(wù)也隨之消失了,如下圖所示:
細(xì)心一點(diǎn)的朋友會(huì)發(fā)現(xiàn),之前的服務(wù)并不會(huì)立馬消失了,而是變成空服務(wù)了,要手動(dòng)切換一下“隱藏空服務(wù)”才能展示出來,但有它和沒它的效果是一樣的了,我們可以創(chuàng)建和它名字相同的臨時(shí)實(shí)例了,這就和刪除的效果一樣了,如果沒有被刪除是創(chuàng)建不了臨時(shí)實(shí)例的,所以從邏輯上理解,我們可以認(rèn)為它已經(jīng)被刪除了。
總結(jié)
Nacos 中有兩種實(shí)例:臨時(shí)實(shí)例和持久化實(shí)例(永久實(shí)例),在 Nacos 2.0 之后,每個(gè)服務(wù)中只能保存一種類型的實(shí)例,也就是實(shí)例類型已經(jīng)升級(jí)成了服務(wù)類型了。
對(duì)于臨時(shí)服務(wù)來說,無需刪除,當(dāng)臨時(shí)服務(wù)中的所有實(shí)例都被刪除之后,臨時(shí)服務(wù)也會(huì)被自動(dòng)刪除;而永久服務(wù)需要先通過 OpenAPI 注銷所有的實(shí)例,當(dāng)所有實(shí)例被注銷之后,服務(wù)也被刪除了。