手动实现RPC远程调用

java中的RPC核心思想就是:socket编程、传输Object、动态代理

package com.lala.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.ServerSocket;
import java.net.Socket;

public class RpcFramework
{
	/**
	 * 初始化一个服务端socket,一直监听客户端请求,当有请求时,依次读取 方法名称,方法参数类型,方法参数,
	 * 根据这些信息在service上找到相应的method,然后,service方法上执行对应的方法,把方法返回值传输回去
	 * @param service 暴露的服务接口实现类
	 * @param port	  绑定的端口
	 * @throws Exception
	 */
	@SuppressWarnings("resource")
	public static void publish(final Object service, final int port)throws Exception
	{
		final ServerSocket server = new ServerSocket(port);
		System.out.println("rpc server is start on port : " + port);
		while(true)
		{
			final Socket client = server.accept();
			new Thread(() -> {
				ObjectInputStream input = null;
				ObjectOutputStream output = null;
				try
				{
					input = new ObjectInputStream(client.getInputStream());
					output = new ObjectOutputStream(client.getOutputStream());

					String methodName = input.readUTF();
					Class<?>[] pamTypes = (Class<?>[])input.readObject();
					Object[] args = (Object[])input.readObject();

					Method method = service.getClass().getMethod(methodName, pamTypes);
					Object obj = method.invoke(service, args);

					output.writeObject(obj);
				}
				catch(Throwable e)
				{
					try {
						output.writeObject(e);
					} catch (Exception e1){
						e1.printStackTrace();
					}
				}
				finally
				{
					closeStream(output);
					closeStream(input);
					closeStream(client);
				}
			}).start();
		}
	}

	/**
	 * 根据host, port初始化一个socket,然后传输 方法名称,方法参数类型,方法参数,最后获取服务器返回的结果,就是方法执行的返回值
	 * @param clazz 调用的接口
	 * @param host	远程服务器
	 * @param port  端口
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T reference(final Class<T> clazz, final String host, final int port)throws Exception
	{
		return (T)Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler()
		{
			public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
			{
				final Socket client = new Socket(host, port);

				ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream());

				/**
				 * 往服务端发送方法名称,参数类型,参数
				 */
				output.writeUTF(method.getName());
				output.writeObject(method.getParameterTypes());
				output.writeObject(args);

				ObjectInputStream input = new ObjectInputStream(client.getInputStream());

				try
				{
					/**
					 * 获取服务端,方法执行的结果
					 */
					Object res = input.readObject();
					if(res instanceof Throwable)
					{
						throw (Throwable)res;
					}
					return res;
				}catch(Throwable e)
				{
					throw e;
				}
				finally
				{
					closeStream(input);
					closeStream(output);
					closeStream(client);
				}
			}
		} );
	}

	private static void closeStream(AutoCloseable stream)
	{
		if(stream != null)
		{
			try
			{
				stream.close();
			}catch(Exception e)
			{
				//ignore
			}
		}
	}
}

此处写一个测试接口:

package com.lala.rpc;

public interface UserService
{
	public String getNameById(String id);
}

接口的实现类:

package com.lala.rpc;

public class UserServiceImpl implements UserService
{
	public String getNameById(String id)
	{
		return "hello " + id;
	}
}

服务端:

package com.lala.rpc;

public class Server
{
	public static void main(String[] args) throws Exception
	{
		UserService userService = new UserServiceImpl();
		RpcFramework.publish(userService, 9999);
	}
}

调用客户端:

package com.lala.rpc;

public class Client
{
	public static void main(String[] args) throws Exception
	{
		UserService userService = RpcFramework.reference(UserService.class, "127.0.0.1", 9999);
		System.out.println(userService.getNameById("100"));
	}
}
时间: 2024-10-22 20:26:29

手动实现RPC远程调用的相关文章

测试JSON RPC远程调用(JSON客户端)

#include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSon客户端 Author: Kagula LastUpdateDate:2014-05-17 描述:测试JSON RPC远程调用 测试环境:Windows 8.1.Visual Studio 2013 SP1 curl-7.36.0 CPPCMS 1.0.4(JSON服务端) Java Servlet (JSON服务端) */ sta

測试JSON RPC远程调用(JSONclient)

#include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Author: Kagula LastUpdateDate:2014-05-17 描写叙述:測试JSON RPC远程调用 測试环境:Windows 8.1.Visual Studio 2013 SP1 curl-7.36.0 CPPCMS 1.0.4(JSON服务端) Java Servlet (JSON服务端) *

徒手撸框架--实现 RPC 远程调用

微服务,已经是每个互联网开发者必须掌握的一项技术.而 RPC 框架,是构成微服务最重要的组成部分之一.趁最近有时间.又看了看 dubbo 的源码.dubbo 为了做到灵活和解耦,使用了大量的设计模式和 SPI机制,要看懂 dubbo 的代码也不太容易. 按照<徒手撸框架>系列文章的套路,我还是会极简的实现一个 RPC 框架.帮助大家理解 RPC 框架的原理. 广义的来讲一个完整的 RPC 包含了很多组件,包括服务发现,服务治理,远程调用,调用链分析,网关等等.我将会慢慢的实现这些功能,这篇文章

rpc远程调用开发

RPC即远程过程调用,适用于集群管理,集群节点就是RPCServer,而我们发起远程调用的web服务器就是RPCClient.所以是少数rpcClient(可能一个)对多个RPCServer(集群节点). 今天讲述的RPC开发希望实现这样一个效果,在RPCClient上(也就是web服务器)执行一条shell命令,要求指定的远程主机执行指定的命令.命令的格式如下 rpc_client address command 比如 ./ssan_client 192.168.1.1 vmstat 希望这条

dubbo集成zookeeper rpc远程调用

注:下面使用dubbo依赖的是zookeeper注册中心,这里没有详细的介绍.在配置之前,请自行准备好zookeeper环境. 后续如果写zookeeper的配置会补放链接 添加Gradle依赖 compile group: 'com.alibaba', name: 'dubbo', version: '2.5.10'//dubbo compile group: 'org.apache.zookeeper', name: 'zookeeper', version: '3.3.3'//zookee

[转]Linux下C语言-RPC远程调用编程rpcgen用法

在查看libc6-dev软件包提供的工具(用 dpkg -L libc6-dev 命令)的时候,发现此软件包提供了一个有用的工具rpcgen命令.通过rpcgen的man手册看到此工具的作用是把RPC源程序编译成C语言源程序,从而轻松实现远程过程调用.下面的例子程序的作用是客户端程序取中心服务器上时间的,编程过程如下:先编写一个 “ RPC 语言 ” ( RPC Language ( Remote Procedure Call Language ) ) 的源文件 test.x ,文件后缀名为 x

go语言net包rpc远程调用的使用

一.基于http的RPC 服务端: package main; import ( "net/rpc" "net/http" "log" ) //go对RPC的支持,支持三个级别:TCP.HTTP.JSONRPC //go的RPC只支持GO开发的服务器与客户端之间的交互,因为采用了gob编码 //注意字段必须是导出 type Params struct { Width, Height int; } type Rect struct{} //函数必须

RPC远程调用概念 &amp;amp;&amp;amp; demo实例

RPC是指远程过程调用,直观说法就是A通过网络调用B的过程方法. 也就是说两台serverA.B,一个应用部署在Aserver上,想要调用Bserver上应用提供的函数/方法,因为不在一个内存空间,不能直接调用.须要通过网络来表达调用的语义和传达调用的数据. 为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完毕的需求,比方比方不同的系统间的通讯,甚至不同的组织间的通讯.因为计算能力须要横向扩展.须要在多台机器组成的集群上部署应用 首先要解决寻址的问题,也就是说,Aserv

RPC远程调用概念 &amp;&amp; demo实例

RPC是指远程过程调用,直观说法就是A通过网络调用B的过程方法.也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据. 为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯.由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用 首先要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的