RPC原理与分析

本文深入解析了RPC(远程过程调用)的基本原理与架构组成,详细介绍了客户端与服务端的交互流程,包括通信模型、服务定位及序列化技术,并提供了一个简易的Java实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RPC原理与分析

   RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
       RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

RPC主要应用在分布式系统。如Hadoop生态中hadooop/hbase等中的IPC组件。RPC框架原理是什么呢?

所涉及的模块包括 1、RPC服务器   2、接口    3、实现类   4、服务器提供者模块    5、客户端消费者模块

从下面几个方面思考,仅供参考:

1.通信模型:客户端与服务端通信在Java中一般基于BIO或NIO,HTTP;。

2.过程(服务)定位:使用给定的通信方式,确定具体的目标服务;

3.远程代理对象:本地调用的方法(服务)其实是远程方法的本地代理,因此可能需要一个远程代理对象,对于Java而言,远程代理对象可以使用Java的动态对象实现,封装了调用远程方法调用;

4.序列化,将对象名称、方法名称、参数等对象信息进行网络传输需要转换成二进制传输,这里可能需要不同的序列化技术方案。如:protobuf,avro等。

即:

RPC架构分为三部分:

1)服务提供者,运行在服务器端,提供服务接口定义与服务实现类。

2)服务中心(RPC服务器),运行在服务器端,负责将本地服务发布成远程服务,管理远程服务,提供给服务消费者使用。

3)服务消费者,运行在客户端,通过远程代理对象调用远程服务。



简易实现:

接口定义:Calc.java

package com.rpc;

public interface Calc {

	public int add(int a,int b);
	
	public int sub(int a, int b);
	public int mulitp(int a, int b);
	
	public int did(int a, int b);
	
}

接口实现CalcImpl.java

package com.rpc;

public class CalcImpl implements Calc {

	 public CalcImpl() {
	};
	@Override
	public int add(int a, int b) {
		
		return a+b;
	}

	@Override
	public int sub(int a, int b) {
		return a-b;
	}

	@Override
	public int mulitp(int a, int b) {
		return a *b;
	}

	@Override
	public int did(int a, int b) {
		return a/b;
	}
}
服务接口Server.java

package com.rpc;

public interface Server {

	public void start();
	
	public void stop();
	
	public void register(Class<?> clz, Class<?> impl); //注册服务
	
	public boolean isRunning();
}

服务接口实现ServerCenter.java

package com.rpc;


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 服务接口实现(服务提供者和服务注册)
 * @author Administrator
 *
 */
public class ServerCenter implements Server {

	private  ExecutorService ExecutorService =null;
	private Map<String, Class> maps = null;
	private ServerSocket serverSocket = null;
	private String ip;
	private int port;
	
	private  boolean isRunnable = false; 
	
	
	public ServerCenter(String ip, int port) {
		ExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*5);
		maps = new HashMap<String,Class>();
		try {
			serverSocket = new ServerSocket();
			serverSocket.bind(new InetSocketAddress(ip, port));
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.ip = ip;
		this.port = port;
	}
	
	
	@Override
	public void start() {
		isRunnable = true;
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				while(isRunnable){
					try {
						System.out.println("is started ...");
						Socket socket = serverSocket.accept();
						
						ExecutorService.execute(new SocketTask(socket));
						
					} catch (IOException e) {
						e.printStackTrace();
					}
					
				}
				
			}
		}).start();
	}

	public class SocketTask implements Runnable{
		Socket socket = null;
		ObjectInputStream dis  = null;
		ObjectOutputStream dos = null;
		public SocketTask(Socket socket) {
			
			System.out.println("socket。。。");
			this.socket = socket;
			
			try {
				socket.setKeepAlive(true);
				dis = new ObjectInputStream(socket.getInputStream());
				dos = new ObjectOutputStream(socket.getOutputStream());
				System.out.println("dfdf。。");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			
			
					
					try {
						String serviceName = dis.readUTF();
						String methodName = dis.readUTF();

						Class<?>[] paramTypes = (Class[]) dis.readObject();
						System.out.println(paramTypes[0].getName());
						Object[] params = (Object[])dis.readObject();
						
						System.out.println("serviceName"+serviceName);
						Class<?> clz = maps.get(serviceName);
						System.out.println("clz"+clz.getName());
						System.out.println();
						System.out.println(serviceName + methodName);
						Method method = clz.getDeclaredMethod(methodName, paramTypes);
						
						Object object = method.invoke(clz.newInstance(), params);
						dos.writeObject(object);
						dos.flush();
					}catch (Exception e) {
						e.printStackTrace();
					}
					
				
			
			
		}
		
		public void stopSocket(){
			if(socket.isClosed()){
				try {
					if(dis != null)dis.close();
					if(dos != null)dos.close();
					if(socket != null)dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	@Override
	public void stop() {
		isRunnable = false;
		try {
			if(serverSocket != null){
				serverSocket.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void register(Class<?> clz, Class<?> impl) {
		
		if(maps != null)
			maps.put(clz.getName(), impl);
	}

	@Override
	public boolean isRunning() {
		return isRunnable;
	}

}



服务请求Client.java

package com.rpc;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Client<T> {
	
	@SuppressWarnings("unchecked")
	public static <T> T getRPCProxy(Class<?> clzz, String ip, int port){ //获得远程动态代理对象
		
		return (T)Proxy.newProxyInstance(clzz.getClassLoader(), new Class[]{clzz}, new InvocationHandler() {
			
			ObjectInputStream input = null;
			ObjectOutputStream output = null;
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				Object result = null;
				Socket socket = new Socket();
				socket.connect(new InetSocketAddress(ip, port));
				System.out.println("is conn..");
				if(socket.isConnected())
					socket.setKeepAlive(true);
				
				output = new ObjectOutputStream(socket.getOutputStream());

					output.writeUTF(clzz.getName());
					output.writeUTF(method.getName());
					output.writeObject(method.getParameterTypes());
					output.writeObject(args);
					
					input = new ObjectInputStream(socket.getInputStream());
						result = input.readObject();

				return result;
			}
		});
		
		
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值