zoukankan      html  css  js  c++  java
  • ElasticSearch 问题分析:No data nodes with HTTP-enabled available

    环境:ES-5.4.0版本,部署方式:3master node+2client node+3data node

    说明:data node和client node都配置了http.enabled: false,程序在写数据时报错:No data nodes with HTTP-enabled available

    源码分析:

     1 public static void filterNonDataNodesIfNeeded(Settings settings, Log log) {
     2     if (!settings.getNodesDataOnly()) {
     3         return;
     4     }
     5 
     6     RestClient bootstrap = new RestClient(settings);
     7     try  {
     8         String message = "No data nodes with HTTP-enabled available";
     9         List<NodeInfo> dataNodes = bootstrap.getHttpDataNodes();
    10     // 找不到dataNodes就会报错
    11         if (dataNodes.isEmpty()) {
    12             throw new EsHadoopIllegalArgumentException(message);
    13         }
    14         ...
    15     } finally {
    16         bootstrap.close();
    17     }
    18 }

    接下来看看RestClient.getHttpDataNodes()方法的取值逻辑

     1 public List<NodeInfo> getHttpDataNodes() {
     2     List<NodeInfo> nodes = getHttpNodes(false);
     3   // 遍历上面获取到的节点
     4     Iterator<NodeInfo> it = nodes.iterator();
     5     while (it.hasNext()) {
     6         NodeInfo node = it.next();
     7     // 如果不是数据节点,则移除
     8         if (!node.isData()) {
     9             it.remove();
    10         }
    11     }
    12     return nodes;
    13 }
    14 
    15 // 获取http节点_nodes/http
    16 public List<NodeInfo> getHttpNodes(boolean clientNodeOnly) {
    17   // 通过es接口“_nodes/http”来获取nodes的信息
    18     Map<String, Map<String, Object>> nodesData = get("_nodes/http", "nodes");
    19     List<NodeInfo> nodes = new ArrayList<NodeInfo>();
    20 
    21     for (Entry<String, Map<String, Object>> entry : nodesData.entrySet()) {
    22         NodeInfo node = new NodeInfo(entry.getKey(), entry.getValue());
    23     // 如果不是查找client节点,则只要节点运行网络访问就可以add了;如果查找client节点,则还要通过isClient验证才能add
    24         if (node.hasHttp() && (!clientNodeOnly || node.isClient())) {
    25             nodes.add(node);
    26         }
    27     }
    28     return nodes;
    29 }
    View Code

     最后再来看看node.hasHttp(),isClient(),isData()的方法

     1     private final String id;
     2     private final String name;
     3     private final String host;
     4     private final String ip;
     5     private final String publishAddress;
     6     private final boolean hasHttp;
     7     private final boolean isClient;
     8     private final boolean isData;
     9     private final boolean isIngest;
    10 
    11     public NodeInfo(String id, Map<String, Object> map) {
    12         this.id = id;
    13         EsMajorVersion version = EsMajorVersion.parse((String) map.get("version"));
    14         this.name = (String) map.get("name");
    15         this.host = (String) map.get("host");
    16         this.ip = (String) map.get("ip");
    17     // 5.0以下版本的分支
    18         if (version.before(EsMajorVersion.V_5_X)) {
    19             Map<String, Object> attributes = (Map<String, Object>) map.get("attributes");
    20             if (attributes == null) {
    21                 this.isClient = false;
    22                 this.isData = true;
    23             } else {
    24                 String data = (String) attributes.get("data");
    25                 this.isClient = data == null ? true : !Boolean.parseBoolean(data);
    26                 this.isData = data == null ? true : Boolean.parseBoolean(data);
    27             }
    28             this.isIngest = false;
    29     // 5.0版本以上的分支
    30         } else {
    31             List<String> roles = (List<String>) map.get("roles");
    32       // 如果roles列表中不包含"data",则此节点是client
    33             this.isClient = roles.contains("data") == false;
    34       // 如果roles列表中包含"data",则此节点是data
    35             this.isData = roles.contains("data");
    36       // 如果roles列表中包含"ingest",则此节点是ingest
    37             this.isIngest = roles.contains("ingest");
    38         }
    39         Map<String, Object> httpMap = (Map<String, Object>) map.get("http");
    40     // 如果节点数据中包含key:http
    41         if (httpMap != null) {
    42             String addr = (String) httpMap.get("publish_address");
    43       // 如果http数据中包含key:publish_address
    44             if (addr != null) {
    45                 StringUtils.IpAndPort ipAndPort = StringUtils.parseIpAddress(addr);
    46                 this.publishAddress = ipAndPort.ip + ":" + ipAndPort.port;
    47         // 则此节点可以提供http服务,即:http.enabled: true
    48                 this.hasHttp = true;
    49             } else {
    50                 this.publishAddress = null;
    51                 this.hasHttp = false;
    52             }
    53         } else {
    54             this.publishAddress = null;
    55             this.hasHttp = false;
    56         }
    57     }
    View Code

     从上面的源码分析可以得出:如果一个data节点不配置http.enabled:true,则此节点不会被getHttpDataNodes()方法搜索到,那么就会直接抛出异常:No data nodes with HTTP-enabled available

    解决的方法无非两种:

    第一:数据节点配置 http.enabled:true

    第二:绕过filterNonDataNodesIfNeeded()校验,需要settings.getNodesDataOnly()返回false;看下面源码可知,默认es.nodes.data.only是true,在客户端中将其设置为false即可。

     1 /** Clients only */
     2 String ES_NODES_CLIENT_ONLY = "es.nodes.client.only";
     3 String ES_NODES_CLIENT_ONLY_DEFAULT = "false";
     4 
     5 /** Data only */
     6 String ES_NODES_DATA_ONLY = "es.nodes.data.only";
     7 String ES_NODES_DATA_ONLY_DEFAULT = "true";
     8 
     9 /** Ingest only */
    10 String ES_NODES_INGEST_ONLY = "es.nodes.ingest.only";
    11 String ES_NODES_INGEST_ONLY_DEFAULT = "false";
    12 
    13 /** WAN only */
    14 String ES_NODES_WAN_ONLY = "es.nodes.wan.only";
    15 String ES_NODES_WAN_ONLY_DEFAULT = "false";
    16 
    17 ...
    18 
    19 public boolean getNodesDataOnly() {
    20     // by default, if not set, return a value compatible with the other settings
    21   // 默认es.nodes.data.only是true,在客户端中将其设置为false即可
    22     return Booleans.parseBoolean(getProperty(ES_NODES_DATA_ONLY), !getNodesWANOnly() && !getNodesClientOnly() && !getNodesIngestOnly());
    23 }
    24 
    25 public boolean getNodesIngestOnly() {
    26     return Booleans.parseBoolean(getProperty(ES_NODES_INGEST_ONLY, ES_NODES_INGEST_ONLY_DEFAULT));
    27 }
    28 
    29 public boolean getNodesClientOnly() {
    30     return Booleans.parseBoolean(getProperty(ES_NODES_CLIENT_ONLY, ES_NODES_CLIENT_ONLY_DEFAULT));
    31 }
    32 
    33 public boolean getNodesWANOnly() {
    34     return Booleans.parseBoolean(getProperty(ES_NODES_WAN_ONLY, ES_NODES_WAN_ONLY_DEFAULT));
    35 }
    View Code

     最后附上一段"_nodes/http"接口的返回值:

    "nodes": {
        "YgwRm4j1RwiK3jjDHY8Hzw": {
          "name": "node-02",
          "transport_address": "192.168.100.10:9300",
          "host": "192.168.100.10",
          "ip": "192.168.100.10",
          "version": "5.4.0",
          "build_hash": "780f8c4",
          "roles": [
            "master",
            "ingest"
          ],
          "attributes": {
            "ml.enabled": "true"
          },
          "http": {
            "bound_address": [
              "192.168.100.10:9200"
            ],
            "publish_address": "192.168.100.10:9200",
            "max_content_length_in_bytes": 104857600
          }
        }
        ...
    }
    View Code
  • 相关阅读:
    Haskell Interactive Development in Emacs
    Access Java API in Groovy Script
    手工设置Eclipse文本编辑器的配色
    Color Theme of Emacs
    Gnucash的投资记录
    Special Forms and Syntax Sugars in Clojure
    Use w3m as Web Browser
    SSE指令集加速之 I420转BGR24
    【图像处理】 增加程序速度的方法
    TBB 入门笔记
  • 原文地址:https://www.cnblogs.com/yucy/p/7010584.html
Copyright © 2011-2022 走看看