hadoop中使用java.util.ServiceLoader

14 篇文章 1 订阅
2 篇文章 0 订阅


在前一篇文章Hadoop源码解析之YARN客户端作业提交流程中,介绍了创建客户端代理阶段用到java.util.ServiceLoader加载

YarnClientProtocolProvider和LocalClientProtocolProvider。

以前从来没有使用过这个类,进去大概看了一下具体的实现。主要是从META-INF/services这个目录下的配置文件加载给定接口或者基类的实现,

ServiceLoader会根据给定的类的full name来在META-INF/services下面找对应的文件,在这个文件中定义了所有这个类的子类或者接口的实现类

,返回一个实例。

下面以一个具体的例子来说明一下ServiceLoader的具体使用,类似Hadoop中的实现。

首先定义一个接口,具体如下:

package ServiceLoaderTest;

public interface MyServiceInterface {

	public String SayHello();
}


该接口有两个子类,分别为ServiceA和ServiceB:

package ServiceLoaderTest;

public class ServiceA implements MyServiceInterface{

	public String SayHello(){
		return "I am ServiceA.";
	}
	
}

package ServiceLoaderTest;

public class ServiceB implements MyServiceInterface{

	public String SayHello() {
		return "I am ServiceB.";
	}
}

需要在META-INF/services下以MyServiceInterface这个类的全名来新建立一个文件,文件中的内容为两个实现类的全名,

其中包名是ServiceLoaderTest,如下:

ServiceLoaderTest.ServiceA
ServiceLoaderTest.ServiceB

所有的实现和配置都已经完成,下面写一个测试类来看一下结果:

package ServiceLoaderTest;
import java.util.ServiceLoader;

public class Test {
	public static void main(String[] args)
	{
		ServiceLoader<MyServiceInterface> sl = ServiceLoader.load(MyServiceInterface.class);
		for(MyServiceInterface s : sl)
		{
			System.out.println(s.SayHello());
		}
	}
}

具体的输出来如下:

I am ServiceA.
I am ServiceB.

测试用例文件的文件结构:


可以看到ServiceLoader可以根据MyServiceInterface把定义的两个实现类找出来,返回一个ServiceLoader的实现,
而ServiceLoader实现了Iterable接口,所以可以通过ServiceLoader来遍历所有在配置文件中定义的类的实例。
Hadoop很多地方就是通过这个机制来根据不同文件的配置来返回不同的具体实现类。


hadoop中Cluster类的相关实现如下:

public class Cluster {

	......
  private static ServiceLoader<ClientProtocolProvider> frameworkLoader =
      ServiceLoader.load(ClientProtocolProvider.class);
  
	......
	
  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.");
    }
  }

META-INF/services的位置为:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
23/07/23 16:19:48 ERROR AsyncProcess: Failed to get region location org.apache.hadoop.hbase.DoNotRetryIOException: java.lang.NoClassDefFoundError: Could not initialize class org.apache.hadoop.hbase.util.ByteStringer at org.apache.hadoop.hbase.client.RpcRetryingCaller.translateException(RpcRetryingCaller.java:241) at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithoutRetries(RpcRetryingCaller.java:214) at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas$RetryingRPC.call(ScannerCallableWithReplicas.java:364) at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas$RetryingRPC.call(ScannerCallableWithReplicas.java:338) at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithRetries(RpcRetryingCaller.java:137) at org.apache.hadoop.hbase.client.ResultBoundedCompletionService$QueueingFuture.run(ResultBoundedCompletionService.java:65) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.apache.hadoop.hbase.util.ByteStringer at org.apache.hadoop.hbase.protobuf.RequestConverter.buildRegionSpecifier(RequestConverter.java:1041) at org.apache.hadoop.hbase.protobuf.RequestConverter.buildScanRequest(RequestConverter.java:492) at org.apache.hadoop.hbase.client.ClientSmallReversedScanner$SmallReversedScannerCallable.call(ClientSmallReversedScanner.java:291) at org.apache.hadoop.hbase.client.ClientSmallReversedScanner$SmallReversedScannerCallable.call(ClientSmallReversedScanner.java:276) at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithoutRetries(RpcRetryingCaller.java:212) ... 7 more
最新发布
07-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值