分布式架构基础 三、基于通信及序列化技术实现简易RPC
简介
本次基于Socket通信、Java Serializable技术、动态代理、反射来实现接口的远程调用。
以用户、订单服务为例;
订单相关业务逻辑的处理及数据库交互是在订单服务内的;当用户服务内需要根据用户获取对应订单时,并不需要再与订单数据库交互,而是远程通信调用订单服务的内部实现;
实现逻辑
1. 公共模块 User-API module:
RpcRequest:
import java.io.Serializable;
public class RpcRequest implements Serializable {
private static final long serialVersionUID = -1927810846083059872L;
private String clazz;
private String methodName;
private Object[] args;
private Class<?>[] types;
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Class<?>[] getTypes() {
return types;
}
public void setTypes(Class<?>[] types) {
this.types = types;
}
}
UserService
public interface UserService {
String getUserName(int id);
String getUserAuth(int userId);
}
2. 接口提供方: user-service module
UserServiceImpl
public class UserServiceImpl implements UserService {
@Override
public String getUserName(int id) {
System.out.println("UserServer: execute getUserName " + id);
return "Shen";
}
@Override
public String getUserAuth(int userId) {
System.out.println("UserServer: execute getUserAuth " + userId);
return "Shen Auth";
}
}
MainStarter
public class MainStarter {
public static void main(String[] args) {
int port = 8180;
RpcServerSocket rpcServerSocket = new RpcServerSocket();
rpcServerSocket.publish(port);
}
}
RpcServerSocket
public class RpcServerSocket {
static ExecutorService pool = Executors.newCachedThreadPool();
public void publish(int port) {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
pool.execute(new SocketConnector(socket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
SocketConnector
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
public class SocketConnector implements Runnable {
private Socket socket;
public SocketConnector(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
ObjectInputStream objectInputStream;
ObjectOutputStream objectOutputStream;
try {
objectInputStream = new ObjectInputStream(socket.getInputStream());
Object request = objectInputStream.readObject();
Object response = invoke(request);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(response);
objectOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// close io
}
}
private Object invoke(Object request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
RpcRequest rpcRequest = (RpcRequest) request;
Class clazz = Class.forName(rpcRequest.getClazz());
Method method = clazz.getMethod(rpcRequest.getMethodName(), rpcRequest.getTypes());
String key = clazz.getName() + "." + method.getName();
Object serviceObj = ServiceCache.serviceCache.get(key);
return method.invoke(serviceObj, ((RpcRequest) request).getArgs());
}
}
ServiceCache
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ServiceCache {
static Map<String, Object> serviceCache = new ConcurrentHashMap<>();
static {
UserService userService = new UserServiceImpl();
for (Method method : userService.getClass().getInterfaces()[0].getMethods()) {
String key = userService.getClass().getInterfaces()[0].getName() + "." + method.getName();
serviceCache.put(key, userService);
}
}
}
3. 接口调用方:order-service module
MainStarter
public class MainStarter {
public static void main(String[] args) {
String ip = "127.0.0.1";
int port = 8180;
UserService userService = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, new RpcProxy(ip, port));
String name = userService.getUserName(123);
System.out.println(name);
String auth = userService.getUserAuth(456);
System.out.println(auth);
}
}
RpcProxy
import com.bigshen.user.RpcRequest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class RpcProxy implements InvocationHandler {
private String ip;
private int port;
public RpcProxy(String ip, int port) {
this.ip = ip;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RpcRequest rpcRequest = new RpcRequest();
rpcRequest.setClazz(method.getDeclaringClass().getName());
rpcRequest.setMethodName(method.getName());
rpcRequest.setArgs(args);
rpcRequest.setTypes(method.getParameterTypes());
Object result = RpcNetTransfer.sendRequest(ip, port, rpcRequest);
return result;
}
}
RpcNetTransfer
import com.bigshen.user.RpcRequest;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class RpcNetTransfer {
public static Object sendRequest(String ip, int port, RpcRequest rpcRequest) {
ObjectOutputStream objectOutputStream;
ObjectInputStream objectInputStream;
try {
Socket socket = new Socket(ip, port);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(rpcRequest);
objectOutputStream.flush();
objectInputStream = new ObjectInputStream(socket.getInputStream());
return objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// close io
}
return null;
}
}

浙公网安备 33010602011771号