什么是PRC
PRC是一种远程过程调用协议,可以像调用本地服务一样调用远程的服务,是一种采用客户端/服务器的模式。常见的PRC框架也有很多比如最常用的dubbo等。
RPC能够让本地应用简单、高效地调用远程服务器中的服务。它主要应用在分布式系统、微服务。
代码实例
技术点:Java socket、动态代理、Java对象操作流、反射
接口以及接口实现
/**
* Created by IntelliJ IDEA.
* 服务类接口
*/
public interface IService {
String getTest(String string);
}
/**
* Created by IntelliJ IDEA.
* 服务接口的实现类
*/
public class ServiceImpl implements IService {
@Override
public String getTest(String string) {
return "调用成功了: " + string;
}
}
/**
* Created by IntelliJ IDEA.
*/
public interface ILoginService {
String login(String string);
}
/**
* Created by IntelliJ IDEA.
*/
public class LoginServiceImpl implements ILoginService {
@Override
public String login(String string) {
return string;
}
}
服务端服务注册实例
/**
* Created by IntelliJ IDEA.
* 服务端
*/
public class RpcServer {
private static final HashMap<String, Class<?>> SERVER_MAP = new HashMap<>();
private int port;
public RpcServer(int port) {
this.port = port;
}
/**
* serviceInterface : 接口
* impl:接口实现类
* 将接口服务放到一个HashMap集合中
*/
public RpcServer register(HashMap<Class<?>, Class<?>> hashMap) {
hashMap.forEach((key, value) -> SERVER_MAP.put(key.getName(), value));
return this;
}
/**
* 执行等待
*
*/
public void run() throws IOException {
ServerSocket server = new ServerSocket();
/*打开服务端并设置端口为port*/
server.bind(new InetSocketAddress(port));
/*对象输入流*/
ObjectInputStream input = null;
/*对象输出流*/
ObjectOutputStream output = null;
Socket socket = null;
try {
while (true) {
/*开始接收 线程会进行等待*/
socket = server.accept();
/*输入流 获取到客户端发送来的消息*/
input = new ObjectInputStream(socket.getInputStream());
String serviceName = input.readUTF();
System.out.println("服务名称:" + serviceName);
String methodName = input.readUTF();
System.out.println("服务方法" + methodName);
/*服务的参数列表*/
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
/*接口的Class*/
Object[] arguments = (Object[]) input.readObject();
/*根据服务名称得到该服务的实现类*/
Class serviceClass = SERVER_MAP.get(serviceName);
if (serviceClass == null) {
throw new ClassNotFoundException(serviceName + " not found");
}
/*得到方法*/
Method method = serviceClass.getMethod(methodName, parameterTypes);
/*相当于接口回调*/
Object result = method.invoke(serviceClass.newInstance(), arguments);
/*输出流*/
output = new ObjectOutputStream(socket.getOutputStream());
/*发送*/
output.writeObject(result);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException {
HashMap<Class<?>, Class<?>> hashMap = new HashMap<>();
hashMap.put(IService.class, ServiceImpl.class);
hashMap.put(ILoginService.class, LoginServiceImpl.class);
/*服务端开始注册服务*/
new RpcServer(7777).register(hashMap).run();
}
}
客户端服务调用实例
/**
* Created by IntelliJ IDEA.
* 动态代理
* 客户端调用服务
*/
public class RpcClient<T> implements InvocationHandler {
private Class<T> serviceInterface;
private InetSocketAddress addr;
/**
* serviceInterface:远程服务接口
* ip:远程IP地址
* port:远程端口
*/
public RpcClient(Class<T> serviceInterface, String ip, String port) {
this.serviceInterface = serviceInterface;
this.addr = new InetSocketAddress(ip, Integer.parseInt(port));
}
public T getClientIntance() {
/*传入被代理的类*/
return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class<?>[]{serviceInterface}, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket = null;
ObjectOutputStream output = null;
ObjectInputStream input = null;
try {
/*创建Socket客户端,根据指定地址连接远程服务提供者*/
socket = new Socket();
/*连接服务端*/
socket.connect(addr);
/*将远程服务调用所需的接口类、方法名、参数列表等编码后发送给服务提供者*/
output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(serviceInterface.getName());
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
/*同步阻塞等待服务器返回应答,获取应答后返回*/
input = new ObjectInputStream(socket.getInputStream());
/*返回结果*/
return input.readObject();
} finally {
if (socket != null) {
socket.close();
}
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
}
}
public static void main(String[] args) {
RpcClient client = new RpcClient<>(IService.class, "localhost", "7777");
IService hello = (IService) client.getClientIntance();
/*调用成功 打印返回值*/
System.out.println(hello.getTest("RPC"));
RpcClient loginPrcClient = new RpcClient<>(ILoginService.class, "localhost", "7777");
ILoginService iLoginService = (ILoginService) loginPrcClient.getClientIntance();
/*调用成功 打印返回值*/
System.out.println(iLoginService.login("登录成功了"));
}
}
实例执行结果
服务端执行进入等待
客户端执行
再看服务端变化