Java RPC remote call handwriting distributed systems framework

Point of attention, do not get lost; Java-related technologies and continuously updated information! ! !

A, RPC Introduction

They recently hadoop underlying communications are achieved through RPC.

RPC (Remote Procedure Call Protocol) remote call: Remote Procedure Call is a common distributed network communications protocol that allows you to run a subroutine call another computer to program a computer, while the communication network of hidden details so that no additional user interaction for this program. Most communications between distributed system implemented by RPC

Two, RPC request procedure
Here Insert Picture Description

  1. client sends a request to call service
  2. The method calls the client stub of the agent, encapsulated in a format parameter, the address of the service side, the network initiates a request
  3. Message sent by the network to the server, server stub receives a message, unpack the corresponding service call the local reflection
  4. Local service execution returns the result to the server stub, server stub will then result message back to the client packages
  5. client stub receiving decoded message to obtain a final result.

Three, RPC framework architecture

Write a RPC framework, which components need?

  1. Serialization. Serialization main role is structured object into a stream of bytes for writing to persistent storage or transmission over a network.
  2. Remote proxy objects, generally using jdk dynamic proxy or cglib
  3. Agency services expose a registry Zookeeper
  4. Network communications, event-driven mode Reactor

Four, RPC exemplary frame

  1. Service provider, running on the server side, providing service interface definition and service implementation class
  2. Service publisher, running on the server side is responsible for local services publish to a remote service, remote management services, services provided to consumers
  3. Consumer services, running on the client, call the remote service through the remote proxy object

Server code

Service Interface:

 //计算学生年龄和的接
public interface CalculateService {
 String cal(Student sta, Student stb);
}
public class CalculateServiceImpl implements CalculateService {
 @Override
 public String cal(Student sta, Student stb) {
 return "学生年龄之和:" + (sta.getAge() + stb.getAge());
 }
}

Service Release

public class PublishUtilI {
 //服务接口集合
 private static List<Object> serviceList;
 private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,10, TimeUnit.SECONDS,
 new LinkedBlockingQueue<Runnable>(10));
 public static void publish(int port,Object... services) throws IOException {
 serviceList= Arrays.asList(services);
 ServerSocket server = new ServerSocket(port);
 Socket client;
 while (true) {
 //阻塞等待请求
 client = server.accept();
 //使用线程池处理请求
 executor.submit(new ServerHandler(client, serviceList));
 }
 }
}

Reflection call service

  1. Reads the service name sent by the client

  2. Determine whether the service is released

  3. If released, reflecting a corresponding service call server

  4. Return the results to the client

    public class ServerHandler implements Runnable {
    private Socket client = null;
    private List serviceList = null;
    public ServerHandler(Socket client, List service) {
    this.client = client;
    this.serviceList = service;
    }
    @Override
    public void run() {
    try (
    ObjectInputStream input = new ObjectInputStream(client.getInputStream());
    ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream())
    ) {
    // 读取客户端要访问那个service
    Class serviceClass = (Class) input.readObject();
    // 找到该服务类
    Object obj = findService(serviceClass);
    if (obj == null) {
    output.writeObject(serviceClass.getName() + “服务未发现”);
    The else {}
    // using reflection to invoke the method, returns the result
    String methodName = input.readUTF (); // read encoded UTF String String
    // read parameter Type
    Class [] parameterTypes = (Class < <?>? > []) input.readObject ();
    // read parameter
    Object [] = arguments (Object []) input.readObject ();
    . Method, Method obj.getClass = () getMethod (methodName, The parameterTypes);
    // reflective performing the method
    Object Method.invoke Result = (obj, arguments);
    output.writeObject (Result);
    }
    } the catch (Exception E) {
    e.printStackTrace ();
    }
    }
    Private findService Object (Class serviceClass) {
    for (Object obj: serviceList) {
    Boolean isFather = serviceClass.isAssignableFrom (obj.getClass ());
    IF (isFather) {
    return obj;
    }
    }
    return null;
    }
    }

Client code

public class Client {
 public static void main(String[] args) {
 CallProxyHandler handler = new CallProxyHandler("127.0.0.1", 1111);
 CalculateService calculateService = handler.getService(CalculateService.class);
 Student sta = new Student(1);
 Student stb = new Student(2);
 String result = calculateService.cal(sta, stb);
 System.out.println(result);
 }
}

Create a proxy class to call a remote server published service

 public class CallProxyHandler implements InvocationHandler {
 private String ip;
 private int port;
 public CallProxyHandler(String ip, int port) {
 this.ip = ip;
 this.port = port;
 }
 /**
 * 获取代理对象
 * @param clazz
 * @param <T>
 * @return
 */
 @SuppressWarnings("all")
 public <T> T getService(Class<T> clazz) {
 return (T) Proxy.newProxyInstance(CallProxyHandler.class.getClassLoader(),
 new Class<?>[] {clazz}, this);
 }
 
 /**
 * 将需要调用服务的方法名,参数类型,参数按照一定格式封装发送至服务端
 * 读取服务端返回的结果
 * @param proxy
 * @param method
 * @param args
 * @return
 * @throws Throwable
 */
 @SuppressWarnings("all")
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 try (
 Socket socket = new Socket(ip, port);
 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
 ObjectInputStream input = new ObjectInputStream(socket.getInputStream())
 ) {
 output.writeObject(proxy.getClass().getInterfaces()[0]);
 output.writeUTF(method.getName());
 output.writeObject(method.getParameterTypes());
 output.writeObject(args);
 output.flush();
 Object result = input.readObject();
 if (result instanceof Throwable) {
 throw (Throwable) result;
 }
 return result;
 }
 }
}

Thus, a simple RPC service invocation framework is completed. But there are many problems:

  1. Serialization java carrying, efficiency is not high, and may be used Hadoop Avro protobuf
  2. Use BIO way for network transmission, can not cope with high concurrency, use Netty framework for network communication
  3. The lack of registry, registration service can be used to manage Zookeeper.

Follows, shares, comments, share knowledge java every day, giving collected some source analysis, Dubbo, Redis, Netty, zookeeper, Spring, cloud, distributed data

Guess you like

Origin blog.csdn.net/XingXing_Java/article/details/91432554