2012-12-17 76 views
0

我正在尝试使用Hadoop IPC在IPC之间创建一个简单的父子进程。事实证明,程序执行并打印结果,但不会退出。这是它的代码。Hadoop RPC服务器不会停止

interface Protocol extends VersionedProtocol{ 
    public static final long versionID = 1L; 
    IntWritable getInput(); 
} 

public final class JavaProcess implements Protocol{ 
    Server server; 

    public JavaProcess() { 
    String rpcAddr = "localhost"; 
    int rpcPort = 8989; 
    Configuration conf = new Configuration(); 
    try { 
    server = RPC.getServer(this, rpcAddr, rpcPort, conf); 
    server.start(); 

    } catch (IOException e) { 
    e.printStackTrace(); 
    } 
} 

public int exec(Class klass) throws IOException,InterruptedException { 
    String javaHome = System.getProperty("java.home"); 
    String javaBin = javaHome + 
     File.separator + "bin" + 
     File.separator + "java"; 
    String classpath = System.getProperty("java.class.path"); 
    String className = klass.getCanonicalName(); 

    ProcessBuilder builder = new ProcessBuilder(
     javaBin, "-cp", classpath, className); 

    Process process = builder.start(); 
    int exit_code = process.waitFor(); 
    server.stop(); 

    System.out.println("completed process"); 
    return exit_code; 
} 

public static void main(String...args) throws IOException, InterruptedException{ 
    int status = new JavaProcess().exec(JavaProcessChild.class); 
    System.out.println(status); 
} 

@Override 
public IntWritable getInput() { 
    return new IntWritable(10); 
} 

@Override 
public long getProtocolVersion(String paramString, long paramLong) 
    throws IOException { 
    return Protocol.versionID; 
} 
} 

这里是子进程类。不过我已经意识到这是由于服务器端的RPC.getServer()导致它的罪魁祸首。这是一些已知的hadoop错误,或者我失去了一些东西?

public class JavaProcessChild{ 

    public static void main(String...args){ 
    Protocol umbilical = null; 
    try { 
     Configuration defaultConf = new Configuration(); 
     InetSocketAddress addr = new InetSocketAddress("localhost", 8989); 
     umbilical = (Protocol) RPC.waitForProxy(Protocol.class, Protocol.versionID, 
      addr, defaultConf); 
     IntWritable input = umbilical.getInput(); 

     JavaProcessChild my = new JavaProcessChild(); 

     if(input!=null && input.equals(new IntWritable(10))){ 
     Thread.sleep(10000); 
     } 
     else{ 
     Thread.sleep(1000); 
     } 
    } catch (Throwable e) { 
     e.printStackTrace(); 
    } finally{ 
     if(umbilical != null){ 
     RPC.stopProxy(umbilical); 
     } 
    } 
} 
} 

回答

1

我们通过邮件对此进行了整理。但我只想给我两毛钱给公众:

因此,不死在那里的线程(因此不让主线程完成)是org.apache.hadoop.ipc.Server$Reader。 原因是,readSelector.select();的执行是不可中断的。如果仔细观察调试器或线程转储,即使主线程已被清理,它也会永远等待该调用。

两个可能的解决方法:

  • 使读者线程一个守护进程(不是很爽,因为选择 不会正确地清理,但这一过程将结束)
  • 明确地关闭“ readSelector“,当中断线程池时

但是,这是Hadoop中的一个错误,我没有时间查看JIRA。也许这已经是固定的,在YARN,旧的IPC被protobuf和节俭取代。

顺便说一句,这也是平台依赖于选择器的实现,我在debian/windows系统上观察过这些僵尸,但在redhat/solaris上没有。

如果有人对Hadoop 1.0补丁感兴趣,请给我发电子邮件。我将在不久的将来梳理JIRA错误,并在此处编辑更多信息。 (无论如何,这可能是固定的)。