java實現一個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 {

	public static void export(final Object service, final Class interfaceClazz, int port) throws Exception {

		System.out.println("Export service " + service.getClass().getName() + " on port " + port);

		ServerSocket server = new ServerSocket(port);
		for (;;) {
			final Socket socket = server.accept();

			new Thread(new Runnable() {
				public void run() {
					try {
						ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
						String interfaceName = input.readUTF();
						String methodName = input.readUTF();
						Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
						Object[] arguments = (Object[]) input.readObject();
						ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
						Method method = service.getClass().getMethod(methodName, parameterTypes);
						Object result = method.invoke(service, arguments);
						output.writeObject(result);

					} catch (Exception e) {
						throw new RuntimeException(e.toString());
					}
				}
			}).start();
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {

		System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass },
				new InvocationHandler() {

					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						Socket socket = new Socket(host, port);

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

						output.writeUTF(interfaceClass.getName());
						output.writeUTF(method.getName());
						output.writeObject(method.getParameterTypes());
						output.writeObject(args);

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

						Object result = input.readObject();
						if (result instanceof Throwable) {
							throw (Throwable) result;
						}
						return result;
					}
				});
	}
}

RpcFramework.java文件是最核心的處理流程,服務端調用其中的export()方法對外暴露服務,客戶端調用refer()方法進行遠程過程調用,其實就是生成了一個動態代理對象,調用該動態代理對象中的invoke()方法,查看源碼可以看到invoke方法中就是使用了java的BIO去連接服務端,並將要調用的接口、方法、參數等傳輸給服務端;而服務端通過這些參數調用具體的對象就返回結果。

公共接口:

public interface HelloService {

    String hello();

    String hello(String name);

}

服務端實現類:

public class HelloServiceImpl implements HelloService {

    public String hello() {
        return "Hello";
    }

    public String hello(String name) {
        return "Hello," + name;
    }

}

服務端暴露服務類:


public class RpcProvider {

    public static void main(String[] args) throws Exception {
        HelloService service = new HelloServiceImpl();
        RpcFramework.export(service, HelloService.class, 9000);
    }

}

客戶端啓動類:

public class RpcConsumer {

	public static void main(String[] args) throws Exception {
		HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 9000);
		String result = service.hello("rod");
		System.out.println(result);
	}

}
到此結束,該代碼案例可以幫助java開發人員理解rpc調用流程。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章