成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

集群中節點之間健康檢查

開發 前端
當新的節點加入集群或者集群中有節點下線了,集群之間可以通過健康檢查發現。健康檢查的頻率是怎么樣的?節點的狀態又是如何變動的?狀態的變動又會觸發什么動作。帶著這些問題本文捋一捋。

[[411449]]

引言

當新的節點加入集群或者集群中有節點下線了,集群之間可以通過健康檢查發現。健康檢查的頻率是怎么樣的?節點的狀態又是如何變動的?狀態的變動又會觸發什么動作。帶著這些問題本文捋一捋。

一、內容提要

內容提要

健康檢查

  • Nacos節點會向集群其他節點發送健康檢查心跳,每一輪頻率為2秒
  • 當健康檢查異常時設置為不信任「SUSPICIOUS」狀態,超過失敗最大次數3次設置為下線「DOWN」狀態
  • 健康檢查成功設置該節點為科通信「UP」狀態
  • 無論成功還是失敗當節點狀態變更時均發布MembersChangeEvent事件

成員變更事件

當集群節點成員變更時,MemberChangeListener會收到該事件

例如回調ClusterRpcClientProxy#onEvent觸發refresh

刷新本節點與集群中其他節點的RPC狀態,關閉無效的或者增加新的RPC連接

二、健康檢查

代碼翻到ServerMemberManager#onApplicationEvent,在Nacos啟動的時候會啟動一個定時任務,第一次延遲5秒執行,該定時任務即負責節點之間的心跳。

  1. @Override 
  2. public void onApplicationEvent(WebServerInitializedEvent event) { 
  3.     getSelf().setState(NodeState.UP); 
  4.     if (!EnvUtil.getStandaloneMode()) { // 注解@1 
  5.         GlobalExecutor.scheduleByCommon(this.infoReportTask, 5_000L); 
  6.     } 
  7.     EnvUtil.setPort(event.getWebServer().getPort()); 
  8.     EnvUtil.setLocalAddress(this.localAddress); 
  9.     Loggers.CLUSTER.info("This node is ready to provide external services"); 

注解@1 非單機模式延遲5秒執行,執行的infoReportTask為MemberInfoReportTask。

  1. public abstract class Task implements Runnable { 
  2.      
  3.     protected volatile boolean shutdown = false
  4.      
  5.     @Override 
  6.     public void run() { // 注解@2 
  7.         if (shutdown) { 
  8.             return
  9.         } 
  10.         try { 
  11.             executeBody(); 
  12.         } catch (Throwable t) { 
  13.             Loggers.CORE.error("this task execute has error : {}", ExceptionUtil.getStackTrace(t)); 
  14.         } finally { 
  15.             if (!shutdown) { 
  16.                 after(); 
  17.             } 
  18.         } 
  19.     } 
  20.    

注解@2 看下這個Task執行邏輯,先執行 executeBody(),執行結束后執行after()。

  1. class MemberInfoReportTask extends Task { 
  2.  
  3.     private final GenericType<RestResult<String>> reference = new GenericType<RestResult<String>>() { 
  4.     }; 
  5.  
  6.     private int cursor = 0; 
  7.  
  8.     @Override 
  9.     protected void executeBody() { 
  10.         // ----------注解@1 start--------------- 
  11.        // 獲取集群中除了自身以外的其他節點列表 
  12.         List<Member> members = ServerMemberManager.this.allMembersWithoutSelf(); 
  13.         if (members.isEmpty()) { 
  14.             return
  15.         } 
  16.         // 定義一個游標 
  17.         this.cursor = (this.cursor + 1) % members.size(); 
  18.         // 獲取每個節信息 
  19.         Member target = members.get(cursor); 
  20.     //-----------注解@1 end----------------- 
  21.         Loggers.CLUSTER.debug("report the metadata to the node : {}", target.getAddress()); 
  22.         // 注解@2 
  23.         final String url = HttpUtils 
  24.                 .buildUrl(false, target.getAddress(), EnvUtil.getContextPath(), Commons.NACOS_CORE_CONTEXT, 
  25.                         "/cluster/report"); 
  26.         try { 
  27.            // 注解@3 
  28.             asyncRestTemplate 
  29.                     .post(url, Header.newInstance().addParam(Constants.NACOS_SERVER_HEADER, VersionUtils.version), 
  30.                             Query.EMPTY, getSelf(), reference.getType(), new Callback<String>() {  
  31.                                 @Override 
  32.                                 public void onReceive(RestResult<String> result) { // 注解@4 
  33.                                     // 注解@5 返回版本不一致 
  34.                                     if (result.getCode() == HttpStatus.NOT_IMPLEMENTED.value() 
  35.                                             || result.getCode() == HttpStatus.NOT_FOUND.value()) { 
  36.                                         // ... 
  37.                                         Member memberNew = target.copy(); 
  38.                                         if (memberNew.getAbilities() != null 
  39.                                                 && memberNew.getAbilities().getRemoteAbility() != null && memberNew 
  40.                                                 .getAbilities().getRemoteAbility().isSupportRemoteConnection()) { 
  41.                                             memberNew.getAbilities().getRemoteAbility() 
  42.                                                     .setSupportRemoteConnection(false); 
  43.                                             update(memberNew); // 更新節點屬性 
  44.                                         } 
  45.                                         return
  46.                                     } 
  47.                                     // 注解@6 
  48.                                     if (result.ok()) { 
  49.                                         MemberUtil.onSuccess(ServerMemberManager.this, target); 
  50.                                     } else { 
  51.                                      // 注解@7 處理失敗上報 
  52.                                         MemberUtil.onFail(ServerMemberManager.this, target); 
  53.                                     } 
  54.                                 } 
  55.  
  56.                                 @Override 
  57.                                 public void onError(Throwable throwable) { 
  58.                                    // 注解@8 處理失敗上報 
  59.                                      MemberUtil.onFail(ServerMemberManager.this, target, throwable); 
  60.                                 } 
  61.  
  62.                                 @Override 
  63.                                 public void onCancel() { 
  64.  
  65.                                 } 
  66.                             }); 
  67.         } catch (Throwable ex) { 
  68.             // ... 
  69.         } 
  70.     } 
  71.  
  72.     @Override 
  73.     protected void after() { 
  74.         GlobalExecutor.scheduleByCommon(this, 2_000L); // 注解@9 
  75.     } 

注解@1 獲取集群中除了自身以外的其他節點列表,通過游標循環每個節點。

注解@2 構造每個節點的上報url請求路徑為「/cluster/report」

注解@3 發起Post健康檢查請求,請求內容為自身信息Member

注解@4 處理健康檢查返回結果,有以下三種類型

注解@5 版本過低錯誤,這個可能在集群中版本不一致出現

注解@6 處理成功上報,更新該節點member的狀態為UP表示科通信,設置失敗次數為0,并發布成員變更事件

  1. public static void onSuccess(final ServerMemberManager manager, final Member member) { 
  2.     final NodeState old = member.getState(); 
  3.     manager.getMemberAddressInfos().add(member.getAddress()); 
  4.     member.setState(NodeState.UP); // 狀態為UP可通信狀態 
  5.     member.setFailAccessCnt(0); // 失敗次數為0 
  6.     if (!Objects.equals(old, member.getState())) { 
  7.         manager.notifyMemberChange(); // 發布成員變更事件 
  8.     } 

注解@7&注解@8 均為處理失敗的上報,例如:集群中一個節點被kill -9 殺掉后。在nacos-cluster.log日志文件中會打印如下日志,并發布成員變更事件

  1. 2021-07-0x 16:30:24,994 ERROR failed to report new info to target node : x.x.x.x:8848, error : caused: Connection refused; 
  2.  
  3. :2021-07-0x 16:30:30,995 ERROR failed to report new info to target node : x.x.x.x:8848, error : caused: Connection refused; 
  1. public static void onFail(final ServerMemberManager manager, final Member member, Throwable ex) { 
  2.     manager.getMemberAddressInfos().remove(member.getAddress()); 
  3.     final NodeState old = member.getState(); 
  4.  
  5.     // 設置該節點為「不信任」 
  6.     member.setState(NodeState.SUSPICIOUS); 
  7.     // 失敗次數遞增+1 
  8.     member.setFailAccessCnt(member.getFailAccessCnt() + 1); 
  9.     // 默認最大失敗重試次數為3 
  10.     int maxFailAccessCnt = EnvUtil.getProperty("nacos.core.member.fail-access-cnt"Integer.class, 3); 
  11.  
  12.     // If the number of consecutive failures to access the target node reaches 
  13.     // a maximum, or the link request is rejected, the state is directly down 
  14.     // 超過重試次數設置節點狀態為「下線」 
  15.     if (member.getFailAccessCnt() > maxFailAccessCnt || StringUtils 
  16.             .containsIgnoreCase(ex.getMessage(), TARGET_MEMBER_CONNECT_REFUSE_ERRMSG)) { 
  17.         member.setState(NodeState.DOWN); 
  18.     } 
  19.  
  20.     if (!Objects.equals(old, member.getState())) { 
  21.         manager.notifyMemberChange(); // 發布成員變更事件 
  22.     } 

被kill -9 殺掉的節點顯示狀態為下線DOWN

注解@9 執行完executeBody后延遲2秒繼續執行executeBody,也就是檢查健康檢查的心跳頻率為2秒,一輪全部節點檢查結束后延遲2秒接著下一輪

無論檢查成功還是失敗,當節點狀態變更時,發布成員變更事件。

  1. if (!Objects.equals(old, member.getState())) { 
  2.     manager.notifyMemberChange(); 
  3.  
  4. void notifyMemberChange() { 
  5.     NotifyCenter.publishEvent(MembersChangeEvent.builder().members(allMembers()).build()); 

小結: Nacos節點會向集群其他節點發送健康檢查心跳,每一輪頻率為2秒;當健康檢查異常時設置為不信任「SUSPICIOUS」狀態,超過失敗最大次數3次設置為下線「DOWN」狀態;健康檢查成功設置該節點為科通信「UP」狀態;無論成功還是失敗當節點狀態變更時均發布MembersChangeEvent事件。

三、成員變更事件

當集群中有節點下線或者新節點上線都會通過心跳健康檢查探測對節點狀態進行改變。而狀態的變更均會觸發成員變更事件MembersChangeEvent。那訂閱到這個事件干啥呢?

ClusterRpcClientProxy繼承了MemberChangeListener,當有MembersChangeEvent事件時會回調其onEvent方法。

  1. @Override 
  2. public void onEvent(MembersChangeEvent event) { 
  3.     try { 
  4.         List<Member> members = serverMemberManager.allMembersWithoutSelf(); 
  5.         refresh(members); 
  6.     } catch (NacosException e) { 
  7.         // ... 
  8.     } 

那接著看refresh方法。

  1. private void refresh(List<Member> members) throws NacosException { 
  2.  
  3.     for (Member member : members) { 
  4.         if (MemberUtil.isSupportedLongCon(member)) { 
  5.             // 注解@10 
  6.             createRpcClientAndStart(member, ConnectionType.GRPC); 
  7.         } 
  8.     } 
  9.     Set<Map.Entry<String, RpcClient>> allClientEntrys = RpcClientFactory.getAllClientEntries(); 
  10.     Iterator<Map.Entry<String, RpcClient>> iterator = allClientEntrys.iterator(); 
  11.     List<String> newMemberKeys = members.stream().filter(a -> MemberUtil.isSupportedLongCon(a)) 
  12.             .map(a -> memberClientKey(a)).collect(Collectors.toList()); 
  13.     // 關閉舊的grpc連接 
  14.     while (iterator.hasNext()) { 
  15.         Map.Entry<String, RpcClient> next1 = iterator.next(); 
  16.         if (next1.getKey().startsWith("Cluster-") && !newMemberKeys.contains(next1.getKey())) { 
  17.             Loggers.CLUSTER.info("member leave,destroy client of member - > : {}", next1.getKey()); 
  18.             RpcClientFactory.getClient(next1.getKey()).shutdown(); 
  19.             iterator.remove(); 
  20.         } 
  21.     } 
  22.  

注解@10 為集群中每個節點member創建rcp client,在client啟動時會先目標節點發送HealthCheckRequest,如果非健康節點將會被移除。見RpcClient類部分代碼。

  1. boolean isHealthy = healthCheck(); 
  2. // 非健康節點 
  3. if (!isHealthy) { 
  4.     if (currentConnection == null) { 
  5.         continue
  6.     } 
  7.     LoggerUtils.printIfInfoEnabled(LOGGER, 
  8.             "[{}]Server healthy check fail,currentConnection={}"name
  9.             currentConnection.getConnectionId()); 
  10.     // 標記客戶端狀態為unhealthy 
  11.     rpcClientStatus.set(RpcClientStatus.UNHEALTHY); 
  12.     // 重置ReconnectContext移除serverInfo 
  13.     reconnectContext = new ReconnectContext(nullfalse); 

這個意味著如果集群中有節點下線,與下線節點的rpc將會失效;同樣如果集群中有新節點加入將會建立新的rpc通道。

小結: 當集群節點成員變更時,MemberChangeListener會收到該事件。例如回調ClusterRpcClientProxy#onEvent觸發refresh。刷新本節點與集群中其他節點的RPC狀態,關閉無效的或者增加新的RPC連接。

本文轉載自微信公眾號「瓜農老梁」,可以通過以下二維碼關注。轉載本文請聯系瓜農老梁公眾號。

 

 

責任編輯:武曉燕 來源: 瓜農老梁
相關推薦

2023-03-03 08:19:35

KubernetesgRPC

2023-03-02 07:20:10

GRPC服務健康檢查協議

2023-03-01 08:33:37

gRPC健康檢查代碼

2017-08-25 10:20:46

Docker容器機制

2020-12-07 06:29:13

SpringBoot

2023-05-09 07:34:25

Docker健康檢查方式

2023-10-14 15:36:14

PodKubernetes

2024-02-27 17:30:11

2021-01-15 05:38:28

ASPHttp端口

2022-09-07 09:19:49

Docker健康檢查

2021-04-18 10:34:28

Spring Clou郵件釘釘

2021-09-18 16:10:48

Spring BootJava微服務

2022-02-28 07:40:23

Nacos注冊中心客戶端

2021-08-02 07:57:03

注冊Nacos源碼

2021-07-05 06:51:41

Nacos微服務源碼

2021-09-21 16:31:56

Windows 11微軟PC健康檢查工具

2015-07-17 10:25:43

kubernetesDocker集群系統

2024-10-31 15:16:35

2012-08-03 11:21:50

應用交付深信服

2023-03-07 07:49:06

Kubernetes容器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲在线一区 | 日韩av电影在线观看 | 欧美男人天堂 | 99成人免费视频 | 国产日韩精品一区 | 免费观看黄a一级视频 | 国产精品久久久久一区二区 | 欧美激情国产日韩精品一区18 | 国产一区二区三区免费 | 欧美精品导航 | 中文一区二区 | 国产人成精品一区二区三 | 凹凸日日摸日日碰夜夜 | 一级毛片在线播放 | 日韩有码一区 | 成人国产在线视频 | 久久久久久久久久久福利观看 | 久久久免费电影 | 一区日韩 | 在线观看www| 久久小视频| 中文字幕在线观看www | 日本一本视频 | 精品欧美一区二区三区精品久久 | 天天做日日做 | 一级黄色短片 | 午夜激情一区 | 国产精品不卡视频 | 中文字幕视频在线 | 国产视频精品免费 | 国产日韩中文字幕 | 亚洲午夜久久久 | 国产精品一二三区在线观看 | 免费国产视频 | 久久精品视频在线观看 | 97精品国产97久久久久久免费 | 国产精品高潮呻吟久久av黑人 | 国产精品久久久久久久久久软件 | 婷婷激情综合 | 国产视频在线观看一区二区三区 | 久久高清 |