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
  • 相关阅读:
    个人阅读作业1
    个人项目-词频统计
    Android中BroadcastReceiver的两种注册方式(静态和动态)详解
    JAVA装饰者模式(从现实生活角度理解代码原理)
    博客维护停止,需要的伙伴们移步http://blog.csdn.net/panhouye
    Android中EditText设置输入条件
    Andriod中自定义Dialog样式的Activity点击空白处隐藏软件盘(Dialog不消失)
    Android中调用文件管理器并返回选中文件的路径
    java中打印实心菱形以及空心菱形的方法
    Android中使用findViewByMe提升组件查找效率
  • 原文地址:https://www.cnblogs.com/yucy/p/7010584.html
Copyright © 2011-2022 走看看