socket,hadoop的rpc
2017-08-14 本文已影响0人
pamperxg
- socket:
在本地我们用PID来唯一标识一个进程。但是在网络中这样做难以实现。在TCP/IP协议簇中,网络层的ip地址可以唯一标识网络中的主机,传输层的协议+端口可以唯一标识主机中的应用程序。我们利用ip,协议,端口就可以标识网络的进程了。网络中进程通信就可以利用这个标志与其他进程进行交互。使用TCP/IP协议的应用程序通常采用应用编程接口socket来实现网络进程之间的通信。
socket起源于unix,本着一切皆文件的哲学,socket也可以用打开open->write/read->close的模式来操作。socket是一种特殊文件,一些socket函数就是对其进行的操作。 -
rpc(remote procedure call):
RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。 RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯) 。RPC 是一个请求响应模型。客户端发起请求,服务器返回响应(类似于Http的工作方式)。RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。
rpc过程
hadoop中的rpc:
主要用到的技术是动态代理和nio。客户端拿到代理对象就可以进行调用。不同的调用时用不同的协议,也就是实现不同的接口,不同的接口有不同的方法,通过这些不同的方法就可以调到不同的业务。hadoop中有一大堆的通信协议(那些接口),接口下有各种动态代理对象。动态代理对象可以通过socket请求。
反射机制和动态代理:
反射:通过一个字符串就可以剖析一个类,拿到类的详细信息。比如类的定义,实例,还可以调用它的方法。
personClass = Class.forName(className);//获取文件对象
Constructor constructor = personClass.getConstructor(Long.class,String.class);//获取构造函数,参数的个数类型可以确定是哪个构造函数
还可以通过各种getxx获取一个类的详细信息
动态代理:
为其他对象提供一种代理以控制对这个对象的访问。可以在不修改原业务的基础上,基于原业务的方法,进行业务拓展,实现新的业务。
nio:
nio
传统io:
传统io
hadoop中rpc框架(导入hadoop common即可用):
服务端工程:
通信接口:
public interface ClientNamenodeProtocol {
public static final long versionID=1L;
public String getMetaData(String path);
}
业务实现:
import hadooprpc.protocol.ClientNamenodeProtocol;
public class MyNameNode implements ClientNamenodeProtocol{
//模拟namenode的业务方法之一:查询元数据
@Override
public String getMetaData(String path){
return path+": 3 - {BLK_1,BLK_2} ....";
}
}
将业务发布为服务:
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;
import hadooprpc.protocol.ClientNamenodeProtocol;
public class PublishServiceUtil {
public static void main(String[] args) throws Exception {
Builder builder = new RPC.Builder(new Configuration());
builder.setBindAddress("localhost")
.setPort(8888)
.setProtocol(ClientNamenodeProtocol.class)
.setInstance(new MyNameNode());
Server server = builder.build();
server.start();
}
}
客户端工程:
通信接口:
和服务端完全一致(包路径一致,接口中必须定义一个常量:版本号)
请求远程功能客户端:
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import hadooprpc.protocol.ClientNamenodeProtocol;
public class MyHdfsClient {
public static void main(String[] args) throws Exception {
ClientNamenodeProtocol namenode = RPC.getProxy(ClientNamenodeProtocol.class, 1L, new InetSocketAddress("localhost", 8888), new Configuration());
String metaData = namenode.getMetaData("/aaa");
System.out.println(metaData);
}
}