技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 系统架构 --> 如何在Hadoop集群运行jni程序

如何在Hadoop集群运行jni程序

浏览:2261次  出处信息
    Hadoop是基于Java的数据计算平台,引入第三方库,例如C语言实现的开发包将会大大增强数据分析的效率和能力。 阿里巴巴内部使用的分词软件(用C++实现的,以下简称WS包)是日常工作中最基本的软件包,通过Java的jni机制,笔者将WS包成功的运行在Hadoop上,深受很多部门的欢迎。下面借这个例子介绍Hadoop上jni程序的开发过程。

     首先,简单介绍一下WS包中的调用接口和基本结构。  WS包包括词典文件A.dict,对外提供静态链接库文件libWS.a。WS.h如下:

 
1 Class WS{
2   
3         int init(const char* name);
4   
5         int segment(char* dest, char* src, int len,int kind);
6 }

我们的方案是首先生成jni的原型定义,然后根据原型定义,来包装WS类的接口,最后生成可在tasknode上运行的jni程序包。结构如下图所示

    第一步,我们先使用java的jni技术,生成C的原型接口(prototype),然后编写Wsjni.java 文件,这是为云梯程序提供的类文件,其中libwsjni.so 就是wrapper类的动态链接库:

 
01 Class Wsjni{
02   
03         Public Native int init(String conf);
04   
05         Public Native String segment(String src,int kind);
06   
07         Public Native void close(); //用于显示的释放内存
08   
09         Static{
10   
11                 System.LoadLibrary(“libwsjni.so”); // load 链接库
12         }
13 }

产生class文件

 
1 Javac -d class Wsjni.java

这样就可以生成C的原型接口头文件Wsjni.h

 
1 javah -classpath ./class ws.Wsjni

Wsjni.h里面的有函数的原型声明,例如:

 
1 JNIEXPORT jint JNICALL Java_ws_Wsjni_ws_1init__Ljava_lang_String_2(JNIEnv *, jobject, jstring);

第二步,根据Wsjni.h实现wrapper类。需要阅读sun公司编写的jni的规范来实现应用,具体不在这里赘述。在Makefile中链接静态库libWs.a,从而生成一个动态的链接库libwsjni.so ,

 
1 g++ -g -o ./class/libwsjni.so -fPIC -shared -Wl,-soname,./class/libWsjni.so ws_Wsjni.cpp -I./include -Wl,-Bstatic -lWs -L./lib/ -Wl,-Bdynamic

我们的wrapper类就写好了。我们可以通过java的程序来测试验证jni是否正确。

 
01 Import Wsjni;
02   
03 Class Test{
04   
05         Public static void main(){
06   
07                 Wsjni ws=new Wsjni();
08   
09                 Ws.init(“taobao.conf”);
10   
11                 Ws.segment("你好淘宝", 1);
12   
13                 Ws.close();
14         }
15 }

运行命令是:

 
1 Java -cp ./class -D java.liabray.path=./class Test

为了在Hadoop上运行Ws包,需要制作两个jar包,一个是wsjni.jar, 通过-libjar选项提供class文件; 一个用于Hadoop集群运行,ws.jar里面放了Ws包运行时需要的资源文件,包括链接库和词典文件。Wsjni.jar中的文件是:

 
1 ./ Wsjni.class

Ws.jar 中的文件是:

 
1 ./A.dict
2 ./libwsjni.so
3 ./taobao.conf

第三步,在Hadoop上调用Wsjni。Hadoop有很特殊的文件系统,这里笔者针对性介绍一下DistributeCache的机制。Hadoop可以将HDFS的一些文件分发到运行的某台机器的工作目录下,并按照一定的逻辑解压。通过以下API实现:

 
1 DistributedCache.addCacheArchive(“hdfs://file_path/ws.jar#ws”,conf);

上面的API将ws.jar分发到tasknode上,并解压到工作目录的link目录下。Ws.jar包含ws相关的资源文件。在tasknode上,每个task工作目录下的文件是:

 
1 Jars/
2 Jars/yourJob.cass
3 ws/
4 ws/A.dict
5 ws/libwsjni.so
6 ws/taobao.conf

这样的目录结构,使得程序访问文件的路径一目了然,当调用者需要调用WS的接口时,词典A.dict和libwsjni.so 都在./ws 目录下。

因此,调用者的代码如下:

 
01 Mapper(){
02   
03         Wsjni wsjni=new Wsjni();
04   
05         Public void configure( ){
06   
07                 Wsjni.init("./ws/taobao.conf”,1);
08   
09         }
10   
11         Public mapper(){
12   
13                 Wsjni.segment(sentence,2);
14   
15         }
16   
17         Public close(){
18   
19                 Wsjni.close();
20   
21         }
22   
23 }
24   
25 Run(){
26   
27         Jobconf.set(“java.library.path”,”./ws”);
28   
29         DistributedCache.addCacheArchive(“hdfs://file_path/ws.jar#ws”,conf);
30   
31 }

需要设置 lava.library.path的原因是,java虚拟机需要找到libwsjni.so存放的路径。有必要通过ldd 命令看看so依赖哪些库,保证这些库和Hadoop集群的tasknode中的库的版本一致。

罗嗦了这么多,都是细节问题,还得各位手动再做一遍,Hadoop的程序不太方便调试,但是遇到的困难越多,收获的越多。呵呵。

欢迎各位不吝赐教。

建议继续学习:

  1. Facebook的实时Hadoop系统    (阅读:10584)
  2. hadoop rpc机制 && 将avro引入hadoop rpc机制初探    (阅读:5104)
  3. Hadoop的map/reduce作业输入非UTF-8编码数据的处理原理    (阅读:4598)
  4. Hadoop超级安装手册    (阅读:3979)
  5. 百度是如何使用hadoop的    (阅读:3918)
  6. Hadoop集群间Hadoop方案探讨    (阅读:3744)
  7. 使用hadoop进行大规模数据的全局排序    (阅读:3449)
  8. Hadoop安装端口已经被占用问题的解决方法    (阅读:2960)
  9. 分布式计算平台Hadoop 发展现状乱而稳定的解读    (阅读:2804)
  10. Hadoop现有测试框架探幽    (阅读:2797)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1