1.什么是rpc?
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。
client functions:客户端,请求发送端
client stub:客户端句柄,主要是获取请求的相关数据信息,比如调用的接口名,参数名,参数类型,以及对信息进行序列化,通过socket发送到服务端;
server stub:服务端句柄,主要将client发来的请求信息进行读取并反序列化,然后通过这些信息调用具体的实现类,并将结果序列化后通过sock发送到client。
2.rpc用到什么技术?
(1)JAVA 动态代理(cglib或jdk的proxy类)
(2)socket通信,涉及到IO(io,NIO)
(3) JAVA序列化
3 rpc架构
RPC架构分为三部分:
(1)服务提供者,运行在服务器端,提供服务接口定义与服务实现类。
(2)服务中心,运行在服务器端,负责将本地服务发布成远程服务,管理远程服务,提供给服务消费者使用。
(3)服务消费者,运行在客户端,通过远程代理对象调用远程服务。
4简单rpc实现代码
====================================================================
服务端
====================================================================
服务端业务处理类:
package com.axj.server;
import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.HashMap;
/**
* \* Created with IntelliJ IDEA.
* \* User: axj
* \* Date: 2018/6/14
* \* Time: 14:46
* \* Description:
* \
*/
public class ServerTask implements Runnable {
private Socket socket = null;
private HashMap<String,Class> serviceRegistry;
public ServerTask(Socket socket, HashMap<String, Class> serviceRegistry) {
this.socket=socket;
this.serviceRegistry=serviceRegistry;
}
@Override
public void run() {
ObjectOutputStream outputStream =null;
ObjectInputStream inputStream=null;
try {
inputStream = new ObjectInputStream(socket.getInputStream());
String serviceName=inputStream.readUTF();
String serviceMethod=inputStream.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) inputStream.readObject();
Object[] arguments = (Object[]) inputStream.readObject();
Class serviceClass=serviceRegistry.get(serviceName);
if (serviceClass == null) {
throw new ClassNotFoundException(serviceName + " not found");
}
Method method=serviceClass.getMethod(serviceMethod,parameterTypes);
Object object=method.invoke(serviceClass.newInstance(),arguments);
//
// 3.将执行结果反序列化,通过socket发送给客户端
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(object);
}catch (Exception e){
e.printStackTrace();
}finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端类ServerSocket:
package com.axj.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* \* Created with IntelliJ IDEA.
* \* User: xxx
* \* Date: 2018/6/14
* \* Time: 14:40
* \* Description:
* \
*/
public class RpcServer {
private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private int port;
private String ip;
public RpcServer(String ip,int port){
this.port=port;
this.ip=ip;
}
private static final HashMap<String, Class> serviceRegistry = new HashMap<String, Class>();
public void register(Class serviceInterface, Class impl) {
serviceRegistry.put(serviceInterface.getName(), impl);
}
//
public void start() throws IOException {
ServerSocket serverSocket= new ServerSocket();
serverSocket.bind(new InetSocketAddress(ip,port));
// 1.监听客户端的TCP连接,接到TCP连接后将其封装成task,由线程池执行
while (true){
Socket socket=serverSocket.accept();
executor.execute(new ServerTask(socket,serviceRegistry));
}
}
}
服务端启动类:
public class RpcServerTest {
public static void main(String[] args) {
try {
RpcServer rpcServer=new RpcServer("localhost",8088);
rpcServer.register(HelloService.class, HelloServiceImpl.class);
rpcServer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
=====================================================================
客户端
=====================================================================
客户端动态代理类:
package com.axj.client;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
* \* Created with IntelliJ IDEA.
* \* User: axj
* \* Date: 2018/6/14
* \* Time: 14:28
* \* Description:
* \
*/
public class RpcClientPoxy {
public static Object getRemoteProxyObj(final Class<?> serviceInterface,final InetSocketAddress addr) {
return Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
Socket socket=null;
ObjectOutputStream outputStream=null;
ObjectInputStream inputStream=null;
Object object=null;
try {
socket=new Socket();
socket.connect(addr);
outputStream=new ObjectOutputStream(socket.getOutputStream());
outputStream.writeUTF(serviceInterface.getName());
outputStream.writeUTF(method.getName());
outputStream.writeObject(method.getParameterTypes());
outputStream.writeObject(args);
inputStream=new ObjectInputStream(socket.getInputStream());
object=inputStream.readObject();
}catch (Exception e){
e.printStackTrace();
} finally {
if (socket != null) socket.close();
if (outputStream != null) outputStream.close();
if (inputStream != null) inputStream.close();
}
return object;
}
});
}
}
客户端Socket
package com.axj;
import com.axj.client.RpcClientPoxy;
import com.axj.service.HelloService;
import java.net.InetSocketAddress;
/**
* \* Created with IntelliJ IDEA.
* \* User: axj
* \* Date: 2018/6/14
* \* Time: 15:38
* \* Description:
* \
*/
public class RpcClientTest {
public static void main(String[] args) {
HelloService helloService= (HelloService) RpcClientPoxy.getRemoteProxyObj(HelloService.class, new InetSocketAddress("localhost",8088));
System.out.println(helloService.sayHeelo("xxxxxxx"));
System.out.println(helloService.sayBye());
}
}
远程service接口
public interface HelloService {
String sayHeelo(String string);
String sayBye();
}
远程service接口实现类
public class HelloServiceImpl implements HelloService { @Override public String sayHeelo(String string) { System.out.println(string); return string; } @Override public String sayBye() { System.out.println("bye bye"); return "bye bye" ; } }