I. Introduction of RPC
RPC, called remote Procedure call, is a computer communication protocol. It allows the remote service to be called as if it were a local service. It can be implemented in different ways. such as RMI (remote method call), Hessian, Http invoker, and so on. In addition, RPC is language-independent.
Rpc
As shown, assuming that Computer1 calls the Sayhi () method, calling the Sayhi () method for Computer1 is like calling a local method, calling –> back. However, it can be seen from subsequent calls that Computer1 calls the Sayhi () method in Computer2, and RPC masks the underlying implementation details so that callers do not have to focus on the details of network communication, data transfer, and so on.
II. implementation of RPC framework
The core principle of RPC is described above:RPC enables local applications to easily and efficiently invoke processes (services) in the server. It is mainly used in distributed systems. such as the IPC components in Hadoop. But how do you implement an RPC framework?
Consider from the following aspects, for reference only:
1. Communication model: Suppose that the communication is between a machine and a B machine, a communication model between A and B, generally based on bio or NiO in Java;
2. Process (service) Positioning: Using a given communication method, with the determination of IP and port and method name to determine the specific process or method;
3. Remote Proxy object: A locally invoked method (service) is actually a local proxy for a remote method, so a remote proxy object may be required, and for Java, the remote proxy object can use Java's dynamic object implementation to encapsulate the invocation of a remote method;
4. Serialization, the object name, method name, parameters and other object information network transmission needs to be converted to binary transmission, here may require a different serialization technology scheme. such as: Protobuf,arvo and so on.
Third, Java implementation of RPC Framework 1, the implementation of technical solutions
The following uses the original scheme to implement the RPC framework, using socket communication, dynamic Proxy and reflection and Java native serialization.
2. RPC Framework Architecture
The RPC schema is divided into three parts:
1) service provider, running on the server side, provides service interface definitions and service implementation classes.
2) service Center, running on the server side, is responsible for publishing local services to remote services, management of remote services, provided to the service consumer use.
3) The service consumer, which runs on the client, invokes the remote service through the remote proxy object.
3. Concrete Realization
Service Provider Interface definition and implementation, the code is as follows:
Public interface HelloService { string Sayhi (string name);}
Helloservices Interface Implementation class:
public class Helloserviceimpl implements HelloService {public String sayhi (String name) { return "Hi," + name;
}}
Service Center code implementation, the code is as follows:
Public interface Server {public void Stop (); public void Start () throws IOException; public void register (class Serviceinterface, class Impl); public boolean isrunning (); public int getport ();}
Service Center Implementation class:
public class Servicecenter implements Server {private static Executorservice executor = Executors.newfixedthreadpool (R Untime.getruntime (). Availableprocessors ()); Private static final hashmap<string, class> serviceregistry = new hashmap<string, class> (); private static Boolean isrunning = false; private static int port; public servicecenter (int port) {this.port = port; } public void Stop () {isrunning = false; Executor.shutdown (); } public void Start () throws IOException {ServerSocket server = new ServerSocket (); Server.bind (New Inetsocketaddress (port)); SYSTEM.OUT.PRINTLN ("Start Server"); try {while (true) {///1. Listens for TCP connections to the client, encapsulates it as a task after receiving a TCP connection, executes executor.execute by the thread pool (n EW Servicetask (Server.accept ())); }} finally {Server.close (); }} public void register (class Serviceinterface, class Impl) {Serviceregistry. Put (Serviceinterface.getname (), impl); } public boolean isrunning () {return isrunning; } public int Getport () {return port; } private static Class Servicetask implements Runnable {Socket clent = null; Public Servicetask (Socket client) {this.clent = client; public void Run () {ObjectInputStream input = null; ObjectOutputStream output = null; try {//2. Deserializes the code stream sent by the client into an object, reflection invokes the service's executor, gets the execution result input = new ObjectInputStream (clent.getinputstr EAM ()); String serviceName = Input.readutf (); String methodName = Input.readutf (); Class<?>[] Parametertypes = (class<?>[]) input.readobject (); object[] arguments = (object[]) input.readobject (); Class ServiceClass = Serviceregistry.get (serviceName); if (ServiceClass = = null) {throw new ClassnotfoundeXception (ServiceName + "not Found"); } method = Serviceclass.getmethod (MethodName, parametertypes); Object result = Method.invoke (Serviceclass.newinstance (), arguments); 3. Deserialize the execution result, sent via socket to client output = new ObjectOutputStream (Clent.getoutputstream ()); Output.writeobject (result); } catch (Exception e) {e.printstacktrace (); } finally {if (output! = null) {try {output.close (); } catch (IOException e) {e.printstacktrace (); }} if (input! = null) {try {input.close (); } catch (IOException e) {e.printstacktrace (); }} if (clent! = null) {try { Clent.close (); } catch (IOException e) {e.printstacktrace (); } } } } }}
Remote proxy object for client:
public class Rpcclient<t> {public static <T> T getremoteproxyobj (final class<?> serviceinterface, fi nal inetsocketaddress addr) {//1. Convert the local interface call to the dynamic proxy of the JDK and implement the remote call to the interface in the dynamic proxy return (T) proxy.newproxyinstance (ser Viceinterface.getclassloader (), New Class<?>[]{serviceinterface}, new Invocationhandler () { public object invoke (object proxy, Method method, object[] args) throws Throwable {Socke t socket = null; ObjectOutputStream output = null; ObjectInputStream input = null; try {//2. Create a socket client to connect the remote service provider socket = new socket () according to the specified address; Socket.connect (addr); 3. Encode the required interface class, method name, parameter list, and so on for the remote service call to the service provider output = new ObjectOutputStream (Socket.getoutputstream ( )); Output.writeutf(Serviceinterface.getname ()); Output.writeutf (Method.getname ()); Output.writeobject (Method.getparametertypes ()); Output.writeobject (args); 4. Synchronous blocking waits for the server to return an answer, and returns input = new ObjectInputStream (Socket.getinputstream ()) after obtaining an answer; return Input.readobject (); } finally {if (socket! = NULL) socket.close (); if (output! = null) output.close (); if (input! = null) input.close (); } } }); }}
Finally, for the test class:
public class Rpctest {public static void Main (string[] args) throws IOException { new Thread (new Runnable () {
public void Run () { try { Server serviceserver = new Servicecenter (8088); Serviceserver.register (Helloservice.class, helloserviceimpl.class); Serviceserver.start (); } catch (IOException e) { e.printstacktrace ();}}} ). Start (); HelloService service = Rpcclient.getremoteproxyobj (Helloservice.class, new inetsocketaddress ("localhost", 8088)); System.out.println (Service.sayhi ("Test"));} }
Operation Result:
Regeist service Helloservicestart Serverhi, test
Iv. Summary
RPC is essentially a message processing model, and RPC masks the details of the communication between the underlying hosts, allowing the process to invoke the remote service as if it were a local service.
Five, can improve the place
The simple RPC framework implemented here is developed using the Java language, which is highly coupled with the Java language, and the socket used for communication is based on bio, the IO efficiency is not high, and the Java Native serialization mechanism accounts for too much memory and is not running efficiently. There are several ways to consider improvements.
- Can adopt the RPC framework based on JSON data transmission;
- Can be implemented using NIO or directly using Netty instead of bio;
- Use open-source serialization mechanisms, such as Hadoop Avro and Google Protobuf;
- Service registration can be managed using zookeeper to make the application more stable.
Java implements a simple RPC framework