Hadoop的mapreduce.framework.name屬性原理

    配置Tez引擎時,只要我們把Tez的jars和配置文件路徑添加進HADOOP_CLASSPATH裏,然後通過設置mapred-site.xml文件的mapreduce.framework.name屬性爲yarn-tez,就可以替換默認的MR框架爲tez引擎。
    其中的奧妙在於使用了JDK6+的一個特性ServiceLoader類。其爲JDK實現了一個依賴注入的機制。
    ServiceLoader可以在加載jar包的時候,構建jar包配置的指定接口的類實現對象,從而提供一個插件實現的作用。具體到這個mapreduce.framework.name屬性的實現,在hadoop-mapreduce-client-jobclient-x.x.x.jar包裏,路徑META-INF\services下,有一個org.apache.hadoop.mapreduce.protocol.ClientProtocolProvider的文件,裏面有這樣一行

org.apache.hadoop.mapred.YarnClientProtocolProvider

    類似地,tez-mapreduce也提供了這樣的文件,內容爲

org.apache.tez.mapreduce.client.YarnTezClientProtocolProvider

    在Cluster類初始化的時候,

private static ServiceLoader frameworkLoader = ServiceLoader.load(ClientProtocolProvider.class);

    這樣在frameworkLoader就把這兩個類加載起來。注意到ServiceLoader的實現了Iterable接口,內部返回的iterator實現了延遲和緩存機制。

      然後會調用initialize方法。

  private void initialize(InetSocketAddress jobTrackAddr, Configuration conf)
      throws IOException {

    synchronized (frameworkLoader) {
      for (ClientProtocolProvider provider : frameworkLoader) {
        LOG.debug("Trying ClientProtocolProvider : "
            + provider.getClass().getName());
        ClientProtocol clientProtocol = null; 
        try {
          if (jobTrackAddr == null) {
            clientProtocol = provider.create(conf);
          } else {
            clientProtocol = provider.create(jobTrackAddr, conf);
          }

          if (clientProtocol != null) {
            clientProtocolProvider = provider;
            client = clientProtocol;
            LOG.debug("Picked " + provider.getClass().getName()
                + " as the ClientProtocolProvider");
            break;
          }
          else {
            LOG.debug("Cannot pick " + provider.getClass().getName()
                + " as the ClientProtocolProvider - returned null protocol");
          }
        } 
        catch (Exception e) {
          LOG.info("Failed to use " + provider.getClass().getName()
              + " due to error: " + e.getMessage());
        }
      }
    }

    if (null == clientProtocolProvider || null == client) {
      throw new IOException(
          "Cannot initialize Cluster. Please check your configuration for "
              + MRConfig.FRAMEWORK_NAME
              + " and the correspond server addresses.");
    }
  }

        YarnClientProtocolProvider的create是這樣實現的。

public class YarnClientProtocolProvider extends ClientProtocolProvider {

  @Override
  public ClientProtocol create(Configuration conf) throws IOException {
    if (MRConfig.YARN_FRAMEWORK_NAME.equals(conf.get(MRConfig.FRAMEWORK_NAME))) {
      return new YARNRunner(conf);
    }
    return null;
  }

  @Override
  public ClientProtocol create(InetSocketAddress addr, Configuration conf)
      throws IOException {
    return create(conf);
  }

  @Override
  public void close(ClientProtocol clientProtocol) throws IOException {
    // nothing to do
  }

}
        這樣就實現了插件類的方法。

        參考文章:how mapreduce.framework.name is hooked into YARN MR2


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章