Actual RPC framework Netty learning

  First attach GitHub Address: https://github.com/kosamino/netty-root/tree/master/ym-netty-rpc

  RPC implementation is a local call remote service through the remote proxy object. Internet application scenarios, the service monomer extreme lack of flexibility scalability, large-scale development team is not easy to develop management. So often the service will be split according to the vertical module, that is, we are talking about SOA as a service. After the split system with direct service business interaction systems often rely on RPC framework for communication.

  The usual RPC server provides an interface corresponding jar package, the client through the proxy instance rpc frame function to get the corresponding interface , the call processing data packaging and communications are transparent.

First, the call flow

  First, first to analyze the next RPC What is the process, as shown below:

        

  We include three parts, users, Netty client, Netty server:

  1. The user initiates a call;
  2. Packaging Netty client requests;
  3. The client requests are serialized (object-ByteBuf);
  4. After the server sends a message to the sequence of;
  5. The server will request deserialize objects into specific decoded;
  6. The server parses the request sent by a client and returns the result to prepare;
  7. The server returns a result serialized as ByteBuf;
  8. The client receives the return information;
  9. Return information to the client column of anti Object obtained information;
  10. The client returns the results to the user caller, to complete the request.

Second, including technical

  As shown above, the entire process is simple RPC framework in which this process technology needed to use it?

  • Dynamic Agent: get the proxy object through java Proxy technology, invocationHandler protocol for data communications and packaging.
  • Serialization, deserialization
  • Network communication: Communication can get good IO performance-based client and server netty's
  • Reflection: The client request parameter corresponding to the server instance of the method is achieved by the reflection technique calling

  Next, we code fragment analysis on the use of part of the technology.

  1, dynamic proxies

//todo 代理对象
QueryStudentClient client = (QueryStudentClient)rpcProxyFactory.factoryRemoteInvoker("localhost",8080,QueryStudentClient.class);

public class RpcProxyFactory<T> {

    public T factoryRemoteInvoker(String host, int port, Class interfaces){
        //动态代理
        return (T) Proxy.newProxyInstance(interfaces.getClassLoader(),new Class[]{interfaces},
                new RemoteInvocationHandler(host,port,interfaces));
    }
}

public class RemoteInvocationHandler implements InvocationHandler {
    private String host;
    private int port;
    private Class interfaces;

    public RemoteInvocationHandler(String host, int port, Class interfaces) {
        this.host = host;
        this.port = port;
        this.interfaces = interfaces;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //todo 封装消息
        RpcContext rpcContext=new RpcContext();
        rpcContext.setClassName(interfaces.getName());
        rpcContext.setMethodName(method.getName());
        rpcContext.setTypes(method.getParameterTypes());
        rpcContext.setParams(args);

        try {
            //通讯
            NettyClient client=new NettyClient(host,port);
            client.connect();
            return client.sendData(rpcContext);
        }catch (Exception e){

        }
        return null;
    }
}

  2, serialization, deserialization

    @Override
    protected void initChannel(SocketChannel sc) throws Exception {
        handler =  new NettyClientHandler(latch);

        HessianEncode hessionEncodeHandler=new HessianEncode();
        HessianDecode hessionDecodeHandler= new HessianDecode();

        LengthFieldPrepender fieldEncoder=new LengthFieldPrepender(2);
//        LengthFieldBasedFrameDecoder fieldDecoder = new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2);

//        出站
        sc.pipeline () addLast (. fieldEncoder ); 
        . sc.pipeline () addLast ( hessionEncodeHandler ); 

        // unsafe multithreaded inbound LengthFieldBasedFrameDecoder, thus using new new 
        . sc.pipeline () addLast ( new new  LengthFieldBasedFrameDecoder (65535 , 0 , 2, 0, 2 )); 
        sc.pipeline () addLast (. hessionDecodeHandler ); 
        sc.pipeline () addLast (Handler);. 
    }

  Can be seen in the pipeline has been added: the packet length is set based on the viscosity of the semi-header packet processing Handler, sequence tool, deserialized tool, is used herein serialization Hessian.

  3, reflection technique

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcContext model=(RpcContext)msg;

        Class clazz=null;
        if(Registry.map.containsKey(model.getClassName())){
            clazz=Registry.map.get(model.getClassName());
        }

        Object result=null;
        try {
            Method method=clazz.getMethod(model.getMethodName(),model.getTypes());
            result=method.invoke(clazz.newInstance(),model.getParams());
        }catch (Exception e){
            e.printStackTrace();
        }

        ctx.channel().writeAndFlush(result);
    }

  You can see the class name server based on the client came, to obtain the map Registry of the registered class, and then call the reflection according to the return type, method name, parameter.

Three, Netty asynchronous collaborative problem calling thread

  Use netty achieve the client sends a point to note:

  Write data channel calling Netty's writeAndFlush written after the event and channelRead event will receive a response is executed asynchronously , so the need to pay attention thread cooperation. Countdowlacth can be used to achieve the main thread after executing the channelread wait before going to get the response object received.

    / ** 
     * client data transmitting method 
     * @param rpcRequest 
     * @return 
     * @throws InterruptedException
      * / 
    public Object the sendData (RpcContext rpcRequest) throws InterruptedException { 
        ChannelFuture CF2 = the this .getChannelFuture (); // singleton objects acquired ChannelFuture 
        if (! cf.channel () = null && cf.channel () isActive ().) { 
            LATCH = new new a CountDownLatch (. 1 ); 
            clientInitializer.reLatch (LATCH);
            cf.channel () writeAndFlush (rpcRequest);. latch.await (); 
        } 
            

        return clientInitializer.getServerResult (); 
    } 
} 

  // client reads the data from the server to complete 
    @Override
     public  void channelRead (ChannelHandlerContext CTX, Object MSG) throws Exception {
         Super .channelRead (CTX, MSG); 
        Result = MSG; 
        System.out.println ( "return data has been read" );
         latch.countDown (); 
    }

  Thereby achieving a thread cooperation, otherwise call the result can not be returned. The remaining details, see the complete code.

Guess you like

Origin www.cnblogs.com/jing99/p/12571961.html