@Override public Boolean login(final String userName, final String password) { LogUtil.info(LOGGER, "输入的用户名密码为:{}", () -> userName + "," + password); if (userName.equals(this.userName) && password.equals(this.password)) { LOGIN_SUCCESS = true; return Boolean.TRUE; } return Boolean.FALSE; }
/** * inti service. */ public void init(TxConfig txConfig) { Runtime.getRuntime().addShutdownHook( new Thread(() -> LOGGER.error("raincat init error"))); try { initService.initialization(txConfig); } catch (RuntimeException ex) { LogUtil.error(LOGGER, "raincat init exception:{}", ex::getMessage); //非正常关闭 System.exit(1); } }
@Override public Object handler(final ProceedingJoinPoint point, final TxTransactionInfo info) throws Throwable { LogUtil.info(LOGGER, "tx-transaction start, class:{}", () -> point.getTarget().getClass()); LogUtil.error(LOGGER, () -> "预提交失败!"); LogUtil.info(LOGGER, "tx-transaction end, class:{}", () -> point.getTarget().getClass());
private void compensate() { scheduledExecutorService .scheduleAtFixedRate(() -> { LogUtil.debug(LOGGER, "compensate recover execute delayTime:{}", () -> txConfig.getCompensationRecoverTime()); final List<TransactionRecover> transactionRecovers = transactionRecoverRepository.listAllByDelay(acquireData()); for (TransactionRecover transactionRecover : transactionRecovers) { if (transactionRecover.getRetriedCount() > txConfig.getRetryMax()) { LogUtil.error(LOGGER, "此事务超过了最大重试次数,不再进行重试:{}", () -> transactionRecover.getTransactionInvocation().getTargetClazz().getName() + ":" + transactionRecover.getTransactionInvocation().getMethod() + "事务组id:" + transactionRecover.getGroupId()); LogUtil.error(LOGGER, "执行事务补偿异常:{}", e::getMessage);
@Override public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) { //心跳配置 if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE) { SpringBeanUtils.getInstance().getBean(NettyClientService.class).doConnect(); } else if (event.state() == IdleState.WRITER_IDLE) { //表示已经多久没有发送数据了 HEART_BEAT.setAction(NettyMessageActionEnum.HEART.getCode()); ctx.writeAndFlush(HEART_BEAT); LogUtil.debug(LOGGER, () -> "send tx manager heart beat!"); } else if (event.state() == IdleState.ALL_IDLE) { //表示已经多久既没有收到也没有发送数据了 SpringBeanUtils.getInstance().getBean(NettyClientService.class).doConnect(); } } }
try { final NettyMessageActionEnum actionEnum = NettyMessageActionEnum.acquireByCode(hb.getAction()); LogUtil.debug(LOGGER, "receive client date this action:{}", actionEnum::getDesc); Boolean success; switch (actionEnum) {
public void commit(final List<TxTransactionItem> txTransactionItems) { try { execute(txTransactionItems, TransactionStatusEnum.COMMIT); } catch (Exception e) { e.printStackTrace(); LogUtil.info(LOGGER, "txManger 发送commit 指令异常 ", e::getMessage); } }
private synchronized void updateTxManagerServices() { String url = assembleUrl(); int maxRetries = 2; for (int i = 0; i < maxRetries; i++) { try { final List<TxManagerServiceDTO> serviceDTOList = OkHttpTools.getInstance().get(url, type); if (CollectionUtils.isEmpty(serviceDTOList)) { LogUtil.error(LOGGER, "Empty response! 请求url为:{}", () -> url); continue; } listAtomicReference.set(serviceDTOList); return; } catch (Throwable ex) { LogUtil.error(LOGGER, "updateTxManagerServices fail exception:{}", ex::getMessage); } } }
HeartBeat heartBeat = (HeartBeat) msg; final NettyMessageActionEnum actionEnum = NettyMessageActionEnum.acquireByCode(heartBeat.getAction()); LogUtil.debug(LOGGER, "receive tx manage info :{}", actionEnum::getDesc);
public void rollBack(final List<TxTransactionItem> txTransactionItems) { try { execute(txTransactionItems, TransactionStatusEnum.ROLLBACK); } catch (Exception e) { e.printStackTrace(); LogUtil.info(LOGGER, "txManger 发送rollback指令异常 ", e::getMessage); } }
@Override public Object interceptor(final ProceedingJoinPoint pjp) throws Throwable { final String compensationId = CompensationLocal.getInstance().getCompensationId(); String groupId = null; if (StringUtils.isBlank(compensationId)) { //如果不是本地反射调用补偿 try { RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); groupId = request.getHeader(CommonConstant.TX_TRANSACTION_GROUP); } catch (IllegalStateException e) { LogUtil.error(LOGGER,"Not Http request ,can't get RequestContextHolder!", e::getMessage); } } return aspectTransactionService.invoke(groupId, pjp); }
private void run() { LogUtil.info(LOGGER, "refresh updateTxManagerServices delayTime:{}", () -> txConfig.getRefreshInterval()); updateTxManagerServices(); } }
/** * acquire tx manage info. * * @return {@linkplain TxManagerServer} */ public TxManagerServer locator() { int maxRetries = 2; final List<TxManagerServiceDTO> txManagerService = getTxManagerService(); if (CollectionUtils.isEmpty(txManagerService)) { return null; } for (int i = 0; i < maxRetries; i++) { List<TxManagerServiceDTO> randomServices = Lists.newLinkedList(txManagerService); Collections.shuffle(randomServices); for (TxManagerServiceDTO serviceDTO : randomServices) { String url = String.join("", serviceDTO.getHomepageUrl(), CommonConstant.TX_MANAGER_PRE, CommonConstant.FIND_SERVER); LOGGER.debug("Loading service from {}", url); try { return OkHttpTools.getInstance().get(url, null, TxManagerServer.class); } catch (Throwable ex) { ex.printStackTrace(); LogUtil.error(LOGGER, "loadTxManagerServer fail exception:{}", ex::getMessage); } } } return null; }
@Override public void init(final String appName, final TxConfig txConfig) { keyName = RepositoryPathUtils.buildRedisKey(appName); final TxRedisConfig txRedisConfig = txConfig.getTxRedisConfig(); try { buildJedisClient(txRedisConfig); } catch (Exception e) { LogUtil.error(LOGGER, "redis init exception please check your config :{}", e::getMessage); } }
@Override public void doConnect() { if (channel != null && channel.isActive()) { return; } final TxManagerServer txManagerServer = TxManagerLocator.getInstance().locator(); if (Objects.nonNull(txManagerServer) && StringUtils.isNoneBlank(txManagerServer.getHost()) && Objects.nonNull(txManagerServer.getPort())) { host = txManagerServer.getHost(); port = txManagerServer.getPort(); } ChannelFuture future = bootstrap.connect(host, port); LogUtil.info(LOGGER, ".....connect txManager-socket -> host:port:{}", () -> host + ":" + port); future.addListener((ChannelFutureListener) futureListener -> { if (futureListener.isSuccess()) { channel = futureListener.channel(); LogUtil.info(LOGGER, "Connect to server successfully!-> host:port:{}", () -> host + ":" + port); } else { LogUtil.info(LOGGER, "Failed to connect to server, try connect after 5s-> host:port:{}", () -> host + ":" + port); futureListener.channel().eventLoop().schedule(this::doConnect, 5, TimeUnit.SECONDS); } }); }
@Override public void init(final String appName, final TxConfig txConfig) { setRootPath(RepositoryPathUtils.buildZookeeperPath(appName)); try { connect(txConfig.getTxZookeeperConfig()); } catch (Exception e) { LogUtil.error(LOGGER, "zookeeper init exception please check you config:{}", e::getMessage); throw new TransactionRuntimeException(e.getMessage()); } }
@Override protected void doCommit(final String txGroupId, final List<TxTransactionItem> txTransactionItems, final List<TxTransactionItem> elseItems) { try { txTransactionItems.forEach(item -> { ChannelSender sender = new ChannelSender(); HeartBeat heartBeat = ExecutorMessageTool.buildMessage(item, sender, TransactionStatusEnum.COMMIT); if (Objects.nonNull(sender.getChannel())) { sender.getChannel().writeAndFlush(heartBeat); LogUtil.info(LOGGER, "txManger 成功发送doCommit指令 事务taskId为:{}", item::getTaskKey); } else { LOGGER.error("txManger 发送doCommit指令失败,channel为空,事务组id:{}, 事务taskId为:{}", txGroupId, item.getTaskKey()); } }); httpExecute(elseItems, TransactionStatusEnum.COMMIT); } catch (Exception e) { e.printStackTrace(); LogUtil.info(LOGGER, "txManger 发送doCommit指令异常 ", e::getMessage); } }
@SuppressWarnings("unchecked") private void compensatoryTransfer(final TransactionRecover transactionRecover) { if (Objects.nonNull(transactionRecover)) { final TransactionInvocation transactionInvocation = transactionRecover.getTransactionInvocation(); if (Objects.nonNull(transactionInvocation)) { final Class clazz = transactionInvocation.getTargetClazz(); final String method = transactionInvocation.getMethod(); final Object[] argumentValues = transactionInvocation.getArgumentValues(); final Class[] argumentTypes = transactionInvocation.getArgumentTypes(); final Object bean = SpringBeanUtils.getInstance().getBean(clazz); try { CompensationLocal.getInstance().setCompensationId(CommonConstant.COMPENSATE_ID); MethodUtils.invokeMethod(bean, method, argumentValues, argumentTypes); //通知tm自身已经完成提交 //删除本地信息 final Boolean success = txManagerMessageService.completeCommitTxTransaction(transactionRecover.getGroupId(), transactionRecover.getTaskId(), TransactionStatusEnum.COMMIT.getCode()); if (success) { transactionRecoverRepository.remove(transactionRecover.getId()); } } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); LogUtil.error(LOGGER, "补偿方法反射调用失败!{}", e::getMessage); } } } }
/** * 回滚整个事务组. * * @param txGroupId 事务组id */ @Override public void rollBack(final String txGroupId) { txManagerService.updateTxTransactionItemStatus(txGroupId, txGroupId, TransactionStatusEnum.ROLLBACK.getCode(), null); final List<TxTransactionItem> txTransactionItems = txManagerService.listByTxGroupId(txGroupId); if (CollectionUtils.isNotEmpty(txTransactionItems)) { final Map<Boolean, List<TxTransactionItem>> listMap = filterData(txTransactionItems); if (Objects.isNull(listMap)) { LogUtil.info(LOGGER, "事务组id:{},提交失败!数据不完整", () -> txGroupId); return; } final List<TxTransactionItem> currentItem = listMap.get(Boolean.TRUE); final List<TxTransactionItem> elseItems = listMap.get(Boolean.FALSE); doRollBack(txGroupId, currentItem, elseItems); } }