Netty Case, Intermediate Extension of Netty 4.1 Seven "Netty Request Response Synchronous Communication"

Posted by dan1956 on Wed, 04 Sep 2019 03:31:01 +0200

Preamble Introduction

When we implement the RPC framework, we need to choose how sockets communicate.And we know that socket communication is similar to qq chatting in general, sending messages in the past and replying whenever possible.But our RPC framework communication, which feels like an http call, needs to be returned within a certain period of time or a timeout disconnection will occur.Here we choose netty as our socket framework and use future to communicate.

Dubbo: The earliest open source RPC framework in China, developed by Alibaba and opened to the outside world in late 2011, supports only Java language.
Motan: The RPC framework used internally by Weibo, which was opened to the outside world in 2016, only supports the Java language.
Tars: The RPC framework used internally by Tencent was opened source in 2017 and only supports C++ language.
Spring Cloud: Foreign Pivotal's 2014 RPC Framework for Open Source, supports only Java Language
gRPC: Google's Open Source Cross-Language RPC Framework in 2015 supports multiple languages.
Thrift: An internal system cross-language RPC framework originally developed by Facebook and contributed to the Apache Foundation in 2007, becoming one of Apache's open source projects that support multiple languages.
hprose: A new lightweight, cross-language, cross-platform, object-oriented, high-performance remote dynamic communication middleware licensed by MIT Open Source.It supports many languages: nodeJs, C++,.NET, Java, Delphi, Objective-C, ActionScript, JavaScript, ASP, PHP, Python, Ruby, Perl, Golang.

Environmental preparation

1. jdk1.8 [below jdk1.7 can only partially support netty]
2. Netty4.1.36.Final [netty3.x 4.x 5 changes a lot each time, so does the interface class name]

Code Samples

itstack-demo-rpc-2-07
└── src
    └── main
    │    └── java
    │        └── org.itstack.demo.netty
    │             ├── client
    │             │   ├── ClientSocket.java
    │             │   └── MyClientHandler.java  
    │             ├── codec
    │             │   ├── RpcDecoder.java
    │             │   └── RpcEncoder.java  
    │             ├── future
    │             │   ├── SyncWrite.java    
    │             │   ├── SyncWriteFuture.java  
    │             │   ├── SyncWriteMap.java 
    │             │   └── WriteFuture.java  
    │             ├── msg
    │             │   ├── Request.java
    │             │   └── Response.java 
    │             ├── server
    │             │   ├── MyServerHandler.java
    │             │   └── ServerSocket.java     
    │             └── util
    │                 └── SerializationUtil.java    
    └── test
         └── java
             └── org.itstack.demo.test
                 ├── StartClient.java
                 └── StartServer.java    

** Show some important code blocks, complete code can focus on public number acquisition; bugstack bug stack**

MyClientHandler.java

/**
 * Hole stack: https://bugstack.cn
 * Public Number: bugstack bug stack  Focus on getting learning source 
 * Cave Group: Group 5398358 Group 5360692
 * Create by fuzhengwei on 2019
 */
public class MyClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object obj) throws Exception {
        Response msg = (Response) obj;
        String requestId = msg.getRequestId();
        SyncWriteFuture future = (SyncWriteFuture) SyncWriteMap.syncKey.get(requestId);
        if (future != null) {
            future.setResponse(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

}

SyncWrite.java

/**
 * Hole stack: https://bugstack.cn
 * Public Number: bugstack bug stack  Focus on getting learning source 
 * Cave Group: Group 5398358 Group 5360692
 * Create by fuzhengwei on 2019
 */
public class SyncWrite {

    public Response writeAndSync(final Channel channel, final Request request, final long timeout) throws Exception {

        if (channel == null) {
            throw new NullPointerException("channel");
        }
        if (request == null) {
            throw new NullPointerException("request");
        }
        if (timeout <= 0) {
            throw new IllegalArgumentException("timeout <= 0");
        }

        String requestId = UUID.randomUUID().toString();
        request.setRequestId(requestId);

        WriteFuture<Response> future = new SyncWriteFuture(request.getRequestId());
        SyncWriteMap.syncKey.put(request.getRequestId(), future);

        Response response = doWriteAndSync(channel, request, timeout, future);

        SyncWriteMap.syncKey.remove(request.getRequestId());
        return response;
    }

    private Response doWriteAndSync(final Channel channel, final Request request, final long timeout, final WriteFuture<Response> writeFuture) throws Exception {

        channel.writeAndFlush(request).addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) throws Exception {
                writeFuture.setWriteResult(future.isSuccess());
                writeFuture.setCause(future.cause());
                //Failure Removal
                if (!writeFuture.isWriteSuccess()) {
                    SyncWriteMap.syncKey.remove(writeFuture.requestId());
                }
            }
        });

        Response response = writeFuture.get(timeout, TimeUnit.MILLISECONDS);
        if (response == null) {
            if (writeFuture.isTimeout()) {
                throw new TimeoutException();
            } else {
                // write exception
                throw new Exception(writeFuture.cause());
            }
        }
        return response;
    }

}

MyServerHandler.java

/**
 * Hole stack: https://bugstack.cn
 * Public Number: bugstack bug stack  Focus on getting learning source 
 * Cave Group: Group 5398358 Group 5360692
 * Create by fuzhengwei on 2019
 */
public class MyServerHandler extends ChannelInboundHandlerAdapter{

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object obj){
        Request msg = (Request) obj;
        //feedback
        Response request = new Response();
        request.setRequestId(msg.getRequestId());
        request.setParam(msg.getResult() + " Request succeeded, please accept feedback{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ");
        ctx.writeAndFlush(request);
        //release
        ReferenceCountUtil.release(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

}

StartClient.java

/**
 * Hole stack: https://bugstack.cn
 * Public Number: bugstack bug stack  Focus on getting learning source 
 * Cave Group: Group 5398358 Group 5360692
 * Create by fuzhengwei on 2019
 */
public class StartClient {

    private static ChannelFuture future;

    public static void main(String[] args) {
        ClientSocket client = new ClientSocket();
        new Thread(client).start();

        while (true) {
            try {
                //Get future, thread has wait time
                if (null == future) {
                    future = client.getFuture();
                    Thread.sleep(500);
                    continue;
                }
                //Build send parameters
                Request request = new Request();
                request.setResult("query{bugstack Bug Hole Stack}User Information");
                SyncWrite s = new SyncWrite();
                Response response = s.writeAndSync(future.channel(), request, 1000);
                System.out.println("Call result:" + JSON.toJSON(response));
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

StartServer.java

/**
 * Hole stack: https://bugstack.cn
 * Public Number: bugstack bug stack  Focus on getting learning source 
 * Cave Group: Group 5398358 Group 5360692
 * Create by fuzhengwei on 2019
 */
public class StartServer {

    public static void main(String[] args) {
        new Thread(new ServerSocket()).start();
        System.out.println("itstack-demo-netty server start done. {Focus on Public Number: bugstack Bug hole stack, get source code}");
    }

}

test result

Start StartServer

itstack-demo-netty server start done. {Focus on public number: bugstack bug stack, get source code}

Start StartClient

Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"188ba00e-3a0d-4094-9475-c7ee93104011"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"bc9d63d4-9d37-406a-9c0f-a68211ac466f"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"cceb510b-8179-46ab-abc6-eb7d5b6c0ac2"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"f65aafd0-07b7-4bdb-be80-a57b4c58ad2d"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"e6700074-380b-441f-ae0d-f71dcd7f84c9"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"25a0a9d5-46d5-4da6-ad3f-1496ca20bb17"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"052dce21-dfb9-42d7-bbcf-46137b9933df"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"4fd968fa-3171-4e4f-838d-4a215a90da00"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"97f6eb6e-8c5d-49f4-beba-2ba7e1ff953f"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"ffc48115-8e62-43a8-b3f7-035390427d37"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"4bafefc9-4beb-49f6-8126-29e0e03a55d1"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"10367786-24fd-4f11-9465-bcd2c87b4027"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"82293ad3-a694-405c-ab03-01624f38b1ad"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"0c163cb8-be5f-4697-931f-61f5bf487bae"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"0f1e7611-4fd0-43b4-86dc-fce09965046e"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"f22ac0dc-974c-4de1-bcdf-1566ca0b2305"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"1907456b-2507-4ddd-8c1e-a86c990e3e72"}
//Call result:{"param":"query{bugstack Bug Hole Stack}User Information Request Successful, Feedback Results Please Accept Processing{Public number: bugstack Worm Hole Stack Blog Stack: https://bugstack.cn}. ","requestId":"6a99b1f2-5859-4ed7-9d17-98229c13250f"}

Process finished with exit code -1

Topics: Java Netty socket Apache