TCP通过 JAVA Socket 实现 RPC 远程调用

RPC 实现技术主要是通过数据的序列化跟反序列话实现的,通过序列化将数据编程二进制流,将数据传送到指定的位置后需要将数据进行反序列化,反序列化
后得到数据。所以这个DEMO主要实现技术是通过SOCKET-ServerSock + ObjectOutputStream实现PRC功能。这里主要有两个技术点,1是使用TCP连接保证连接的
稳定,另外一个是序列化的效率问题。目前流行的两个序列化工具是 Google的Protocal Buffers 效率高,代码侵入性较强,Hessian效率稍低,但是其对各
种编程语言有着良好的支持。且稳定性好。这里的Socket是阻塞式的,可以使用类似于Netty这种非阻塞式的框架用来实现RPC的调用。调用流程如下:1、
消费者通过获取SOcket连接,获取数据传输的线路,然后将数据序列化到服务提供者,服务提供者拿到数据后进行对应的服务调用,然后通过Socket进行数据
的返回。这样就能实现JAVA的RPC
 
 
 
 
 
 
 
 
public class Consumer {//消费者

	public static void main(String[] args) throws Exception{
		String interfaceName = UserService.class.getName();
		
		//需要远程执行的方法
		Method method = UserService.class.getMethod("getUserName", java.lang.String.class);
		//RPC参数
		Object[] arguments = {"441622"};
		//Socket数据通道
		Socket socket = new Socket("172.29.224.87",1234);

		//序列化RPC调用参数
		ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
		output.writeUTF(interfaceName);
		output.writeUTF(method.getName());
		output.writeObject(method.getParameterTypes());
		output.writeObject(arguments);
		
		//获取RPC返回结果
		ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
		Object result = input.readObject();
		System.out.println((String)result);
	}
	
}
public class Provider {//服务提供者
	private static Map<String, Object> servicesPool = new HashMap<>();
	
	public static void main(String[] args) throws Exception{
		init();
		System.out.println("RPC Server 启动");
		
		@SuppressWarnings("resource")
		ServerSocket server = new ServerSocket(1234);
		
		while (true) {
			try {
				//开启SocketServer用于传输数据
				Socket socket = server.accept();

				//反序列化RPC调用数据包括,接口名称,方法名,参数类型,参数i
				ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
				//接口名称
				String interfacename = input.readUTF();
				//方法名
				String methodName = input.readUTF();
				//参数类型
				Class<?>[] paramterType = (Class<?>[])input.readObject();
				//参数
				Object[] params = (Object[]) input.readObject();
				
				//将类加载到内存中
				Class<?> serviceInterfaceclass = Class.forName(interfacename);
				//获取对象,线程安全的方法所以可以预先加载类,可以节省每次创建对内存处理器的消耗
				Object service = servicesPool.get(interfacename);
				//根据方法名跟参数类型确认一个方法
				Method method = serviceInterfaceclass.getMethod(methodName, paramterType);
				//调用方法
				Object result = method.invoke(service, params);
				
				//根据socket通道返回RPC调用数据
				ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
				output.writeObject(result);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void init(){
		servicesPool.put("org.rpc.UserService", new UserServiceImpl());
	}
}
public interface UserService {//服务接口
	
	/**
	 * 获取身份证获取用户姓名
	 * @param helloArg 参数
	 * @return
	 */
	public String getUserName(String idCard);
}

public class  UserServiceImpl implements UserService{//服务实现
	Map<String, String> userPool = new HashMap<String, String>();
	
	public UserServiceImpl() {
		userPool.put("441621", "小张");
		userPool.put("441622", "小王");
		userPool.put("441623", "小刘");
	}
	
	@Override
	public String getUserName(String idCard) {
		if(idCard == null){
			return "参数异常";
		}
		String userName = userPool.get(idCard);
		if(userName != null){
			return userName;
		}else{
			return "用户不存在";
		}
	}
	
}



 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/zsf5201314z/article/details/78116018