温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中RPC的原理是什么

发布时间:2021-08-09 14:10:53 来源:亿速云 阅读:95 作者:Leah 栏目:云计算

这篇文章将为大家详细讲解有关Java中RPC的原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

Java中RPC的原理是什么

package com.wish.RPC;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * RPC原理解析:
 * 服务器端:
 * 1、RPCServer#registService:主要作用就是提供了一个服务注册管理中心,
 *    用来保存被注册服务(如果是dubbo则是分布式服务框架,对应了不同机器的地址及端口发布的服务(dubbo还使用了zookeeper))
 * 2、RPCServer#startServer:开启一个ServerSocket连接(new 一个ServiceTask服务,使用线程循环监听等待),
 *    等待客户端的远程socket连接调用
 * 3、RPCServer#registService:定义一个注册服务接口。即将所有需要注册的服务保存起来,后续ServiceTask需要使用该接口对象,
 *    动态代理调用该接口对象方法,并将方法返回值通过socket网络通信方式,传递给该服务的Client客户端。
 *    
 * 客户端:
 * 1、RPCClient#findService:根据serviceInterface接口名,通过动态代理生成被请求对象及通过InvocationHandler调用远程方法。
 *    其中InvocationHandler里面,通过传入的ip和prot地址,开启一个socket连接,远程发送调用远端RPCServer注册的服务方法
 *    然后通过远端RPCServer,的socket连接,讲返回对象通过socket网络通信传递过来,这样即获取到了远端服务的返回结果。
 *    
 * 启动服务端:
 * 1、TestRPCServer#main:启动服务端,通过server.registService(new HelloWorld()) ;
 *    注册HelloWorld服务方法到RPCServer
 * 2、TestRPCServer#main:通过server.startServer(51234);启动RPCServer,监听来自client的socket请求
 * 
 * 启动客户端:
 * 1、TestRPCClient#main:通过RPCClient.findService("127.0.0.1" , 51234 , IHelloWorld.class);
 *    调用客户端findService,获取HelloWorld对象,接下来即可以像使用本地一样使用远程服务方法
 * 
 * PS:更多源码请访问:http://git.oschina.net/tantexian/wishRPC
 * 
 * @author tantexian<tantexian@qq.com>
 * @since 2016年5月27日 上午9:44:46
 */
public class RPCServer {

	private static final ExecutorService taskPool = Executors.newFixedThreadPool(50);

	/**
	 * 服务接口对象库 key:接口名 value:接口实现
	 */
	private static final ConcurrentHashMap<String, Object> serviceTargets = new ConcurrentHashMap<String, Object>();

	private static AtomicBoolean run = new AtomicBoolean(false);

	/**
	 * 注册服务
	 * 
	 * @param service
	 */
	public void registService(Object service) {
		Class<?>[] interfaces = service.getClass().getInterfaces();
		if (interfaces == null) {
			throw new IllegalArgumentException("服务对象必须实现接口");
		}
		Class<?> interfacez = interfaces[0];
		String interfaceName = interfacez.getName();
		serviceTargets.put(interfaceName, service);
	}

	/**
	 * 启动Server
	 * 
	 * @param port
	 */
	public void startServer(final int port) {
		Runnable lifeThread = new Runnable() {
			@Override
			public void run() {
				ServerSocket lifeSocket = null;
				Socket client = null;
				ServiceTask serviceTask = null;
				try {
					lifeSocket = new ServerSocket(port);
					run.set(true);
					while (run.get()) {
						client = lifeSocket.accept();
						serviceTask = new ServiceTask(client);
						serviceTask.accept();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		};
		taskPool.execute(lifeThread);
		System.out.println("服务启动成功...");
	}

	public void stopServer() {
		run.set(false);
		taskPool.shutdown();
	}

	public static final class ServiceTask implements Runnable {

		private Socket client;

		public ServiceTask(Socket client) {
			this.client = client;
		}

		public void accept() {
			taskPool.execute(this);
		}

		@Override
		public void run() {
			InputStream is = null;
			ObjectInput oi = null;
			OutputStream os = null;
			ObjectOutput oo = null;
			try {
				is = client.getInputStream();
				os = client.getOutputStream();
				oi = new ObjectInputStream(is);
				String serviceName = oi.readUTF();
				String methodName = oi.readUTF();
				Class<?>[] paramTypes = (Class[]) oi.readObject();
				Object[] arguments = (Object[]) oi.readObject();
				System.out.println("serviceName:" + serviceName + " methodName:" + methodName);
				Object targetService = serviceTargets.get(serviceName);
				if (targetService == null) {
					throw new ClassNotFoundException(serviceName + "服务未找到!");
				}

				Method targetMethod = targetService.getClass().getMethod(methodName, paramTypes);
				Object result = targetMethod.invoke(targetService, arguments);

				oo = new ObjectOutputStream(os);
				oo.writeObject(result);
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} finally {
				try {
					if (oo != null) {
						oo.close();
					}
					if (os != null) {
						os.close();
					}
					if (is != null) {
						is.close();
					}
					if (oi != null) {
						oi.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

}

package com.wish.RPC;

import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;

public class RPCClient {

	/** 
     * 根据接口类型得到代理的接口实现 
     * @param <T> 
     * @param host  RPC服务器IP 
     * @param port  RPC服务端口 
     * @param serviceInterface  接口类型 
     * @return  被代理的接口实现 
     */  
    @SuppressWarnings("unchecked")  
    public static <T> T findService(final String host , final int port ,final Class<T> serviceInterface){  
        return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, new InvocationHandler() {  
            @SuppressWarnings("resource")
			@Override  
            public Object invoke(final Object proxy, final Method method, final Object[] args)  
            throws Throwable {  
                Socket socket = null ;  
                InputStream is = null ;  
                OutputStream os = null ;  
                ObjectInput oi = null ;  
                ObjectOutput oo = null ;  
                try {  
                    socket = new Socket(host, port) ;  
                    os = socket.getOutputStream() ;  
                    oo = new ObjectOutputStream(os);  
                    oo.writeUTF(serviceInterface.getName()) ;  
                    oo.writeUTF(method.getName()) ;  
                    oo.writeObject(method.getParameterTypes()) ;  
                    oo.writeObject(args);  

                    is = socket.getInputStream() ;  
                    oi = new ObjectInputStream(is) ;  
                    return oi.readObject() ;  
                } catch (Exception e) {  
                    System.out.println("调用服务异常...");  
                    return null ;  
                }finally{  
                    if(is != null){  
                        is.close() ;  
                    }  
                    if(os != null){  
                        is.close() ;  
                    }  
                    if(oi != null){  
                        is.close() ;  
                    }  
                    if(oo != null){  
                        is.close() ;  
                    }  
                    if(socket != null){  
                        is.close() ;  
                    }  
                }  
            }  
        });   
    }  

}

package com.wish.RPC;

public class HelloWorld implements IHelloWorld {

	@Override
	public String sayHello(String name) {
		return "Hello, " + name;
	}

}

package com.wish.RPC;

public interface IHelloWorld {

	String sayHello(String name);
}

package com.wish.RPC;

public class TestRPCServer {

	public static void main(String[] args) {  

        RPCServer server = new RPCServer() ;  
        server.registService(new HelloWorld()) ;  
        server.startServer(51234) ;  
    }  
}

package com.wish.RPC;

public class TestRPCClient {

	public static void main(String[] args) {  

        IHelloWorld helloWorld =   
            RPCClient.findService("127.0.0.1" , 51234 , IHelloWorld.class) ;  
        String  result = helloWorld.sayHello("tantexian, My blog address is: http://my.oschina.net/tantexian/");  
        System.out.println(result );  

    }  
}

关于Java中RPC的原理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI