同步调用 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());
}
}