Nacos健康檢查
兩種健康檢查機制
Nacos作為注冊中?, 需要感知服務的健康狀態, 才能為服務調??提供良好的服務。
Nacos 中提供了兩種健康檢查機制:
客?端主動上報機制:
- 客?端通過?跳上報?式告知服務端(nacos注冊中?)健康狀態, 默認?跳間隔5秒;
- nacos會在超過15秒未收到?跳后將實例設置為不健康狀態, 超過30秒將實例刪除
服務器端反向探測機制:
- nacos主動探知客?端健康狀態, 默認間隔為20秒.
- 健康檢查失敗后實例會被標記為不健康, 不會被?即刪除.
?如領導管理員?的?作
- 員?主動匯報: 員?每天主動匯報???作進度
- 領導主動問詢: 領導每周向員?了解?作進度
Nacos 中的健康檢查機制不能主動設置,健康檢查機制是和 Nacos 的服務實例類型強相關的.
Nacos服務實例類型
Nacos的服務實例(注冊的節點)分為臨時實例和?臨時實例.
臨時實例
臨時實例:如果實例宕機超過?定時間, 會從服務列表剔除, 默認類型.
?臨時實例
?臨時實例:如果實例宕機, 不會從服務列表剔除, 也可以叫永久實例
Nacos對臨時實例, 采取的是 客?端主動上報機制, 對?臨時實例, 采取服務器端反向探測機制
配置?個服務實例為永久實例
spring:cloud:nacos:discovery:ephemeral: false # 設置為?臨時實例
重啟服務,觀察nacos:
停止服務,再次觀察nacos:
節點依然不會消失。
常?問題
1.Nacos服務實例類型不允許改變
設置服務實例類型, 重新啟動Nacos可能會報錯
報錯信息參考:
Caused by: com.alibaba.nacos.api.exception.NacosException: failed to req
API:/nacos/v1/ns/instance after all servers([110.41.51.65:10020]) tried:
caused: errCode: 400, errMsg: Current service DEFAULT_GROUP@@product-service isephemeral service, can't register persistent instance. ;at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:410) ~[nacos-client-2.2.1.jar:na]at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:351) ~[nacos-client-2.2.1.jar:na]at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:346) ~[nacos-client-2.2.1.jar:na]
//.......
原因: Nacos會記錄每個服務實例的IP和端?號, 當發現IP和端?都沒有發?變化時, Nacos不允許?個
服務實例類型發?變化, ?如從臨時實例,變為?臨時實例, 或者從?臨時實例, 變成臨時實例.
解決辦法:
- 停掉nacos
- 刪除nacos ?錄下 /data/protocol/raft 信息, ??會保存應?實例的元數據信息
2.服務正常, Nacos健康檢查失敗
原因和解決辦法:
參考:如何解決Nacos持久化實例HTTP/TCP的健康檢查不通過問題_微服務引擎(MSE)-阿里云幫助中心
Nacos環境隔離
企業開發中, ?個服務會分為開發環境, 測試環境和?產環境.
- 開發環境:開發?員?于開發的服務器, 是最基礎的環境. ?般?志級別設置較低, 可能會開啟?些調試信息.
- 測試環境:測試?員?來進?測試的服務器, 是開發環境到?產環境的過渡環境.
- ?產環境:正式提供對外服務的環境, 通常關掉調試信息.
通常情況下, 這?個環境是不能互相通信的. Nacos提供了namespace(命名空間)來實現環境的隔離. 不
同的namaspace的服務不可?
創建Namespace
默認情況下,所有服務都在同?個namespace,名為public
點擊左側命名空間, 就可以對namespace進?操作
新增命名空間
配置namespace
namespace創建完成后, 對服務進?配置
配置項 | Key | 默認值 | 說明 |
---|---|---|---|
命名空間 | spring.cloud.nacos.discovery.namespace | ? | 常?場景之?是不同環境的注冊的區分隔離, |
例如開發測試環境和?產環境的資源(如配置、服務)隔離等。 |
修改order-service的命名空間
spring:cloud:nacos:discovery:namespace: 8078d722-567c-4e27-9ff1-a42d6101a546 #(為命名空間ID)
測試遠程調?
1. 啟動服務, 觀察Nacos控制臺
public 命名空間下只有product-service服務(order-service 那個不用管,之前設置的是非臨時實例,所以還在,但它的健康檢查是為false,就不用管它)
order-service在dev命名空間下
2.訪問接?, 測試遠程調?
發現服務報錯
java.lang.IllegalStateException: No instances available for product-serviceat org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.execute(BlockingLoadBalancerClient.java:78) ~[spring-cloud-loadbalancer-4.0.3.jar:4.0.3]at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:56) ~[spring-cloud-commons-4.0.3.jar:4.0.3]at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:87) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:71) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:862) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:764) ~[spring-web-6.0.14.jar:6.0.14]at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:378) ~[spring-web-6.0.14.jar:6.0.14]at com.reggie.order.service.OrderService.selectOrderById(OrderService.java:27) ~[classes/:na]at com.reggie.order.controller.OrderController.getOrderById(OrderController.java:19) ~[classes/:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]........
3. 修改product-service的其中?個實例, 命名空間改為dev
spring:cloud:nacos:discovery:namespace: 8078d722-567c-4e27-9ff1-a42d6101a546 #(為命名空間ID)
4.啟動服務
觀察Nacos控制臺
再次訪問接? 127.0.0.1:8080/order/1 , 發現遠程調?成功
Nacos配置中?
除了注冊中?和負載均衡之外, Nacos還是?個配置中?, 具備配置管理的功能.
Namespace 的常?場景之?是不同環境的配置區分隔離. 例如開發測試環境和?產環境的配置隔離.
為什么需要配置中?
當前項?的配置都在代碼中, 會存在以下問題:
-
配置?件修改時, 服務需要重新部署. 微服務架構中, ?個服務可能有成百個實例, 挨個部署?較?
煩, 且容易出錯.
-
多?開發時, 配置?件可能需要經常修改, 使?同?個配置?件容易沖突.
配置中?就是對這些配置項進?統?管理. 通過配置中?, 可以集中查看, 修改和刪除配置, ?需再逐個
修改配置?件. 提?效率的同時, 也降低了出錯的?險.
- 服務啟動時, 從配置中?讀取配置項的內容, 進?初始化.
- 配置項修改時, 通知微服務, 實現配置的更新加載.
快速上?
通過以下操作, 我們先來感受下Nacos 配置中?的使?
參考?檔:Nacos 融合 Spring Cloud,成為注冊配置中心 | Nacos 官網
添加配置
在Nacos控制臺添加配置項
<aside> 💡
注意: 配置管理的命名空間和服務列表的命名空間是隔離的, 兩個是分別設置的. 默認是public,也就是服務管理命名空間配置 ≠ 配置管理的命名空間 ???沒懂
</aside>
新建配置項
說明:
- Data ID 設置為項?名稱
- 配置內容的數據格式, ?前只?持 properties 和 yaml 類型
- 設置配置內容
獲取配置
- 引入 nacos config 依賴
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- SpringCloud 2020.*之后版本需要引?bootstrap--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>
- 配置bootstrap.properties
微服務啟動前, 需要先獲取nacos中配置, 并與application.yml配置合并. 在微服務運?之前, Nacos要求 必須使? bootstrap.properties 配置?件來配置Nacos Server 地址
spring:application:name: product-servicecloud:nacos:config:server-addr: 127.0.0.1:8848
- spring.application.name 需要和nacos配置管理的Data ID?致
spring.cloud.nacos.config.server-addr
為Nacos Server的地址
<aside> 💡
配置中?和注冊中?的配置是隔離的 Nacos 配置中?: spring.cloud.nacos.config.server-addr Nacos 注冊中?: spring.cloud.nacos.discovery.server-addr
</aside>
-
編寫程序
@RefreshScope @RestController public class NacosConteoller {@Value("${nacos.test}")private String nacosConfig;@RequestMapping("/getConfig")public String getConfig(){return "從nacos獲取配置項nacos.config:" + nacosConfig;} }
- @Value 讀取配置
- @RefreshScope 配置進?熱更新
- 測試
訪問接口:127.0.0.1:9090/getConfig
在Nacos控制臺修改 nacos.config
再次訪問接口:
常?問題
-
讀取不到配置項
可能原因:
- 配置錯誤: 檢查配置Data ID, 配置格式, 配置空間等
- 未引?依賴
-
No spring.config.import property has been defined
啟動報錯?志:
*************************** APPLICATION FAILED TO START *************************** Description: No spring.config.import property has been defined Action: Add a spring.config.import=nacos: property to your configuration.If configuration is not required add spring.config.import=optional:nacos: instead.To disable this check, set spring.cloud.nacos.config.importcheck.enabled=false.
原因: bootstrap.properties 是系統級的資源配置?件, ?于程序執?更加早期配置信息讀
取. 但是SpringCloud 2020.* 之后的版本把bootstrap禁?了, 導致在讀取?件的時候讀取不到?報
錯, 所以需要重新導?bootstrap 包進來就可以了
-
Nacos Server地址配置錯誤
報錯信息如下:
2023-12-28T17:12:53.070+08:00 ERROR 14356 --- [t.remote.worker] c.a.n.c.remote.client.grpc.GrpcClient : Server check fail, please check server 127.0.0.1 ,port 11020 is available , error ={} java.util.concurrent.ExecutionException: com.alibaba.nacos.shaded.io.grpc.StatusRuntimeException: UNAVAILABLE: io exceptionat com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture.ge tDoneValue(AbstractFuture.java:566) ~[nacos-client-2.2.1.jar:na]at com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture.ge t(AbstractFuture.java:445) ~[nacos-client-2.2.1.jar:na] // ...Caused by: com.alibaba.nacos.shaded.io.grpc.StatusRuntimeException: UNAVAILABLE: io exceptionat com.alibaba.nacos.shaded.io.grpc.Status.asRuntimeException(Status.java:539) ~[nacos-client-2.2.1.jar:na]at com.alibaba.nacos.shaded.io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClos e(ClientCalls.java:544) ~[nacos-client-2.2.1.jar:na]at com.alibaba.nacos.shaded.io.grpc.internal.DelayedClientCall$DelayedListener$ 3.run(DelayedClientCall.java:471) ~[nacos-client-2.2.1.jar:na]// ... Caused by: com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.AbstractChann el$AnnotatedConnectException: Connection refused: no further information: /127.0.0.1:11020 Caused by: java.net.ConnectException: Connection refused: no further informationat java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java: 946) ~[na:na]
配置中?詳解
設置命名空間
Nacos配置管理的命名空間和服務列表的命名空間是分別設置的. 默認是public
Nacos命名空間配置依然在bootstrap.yml中進?配置
spring:cloud:nacos:config:server-addr: 127.0.0.1:8848namespace: 8078d722-567c-4e27-9ff1-a42d6101a546 #配置中心的命名空間
如果設置命名空間后, 項?啟動時, 會從該命名空間下找對應的配置項:
再次訪問接口:127.0.0.1:9090/getConfig
Data Id
Data Id 格式介紹
在 Nacos Spring Cloud 中, dataId 的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}
- prefix 默認為 spring.application.name 的值, 也可以通過配置項spring.cloud.nacos.config.prefix 來配置.
- spring.profiles.active 即為當前環境對應的 profile. 當 spring.profiles.active為空時,對應的連接符 - 也將不存在,dataId 的拼接格式變成 ${prefix}.${fileextension}
- file-exetension 為配置內容的數據格式,可以通過配置項spring.cloud.nacos.config.file-extension 來配置。?前只?持 properties和 yaml 類型. 默認為properties.
微服務啟動時, 會從Nacos讀取多個配置?件:
- ${prefix}-${spring.profiles.active}.${file-extension} 如: product-service-dev.properties
- ${prefix}.${file-extension} , 如: product-service.properties
- ${prefix} 如product-service
<aside> 💡
${spring.application.name}, ${spring.profiles.active} 等通過配置?件來指定時, 必須放在 bootstrap.properties ?件中
</aside>
三個?件的優先級為: product-service-dev.properties > product-service.properties > productservice
觀察?志
在bootstrap.yml中添加 spring.profiles.active 值
spring:profiles:active: dev
#pom.xml<profiles><profile><id>dev</id><properties><profile.name>dev</profile.name></properties></profile><profile><id>prod</id><properties><profile.name>prod</profile.name></properties></profile></profiles>
啟動服務, 觀察?志
2023-12-28T18:48:08.614+08:00 INFO 36672 --- [ main]
c.a.n.client.config.impl.ClientWorker : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [subscribe] product-servicedev.properties+DEFAULT_GROUP+51152a13-7911-49e3-bbdc-16fd5670a257
2023-12-28T18:48:08.624+08:00 INFO 36672 --- [ main]
c.a.nacos.client.config.impl.CacheData : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [**add-listener**] ok, tenant=51152a13-7911-49e3-
bbdc-16fd5670a257, **dataId=product-service-dev.properties**, group=DEFAULT_GROUP,
cnt=1
2023-12-28T18:48:08.624+08:00 INFO 36672 --- [ main]
c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config:
dataId=product-service-dev.properties, group=DEFAULT_GROUP
2023-12-28T18:48:08.625+08:00 INFO 36672 --- [ main]
c.a.n.client.config.impl.ClientWorker : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [subscribe] productservice.properties+DEFAULT_GROUP+51152a13-7911-49e3-bbdc-16fd5670a257
2023-12-28T18:48:08.625+08:00 INFO 36672 --- [ main]
c.a.nacos.client.config.impl.CacheData : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [**add-listener**] ok, tenant=51152a13-7911-49e3-
bbdc-16fd5670a257, **dataId=product-service.properties**, group=DEFAULT_GROUP,
cnt=1
2023-12-28T18:48:08.625+08:00 INFO 36672 --- [ main]
c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config:
dataId=product-service.properties, group=DEFAULT_GROUP
2023-12-28T18:48:08.626+08:00 INFO 36672 --- [ main]
c.a.n.client.config.impl.ClientWorker : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [subscribe] productservice+DEFAULT_GROUP+51152a13-7911-49e3-bbdc-16fd5670a257
2023-12-28T18:48:08.627+08:00 INFO 36672 --- [ main]
c.a.nacos.client.config.impl.CacheData : [fixed-51152a13-7911-49e3-bbdc-
16fd5670a257-110.41.51.65_10020] [**add-listener**] ok, tenant=51152a13-7911-49e3-
bbdc-16fd5670a257, **dataId=product-service**, group=DEFAULT_GROUP, cnt=1
2023-12-28T18:48:08.627+08:00 INFO 36672 --- [ main]
c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config:
dataId=product-service, group=DEFAULT_GROUP
測試
bootstrap.yml配置如下:
spring:application:name: product-serviceprofiles:active: @profile.name@cloud:nacos:config:server-addr: 127.0.0.1:8848namespace: 8078d722-567c-4e27-9ff1-a42d6101a546 #配置中心的命名空間
配置項如下:
訪問接?: http://127.0.0.1:9090/getConfig
服務獲取到了 product-service-dev.properties 的值
刪除 product-service-dev.properties 配置, 再次訪問接?
<aside> 💡
注意:
- bootstrap.yml 設置的配置格式必須和nacos控制臺配置的數據格式保持?致.
- 不設置配置格式(spring.cloud.nacos.config.file-extension)時, 默認為properties </aside>
Nacos與Eureka的區別
共同點:
- 都?持服務注冊和服務拉取
區別:
-
功能
Nacos除了服務發現和注冊之外, 還提供了配置中?, 流量管理和DNS服務等功能.
-
CAP理論
Eureka遵循AP原則, Nacos可以切換AP和CP模式,默認AP.
Nacos 根據配置識別CP或者AP模式. 如果注冊Nacos的Client的節點是臨時節點, 那么Nacos對這個
Client節點的效果就是AP, 反之是CP. AP和CP可以同時混合存在.
-
服務發現
Eureka:基于拉模式. Eureka Client會定期從Server拉取服務信息, 有緩存, 默認每30秒拉取?次.
Nacos:基于推送模式. 服務列表有變化時實時推送給訂閱者, 服務端和客?端保持?跳連接.