RPC:远程调用服务
假如有两个不同的项目A&B,A项目如果想调用B项目的接口,需要使用RPC。类似于webServers
主要应用于一些分布式的系统。
RPC主要是两个进程间的的调用。不在同一个JVM见。无法拿到其他项目的实例。
RPC和soap协议的区别就是PRC更加精简。
socket是实现远程调用的关键。
1. 生成调用端socket程序动态代理对象
2. 通过proxy调用业务方法
3. 调用socket的请求方法
4. 发送调用请求
5. 生成impl的动态代理对象
6. 通用业务代理对象的具体业务方法
7. 获取调用结果
8. 返回调用结果
9. socket返回结果
简单的RPC实例
新建maven project
添加依赖
maven的中心库(http://www.mvnrepository.com)中搜索hadoop
找到
Apache Hadoop Common
<!-- http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.1</version>
</dependency>
Apache Hadoop HDFS
<!-- http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.1</version>
</dependency>
Hadoop Mapreduce Client Core
<!-- http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-mapreduce-client-core -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.1</version>
</dependency>
Hadoop Mapreduce Client Common
<!-- http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-mapreduce-client-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-common</artifactId>
<version>2.7.1</version>
</dependency>
一般开发mapreduce程序只需要这四个依赖。
将这四个依赖复制到pom.xml中。
- 添加hadoop.version
<properties>
<hadoop.version>2.7.1</hadoop.version>
</properties>
并将刚才添加的依赖的版本全都用 ${hadoop.version}
来代替。
- 在src/main/java包下新建一个接口
public interface IRPCInterface {
public static final long versionID = 1;
public String test(String s);
}
在hadoop1.X中,可以不指定versionID,但是如果使用hadoop2.X时必须要指定。这个ID和后面要编写的Client中的ID要保持一致。
- 新建一个server端
package com.edu.hadoop;
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.Server;
public class RPCServer implements IRPCInterface {
public static void main(String[] args) throws Exception{
Server server = new RPC.Builder(new Configuration())
.setBindAddress("localhost")//本机地址,也可以换成IP
.setPort(8888)
.setInstance(new RPCServer())
.setProtocol(IRPCInterface.class)
.build();
server.start();
}
public String test(String s) {
System.out.println("RPCServer.test()");
return "rpc "+s;
}
}
开启服务端。
- 新建一个Client端
package com.edu.hadoop;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
public class RPCClient {
public static void main(String[] args) throws Exception {
IRPCInterface proxy = RPC.getProxy(IRPCInterface.class, 1,//这里要和接口中的ID保持一直
new InetSocketAddress("localhost", 8888), new Configuration());
String s = proxy.test("client");
System.out.println("client======>"+s);
}
}
启动客户端,可以得到正确的从服务端修改后的字符串,服务端中也有相应的输出,测试成功。
两个项目之间的RPC通信
新建一个接口
package com.hadoop.rpc;
public interface LoginServiceInterface {
public static final long versionID = 1L;
public String login(String username, String password);
}
一个业务方法,实现这个接口
package com.hadoop.rpc;
public class LoginServiceImpl implements LoginServiceInterface {
public String login(String username, String password) {
// TODO Auto-generated method stub
return username + "登陆成功!";
}
}
服务端代码
package com.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 Exception {
Builder builder = new RPC.Builder(new Configuration());
builder.setBindAddress("localhost").setPort(10000).setProtocol(LoginServiceInterface.class).setInstance(new LoginServiceImpl());
Server server = builder.build();
server.start();
}
}
另一个项目写客户端
将LoginServiceInterface接口也放入这个项目
编写客户端代码
package com.hadoop.rpc;
import java.io.IOException;
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 = (LoginServiceInterface) RPC.getProxy(
LoginServiceInterface.class, 1L, new InetSocketAddress(
"localhost", 10000), new Configuration());
String result = proxy.login("devil", "123456");
System.out.println(result);
}
}