package xyz.redtorch.node.slave.rpc.service.impl; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import net.jpountz.lz4.LZ4FrameInputStream; import net.jpountz.lz4.LZ4FrameOutputStream; import xyz.redtorch.common.service.RpcClientProcessService; import xyz.redtorch.node.slave.rpc.service.RpcClientReqHandlerService; import xyz.redtorch.node.slave.rpc.service.RpcClientRspHandlerService; import xyz.redtorch.node.slave.web.socket.WebSocketClientHandler; import xyz.redtorch.pb.CoreField.CommonReqField; import xyz.redtorch.pb.CoreField.CommonRspField; import xyz.redtorch.pb.CoreRpc.RpcCancelOrderReq; import xyz.redtorch.pb.CoreRpc.RpcExceptionRsp; import xyz.redtorch.pb.CoreRpc.RpcGetAccountListReq; import xyz.redtorch.pb.CoreRpc.RpcGetContractListReq; import xyz.redtorch.pb.CoreRpc.RpcGetOrderListReq; import xyz.redtorch.pb.CoreRpc.RpcGetPositionListReq; import xyz.redtorch.pb.CoreRpc.RpcGetTickListReq; import xyz.redtorch.pb.CoreRpc.RpcGetTradeListReq; import xyz.redtorch.pb.CoreRpc.RpcId; import xyz.redtorch.pb.CoreRpc.RpcSearchContractReq; import xyz.redtorch.pb.CoreRpc.RpcSubmitOrderReq; import xyz.redtorch.pb.CoreRpc.RpcSyncSlaveNodeRuntimeDataRsp; import xyz.redtorch.pb.Dep.DataExchangeProtocol; import xyz.redtorch.pb.Dep.DataExchangeProtocol.ContentType; import xyz.redtorch.pb.Dep.DataExchangeProtocol.RpcType; @Service public class RpcClientProcessServiceImpl implements RpcClientProcessService, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(RpcClientProcessServiceImpl.class); @Value("${rt.rpc.client.node-id}") private int nodeId; @Autowired private RpcClientReqHandlerService rpcClientReqHandlerService; @Autowired private RpcClientRspHandlerService rpcClientRspHandlerService; @Autowired private WebSocketClientHandler webSocketClientHandler; @Value("${rt.rpc.client.threads-normal}") private Integer threadsNormal; private ExecutorService normalExecutorService; // private ExecutorService importantExecutorService = Executors.newCachedThreadPool(); @Override public void afterPropertiesSet() throws Exception { normalExecutorService = Executors.newFixedThreadPool(threadsNormal); } @Override public void processData(byte[] data) { DataExchangeProtocol dep = null; try { dep = DataExchangeProtocol.parseFrom(data); } catch (InvalidProtocolBufferException e) { logger.error("处理DEP错误,PB解析数据发生错误", e); logger.error("处理DEP错误,PB解析数据发生错误,原始数据HEX:{}", Hex.encodeHexString(data)); return; } int sourceNodeId = dep.getSourceNodeId(); int targetNodeId = dep.getTargetNodeId(); if (targetNodeId != nodeId) { logger.error("处理DEP错误,目标节点ID不匹配当前节点ID:{},目标节点ID:{}", nodeId, targetNodeId); return; } int rpcId = dep.getRpcId(); long timestamp = dep.getTimestamp(); DataExchangeProtocol.ContentType contentType = dep.getContentType(); String contentTypeValueName = contentType.getValueDescriptor().getName(); RpcType rpcType = dep.getRpcType(); String rpcTypeValueName = rpcType.getValueDescriptor().getName(); String reqId = dep.getReqId(); logger.info("处理DEP记录,来源节点ID:{},RPC类型:{},RPC ID:{},请求ID:{}内容类型:{},时间戳:{}", sourceNodeId, rpcTypeValueName, rpcId, reqId, contentTypeValueName, timestamp); ByteString contentByteString; if (contentType == ContentType.COMPRESSED_LZ4) { try (InputStream in = new ByteArrayInputStream(dep.getContentBytes().toByteArray()); BufferedInputStream bin = new BufferedInputStream(in); LZ4FrameInputStream zIn = new LZ4FrameInputStream(bin);) { contentByteString = ByteString.readFrom(zIn); } catch (Exception e) { logger.error("处理DEP异常,来源节点ID:{},RPC类型:{},RPC ID:{},请求ID:{}时间戳:{},无法使用LZ4正确解析报文内容", sourceNodeId, rpcTypeValueName, rpcId, reqId, timestamp, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, "无法使用LZ4正确解析报文内容"); return; } } else if (contentType == ContentType.ROUTINE) { contentByteString = dep.getContentBytes(); } else { logger.error("处理DEP错误,来源节点ID:{},RPC类型:{},RPC ID:{},请求ID:{}内容类型:{},时间戳:{},不支持的报文类型", sourceNodeId, rpcTypeValueName, rpcId, reqId, contentTypeValueName, timestamp); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, "不支持的报文类型"); return; } if (contentByteString == null || contentByteString.size() <= 0) { logger.error("处理DEP错误,来源节点ID:{},RPC类型:{},RPC ID:{},请求ID:{}内容类型:{},时间戳:{},报文内容长度错误", sourceNodeId, rpcTypeValueName, rpcId, contentTypeValueName, timestamp); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, "报文内容长度错误"); return; } if (dep.getRpcType() != RpcType.CORE_RPC) { logger.error("处理DEP错误,来源节点ID:{},RPC类型:{},RPC ID:{},请求ID:{}内容类型:{},时间戳:{},未能识别的RPC类型", sourceNodeId, rpcTypeValueName, rpcId, reqId, contentTypeValueName, timestamp); return; } doCoreRpc(sourceNodeId, rpcId, reqId, contentByteString, timestamp); } private void doCoreRpc(int sourceNodeId, int rpcId, String reqId, ByteString contentByteString, long timestamp) { switch (rpcId) { case RpcId.UNKNOWN_RPC_ID_VALUE: { logger.warn("处理RPC,来源节点ID:{},RPC ID:{}", sourceNodeId, rpcId); break; } case RpcId.SUBMIT_ORDER_REQ_VALUE: { importantExecutorService.execute(new Runnable() { @Override public void run() { try { RpcSubmitOrderReq rpcSubmitOrderReq = RpcSubmitOrderReq.parseFrom(contentByteString); checkCommonReq(rpcSubmitOrderReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:SUBMIT_ORDER_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.submitOrder(rpcSubmitOrderReq.getCommonReq(), rpcSubmitOrderReq.getSubmitOrderReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:SUBMIT_ORDER_REQ", e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.CANCEL_ORDER_REQ_VALUE: { importantExecutorService.execute(new Runnable() { @Override public void run() { try { RpcCancelOrderReq rpcCancelOrderReq = RpcCancelOrderReq.parseFrom(contentByteString); checkCommonReq(rpcCancelOrderReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:CANCEL_ORDER_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.cancelOrder(rpcCancelOrderReq.getCommonReq(), rpcCancelOrderReq.getCancelOrderReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:CANCEL_ORDER_REQ", e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.SEARCH_CONTRACT_REQ_VALUE: { importantExecutorService.execute(new Runnable() { @Override public void run() { try { RpcSearchContractReq rpcSearchContractReq = RpcSearchContractReq.parseFrom(contentByteString); checkCommonReq(rpcSearchContractReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:SEARCH_CONTRACT_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.searchContract(rpcSearchContractReq.getCommonReq(), rpcSearchContractReq.getContract()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:SEARCH_CONTRACT_REQ", e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.SYNC_SLAVE_NODE_RUNTIME_DATA_RSP_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcSyncSlaveNodeRuntimeDataRsp rpcSyncSlaveNodeRuntimeDataRsp = RpcSyncSlaveNodeRuntimeDataRsp.parseFrom(contentByteString); checkCommonRsp(rpcSyncSlaveNodeRuntimeDataRsp.getCommonRsp(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:SYNC_SLAVE_NODE_RUNTIME_DATA_RSP", sourceNodeId, reqId); rpcClientRspHandlerService.onSyncSlaveNodeRuntimeDataRsp(rpcSyncSlaveNodeRuntimeDataRsp); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:SYNC_SLAVE_NODE_RUNTIME_DATA_RSP", e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.EXCEPTION_RSP_VALUE: { importantExecutorService.execute(new Runnable() { @Override public void run() { try { RpcExceptionRsp rpcExceptionRsp = RpcExceptionRsp.parseFrom(contentByteString); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:EXCEPTION_RSP", sourceNodeId, reqId); rpcClientRspHandlerService.onExceptionRsp(rpcExceptionRsp); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:EXCEPTION_RSP", e); } } }); break; } case RpcId.GET_TICK_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetTickListReq rpcGetTickListReq = RpcGetTickListReq.parseFrom(contentByteString); checkCommonReq(rpcGetTickListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_TICK_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getTickList(rpcGetTickListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_TICK_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.GET_POSITION_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetPositionListReq rpcGetPositionListReq = RpcGetPositionListReq.parseFrom(contentByteString); checkCommonReq(rpcGetPositionListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_POSITION_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getPositionList(rpcGetPositionListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_POSITION_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.GET_CONTRACT_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetContractListReq rpcGetContractListReq = RpcGetContractListReq.parseFrom(contentByteString); checkCommonReq(rpcGetContractListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_CONTRACT_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getContractList(rpcGetContractListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_CONTRACT_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.GET_ACCOUNT_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetAccountListReq rpcGetAccountListReq = RpcGetAccountListReq.parseFrom(contentByteString); checkCommonReq(rpcGetAccountListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_ACCOUNT_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getAccountList(rpcGetAccountListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_ACCOUNT_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.GET_ORDER_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetOrderListReq rpcGetOrderListReq = RpcGetOrderListReq.parseFrom(contentByteString); checkCommonReq(rpcGetOrderListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_ORDER_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getOrderList(rpcGetOrderListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_ORDER_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } case RpcId.GET_TRADE_LIST_REQ_VALUE: { normalExecutorService.execute(new Runnable() { @Override public void run() { try { RpcGetTradeListReq rpcGetTradeListReq = RpcGetTradeListReq.parseFrom(contentByteString); checkCommonReq(rpcGetTradeListReq.getCommonReq(), sourceNodeId, reqId); logger.info("处理RPC记录,来源节点ID:{},请求ID:{},RPC:GET_TRADE_LIST_REQ", sourceNodeId, reqId); rpcClientReqHandlerService.getTradeList(rpcGetTradeListReq.getCommonReq()); } catch (Exception e) { logger.error("处理RPC异常,来源节点ID:{},RPC:GET_TRADE_LIST_REQ", sourceNodeId, e); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, e.getMessage()); } } }); break; } default: logger.error("处理RPC错误,来源节点ID:{},RPC ID:{},请求ID:{}不支持此功能", sourceNodeId, rpcId, reqId); sendExceptionRsp(sourceNodeId, rpcId, reqId, timestamp, "不支持此功能"); break; } } private void checkCommonRsp(CommonRspField commonRsp, int sourceNodeId, String reqId) { if (commonRsp == null) { logger.error("参数commonRsp缺失"); throw new IllegalArgumentException("参数commonRsp缺失"); } if (StringUtils.isBlank(commonRsp.getReqId())) { logger.error("参数reqId缺失"); throw new IllegalArgumentException("参数reqId缺失"); } if (!commonRsp.getReqId().equals(reqId)) { logger.error("请求ID不匹配"); throw new IllegalArgumentException("请求ID不匹配"); } } private void checkCommonReq(CommonReqField commonReq, int sourceNodeId, String reqId) { if (commonReq == null) { logger.error("参数commonReq缺失"); throw new IllegalArgumentException("参数commonReq缺失"); } if (sourceNodeId != commonReq.getSourceNodeId()) { throw new IllegalArgumentException("不合法的来源节点ID:" + commonReq.getSourceNodeId()); } if (commonReq.getTargetNodeId() != nodeId) { throw new IllegalArgumentException("目标节点ID " + commonReq.getTargetNodeId() + ",与当前节点" + nodeId + "不匹配!"); } if (StringUtils.isBlank(commonReq.getReqId())) { logger.error("参数reqId缺失"); throw new IllegalArgumentException("参数reqId缺失"); } if (!commonReq.getReqId().equals(reqId)) { logger.error("请求ID不匹配"); throw new IllegalArgumentException("请求ID不匹配"); } if (StringUtils.isBlank(commonReq.getOperatorId())) { logger.error("参数operatorId缺失"); throw new IllegalArgumentException("参数operatorId缺失"); } } public void sendExceptionRsp(int targetNodeId, int originalRpcId, String originalReqId, long originalTimestamp, String info) { if (info == null) { info = ""; } ByteString content = RpcExceptionRsp.newBuilder() // .setOriginalRpcId(originalRpcId) // .setOriginalReqId(originalReqId) // .setOriginalTimestamp(originalTimestamp) // .setInfo(info) // .build().toByteString(); sendRoutineCoreRpc(targetNodeId, content, originalReqId, RpcId.EXCEPTION_RSP); } public boolean sendCoreRpc(int targetNodeId, ByteString content, String reqId, RpcId rpcId) { logger.info("发送RPC记录,目标节点ID:{},请求ID:{},RPC:{}", targetNodeId, reqId, rpcId.getValueDescriptor().getName()); if (content.size() > 262144) { return sendLz4CoreRpc(targetNodeId, content, reqId, rpcId); } else { return sendRoutineCoreRpc(targetNodeId, content, reqId, rpcId); } } public boolean sendRoutineCoreRpc(int targetNodeId, ByteString content, String reqId, RpcId rpcId) { DataExchangeProtocol.Builder depBuilder = DataExchangeProtocol.newBuilder() // .setRpcId(rpcId.getNumber()) // .setReqId(reqId) // .setContentType(ContentType.ROUTINE) // .setSourceNodeId(nodeId) // .setTargetNodeId(targetNodeId) // .setTimestamp(System.currentTimeMillis()) // .setContentBytes(content); if (!webSocketClientHandler.sendData(depBuilder.build().toByteArray())) { logger.error("发送RPC错误,目标节点ID:{},请求ID:{},RPC:{}", targetNodeId, reqId, rpcId.getValueDescriptor().getName()); return false; } return true; } public boolean sendLz4CoreRpc(int targetNodeId, ByteString content, String reqId, RpcId rpcId) { ByteString contentByteString = ByteString.EMPTY; long beginTime = System.currentTimeMillis(); try (InputStream in = new ByteArrayInputStream(content.toByteArray()); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); LZ4FrameOutputStream lzOut = new LZ4FrameOutputStream(bOut);) { final byte[] buffer = new byte[10240]; int n = 0; while (-1 != (n = in.read(buffer))) { lzOut.write(buffer, 0, n); } lzOut.close(); in.close(); contentByteString = ByteString.copyFrom(bOut.toByteArray()); logger.info("发送RPC记录,目标节点ID:{},请求ID:{},RPC:{},压缩耗时{}ms,原始数据大小{},压缩后数据大小{},压缩率{}", targetNodeId, reqId, rpcId.getValueDescriptor().getName(), System.currentTimeMillis() - beginTime, content.size(), contentByteString.size(), contentByteString.size() / (double) content.size()); } catch (Exception e) { logger.error("发送RPC错误,压缩异常,目标节点ID:{},请求ID:{},RPC:{}", targetNodeId, reqId, rpcId.getValueDescriptor().getName(), e); return false; } DataExchangeProtocol.Builder depBuilder = DataExchangeProtocol.newBuilder() // .setRpcId(rpcId.getNumber()) // .setReqId(reqId) // .setContentType(ContentType.COMPRESSED_LZ4) // .setSourceNodeId(nodeId) // .setTargetNodeId(targetNodeId) // .setTimestamp(System.currentTimeMillis()) // .setContentBytes(contentByteString); if (!webSocketClientHandler.sendData(depBuilder.build().toByteArray())) { logger.error("发送RPC错误,目标节点ID:{},请求ID:{},RPC:{}", targetNodeId, reqId, rpcId.getValueDescriptor().getName()); return false; } return true; } @Override public void onWsClosed() { // NOP } @Override public void onWsError() { // NOP } @Override public void onWsConnected() { // NOP } @Override public void onHeartbeat(String result) { // NOP } }