一款基于Netty和Grpc的轻量级、高性能网络编程框架(四)

201 阅读1分钟

同步调用 API

同步调用会阻塞当前线程,适用于不频繁调用的场景

public interface RemotingInvoker {  
  
    /**  
    * 同步调用  
    * @param message  
    * @param serverInformation  
    * @throws RpcException  
    */  
    MessageResponseBody invoke(Message message, ServerInformation serverInformation) throws RpcException;  
  
    //~  
}  

Netty 实现

@Slf4j  
public class NettyRemotingInvoker implements RemotingInvoker {  
  
    private final RpcClient rpcClient;  
    private final RequestInterceptor requestInterceptor;  
    private final RequestIdGenerator requestIdGenerator;  

    public NettyRemotingInvoker(RpcClient rpcClient, RequestInterceptor requestInterceptor, RequestIdGenerator requestIdGenerator) {  
        this.rpcClient = rpcClient;  
        this.requestInterceptor = requestInterceptor;  
        this.requestIdGenerator = requestIdGenerator;  
    }  

    @Override  
    public MessageResponseBody invoke(Message message, ServerInformation serverInformation) throws RpcException {  
        Channel channel = NettyClientChannelManager.establishChannel((NettyClient) rpcClient, serverInformation);  
        String serverId = serverInformation.getServerId();  
        final String random = requestIdGenerator.generate();  
        MessageRequestBody requestBody = new MessageRequestBody().setServerId(serverId).setMessage(message).setRequestId(random);  
        String requestJsonBody = JSON.toJSON(requestBody);  
        MessageRequest messageRequest = MessageRequest.newBuilder().setBody(requestJsonBody).build();  
        requestInterceptor.intercept(requestBody);  
        CompletableFuture<MessageResponseBody> completableFuture = new CompletableFuture<>();  
        NettyUnprocessedRequests.put(random, completableFuture);  
        try {  
            channel.writeAndFlush(messageRequest).addListener((ChannelFutureListener) future -> {  
                if (!future.isSuccess()) {  
                    completableFuture.completeExceptionally(future.cause());  
                }  
            });  
            return completableFuture.get();  
        } catch (Exception e) {  
            handlerException(serverId, channel, e);  
            String msg = String.format("To the Server: %s, exception when sending a message, cause by: %s", serverId, e.getMessage());  
            throw new RemoteInvokeException(serverId, msg);  
        }  
    }  

    // ~  

    private void handlerException(String serverId, Channel channel, Exception e){  
        log.error("To the server {}, occur exception {}", serverId, e.getMessage());  
        if (!channel.isActive() && !channel.isOpen() && !channel.isWritable()) {  
            channel.close();  
            NettyClientChannelManager.removeChannel(serverId);  
            log.error("The Server is unavailable, shutdown channel and the cached channel is deleted.");  
        }  
    }  
}  

Grpc 实现

@Slf4j  
public class GrpcRemotingInvoker implements RemotingInvoker {  
  
    private final RpcClient rpcClient;  
    private final RequestInterceptor requestInterceptor;  
    private final RequestIdGenerator requestIdGenerator;  

    public GrpcRemotingInvoker(RpcClient rpcClient, RequestInterceptor requestInterceptor, RequestIdGenerator requestIdGenerator) {  
        this.rpcClient = rpcClient;  
        this.requestInterceptor = requestInterceptor;  
        this.requestIdGenerator = requestIdGenerator;  
    }  
  
    @Override  
    public MessageResponseBody invoke(Message message, ServerInformation serverInformation) throws RpcException {  
        String serverId = serverInformation.getServerId();  
        ManagedChannel channel = GrpcClientChannelManager.establishChannel((GrpcClient) rpcClient, serverInformation);  
        MessageServiceGrpc.MessageServiceBlockingStub messageClientStub = MessageServiceGrpc.newBlockingStub(channel);  
        final String random = requestIdGenerator.generate();  
        MessageRequestBody requestBody = new MessageRequestBody().setServerId(serverId).setMessage(message).setRequestId(random);  
        MessageRequest messageRequest = MessageRequest.newBuilder().setBody(JSON.toJSON(requestBody)).build();  
        requestInterceptor.intercept(requestBody);  

        try {  
            MessageResponse response = messageClientStub.messageProcessing(messageRequest);  
            return JSON.parse(response.getBody(), MessageResponseBody.class);  
        } catch (StatusRuntimeException e) {  
            Status.Code code = e.getStatus().getCode();  
            handlerException(serverId, channel, code);  
            throw new RemoteInvokeException(serverId, e.getMessage());  
        } catch (Exception e) {  
            channel.shutdown();  
            String msg = String.format("To the Server: %s, exception when sending a message, cause by: %s", serverId, e.getMessage());  
            throw new RemoteInvokeException(serverId, msg);  
        }  
    }  

    // ~  

    private void handlerException(String serverId, ManagedChannel channel, Status.Code code){  
        log.error("To the Server: {}, exception when sending a message, Status Code: {}", serverId, code);  
        if (Status.Code.UNAVAILABLE == code) {  
            channel.shutdown();  
            GrpcClientChannelManager.removeChannel(serverId);  
            log.error("The Server is unavailable, shutdown channel and the cached channel is deleted.");  
        }  
    }  
}

使用示例

以下代码截取自 Open-Job,代码仅为示例

public void killTask(Long jobId, ServerInformation serverInformation) {  
    Message message = new Message();  
    message.setBody(serializeData);  

    MessageResponseBody response;  
    try {  
        response = remotingInvoker.invoke(message, serverInformation);  
    } catch (RpcException ex) {  
        throw new ServiceException(ex.getMessage());  
    }  

    if (response.getStatus() != ResponseStatus.SUCCESS) {  
        throw new ServiceException(response.getMsg());  
    }  
}  

链接