分享

使用hadoop2.x RPC框架通讯

本帖最后由 PeersLee 于 2016-3-23 15:51 编辑
问题导读:

1、hadoop RPC 简介

2、远程过程调用框架底层实现机制介绍

3、hadoop RPC框架封装思想(原始+改进)

4、hadoop中的RPC应用实例demo





解决方案:

环境:
系统:windows 7 + centos 6.5

软件:jdk 7 + eclipse + hadoop 2.4.1

--------------------------------------------------------------------------------------


hadoop RPC 简介:

RPC的全称为远程过程调用。由于Hadoop是一个分布式系统,因此底层的通信库也就必须实现RPC的基础功能。Hadoop RPC 在整个hadoop中扮演着底层通信模块的角色,举例而言NN和DN、AM和RM之间的通信和协调都是Hadoop RPC来完成的。熟悉使用Hadoop RPC可以加深我们对Hadoop各个模块之间通信过程的理解,也能让我们实现一些自己想要的分布式的小功能。

----------------------------------------------------------------------------------------

远程过程调用框架底层实现机制介绍:

我们要实现客户端的LoginController去控制服务端中的LoginService要通过网络通信的方式。首先,LoginController将他要调用LoginService的一些相关信息传递给socket client,告诉client他要调用LoginService的login方法并将username和passwd传递给他,之后通过socket client 将信息传递给socket service,socket service 反射实例调用目标方法,并调用获取返回的方法再将该方法反向传递给socket client,socket client 返回来的方法交个给LoginController。


2016-02-27_165925.png



-------------------------------------------------------------------------------------------------------------------------------------------------

hadoop RPC 框架实现效果:

Controller 通过一个工具类就拿到一个代理对象,这个代理对象可以使LoginService就像在客户端本地一样的效果直接调用 LoginService的l ogin()方法,就像在本地调用一样,因为通过网络通信实现的远程过程调用已经被RPC通过动态代理和反射技术封装好了,我们只要只用即可。

---------------------------------------------------------------------------------------------------------------------------------------------------

hadoop RPC框架封装思想:

LoginController中的代理对象proxy要有LoginServicempl中的要实现的方法,所以就意味着那边的LoginServiceImpl和这里的 LoginController中要使用的代理对象proxy 实现同一个接口就可以了,其实这个代理对象proxy 要代理的 就是客户端中的socket。当这个代理对象proxy 调用接口中的 Login()方法之后,socket将调用一个sendMsg()方法将一些登录信息(username,passwd)发送到服务端的socket中,之后服务端中的socket中的receiveMsg()方法将接受这些信息,之后将反射出实例对象,调用方法,返回信息,客户端接受信息,将返回的信息传递给LoginController。hadoop RPC就是将这个过程封装起来。
2016-02-27_181019.png

---------------------------------------------------------------------------------------------------------------------------------------------------

改进:

当服务端直接拿到Impl的实例对象时,如果存在逻辑控制代码(例如权限验证),显然这样是不合适的,所以我们使用一个动态代理对象去代理这个Impl的实例对象,这样就可以在实现业务逻辑代码之前就拦截到相关处理。这样就在服务端 实现了控制 和 业务的分离。



2016-02-27_181228.png

----------------------------------------------------------------------------------------------------------------------------------------------------

hadoop中的RPC应用实例demo:

服务端代码:

LoginServiceInterface:

[mw_shl_code=java,true]package peerslee.hadoop.rpc;

public interface LoginServiceInterface {
        
        public static final long versionID=1L;
        public String login(String username,String password);

}
[/mw_shl_code]

LoginServiceImpl:
[mw_shl_code=java,true]package peerslee.hadoop.rpc;

public class LoginServiceImpl implements LoginServiceInterface {

        @Override
        public String login(String username, String password) {
               
                return username + " logged in successfully!";
        }

}
[/mw_shl_code]

Starter:
[mw_shl_code=java,true]package peerslee.hadoop.rpc;

import java.io.IOException;

import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Builder;
import org.apache.hadoop.ipc.RPC.Server;

public class Starter {

        public static void main(String[] args) throws HadoopIllegalArgumentException, IOException {
               
               
                Builder builder = new RPC.Builder(new Configuration());
               
                builder.setBindAddress("master).setPort(10000).setProtocol(LoginServiceInterface.class).setInstance(new LoginServiceImpl());
               
                Server server = builder.build();
               
                server.start();

        }

}[/mw_shl_code]

----------------------------------------------------------------------

客户端代码:

LoginServiceInterface:
[mw_shl_code=java,true]package peerslee.hadoop.rpc;

public interface LoginServiceInterface {
        public static final long versionID=1L;
        public String login(String username, String passwd);
}
[/mw_shl_code]

LoginController:
[mw_shl_code=java,true]package peerslee.hadoop.rpc;

import java.net.InetSocketAddress;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;

public class LoginController {
        public static void main(String[] args) throws Exception {
                LoginServiceInterface proxy =  RPC.getProxy(LoginServiceInterface.class, 1L, new InetSocketAddress("master", 10000), new Configuration());
               
                String result = proxy.login("peerslee", "123456");
               
                System.out.println(result);
        }
}
[/mw_shl_code]

----------------------------------------------------------------------------------------------

然后服务端和客户端所在包(就是项目内路径)必须一致,否则会出现如下错误:

2016-02-27_115859.png









已有(1)人评论

跳转到指定楼层
Mr.k 发表于 2017-1-13 09:18:32
挺好的学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条