Hmily(2)

4. 事务发起者执行事务处理StarterHmilyTransactionHandler

 public Object handler(final ProceedingJoinPoint point, final HmilyTransactionContext context)
            throws Throwable {
        Object returnValue;
        try {
            HmilyTransaction hmilyTransaction = hmilyTransactionExecutor.preTry(point);
            try {
                //execute try
                returnValue = point.proceed();
                hmilyTransaction.setStatus(HmilyActionEnum.TRYING.getCode());
                hmilyTransactionExecutor.updateStatus(hmilyTransaction);
            } catch (Throwable throwable) {
                //if exception ,execute cancel
                final HmilyTransaction currentTransaction = hmilyTransactionExecutor.getCurrentTransaction();
                executor.execute(() -> hmilyTransactionExecutor
                        .cancel(currentTransaction));
                throw throwable;
            }
            //execute confirm
            final HmilyTransaction currentTransaction = hmilyTransactionExecutor.getCurrentTransaction();
            executor.execute(() -> hmilyTransactionExecutor.confirm(currentTransaction));
        } finally {
            HmilyTransactionContextLocal.getInstance().remove();
            hmilyTransactionExecutor.remove();
        }
        return returnValue;
    }

开始执行try操作HmilyTransactionExecutor#preTry,构建事务HmilyTransaction,保存参数,方法,类,参数值,确认方法,取消方法等属性,以及事务参与者。把他设置到线程ThreadLocal保存起来等待dubo调用获取。

 public HmilyTransaction preTry(final ProceedingJoinPoint point) {
        LogUtil.debug(LOGGER, () -> "......hmily transaction starter....");
        //build tccTransaction
        final HmilyTransaction hmilyTransaction = buildHmilyTransaction(point, HmilyRoleEnum.START.getCode(), null);
        //save tccTransaction in threadLocal
        CURRENT.set(hmilyTransaction);
        //publishEvent
        hmilyTransactionEventPublisher.publishEvent(hmilyTransaction, EventTypeEnum.SAVE.getCode());
        //set TccTransactionContext this context transfer remote
        HmilyTransactionContext context = new HmilyTransactionContext();
        //set action is try
        context.setAction(HmilyActionEnum.TRYING.getCode());
        context.setTransId(hmilyTransaction.getTransId());
        context.setRole(HmilyRoleEnum.START.getCode());
        HmilyTransactionContextLocal.getInstance().set(context);
        return hmilyTransaction;
    }

private HmilyTransaction buildHmilyTransaction(final ProceedingJoinPoint point, final int role, final String transId) {
        HmilyTransaction hmilyTransaction;
        if (StringUtils.isNoneBlank(transId)) {
            hmilyTransaction = new HmilyTransaction(transId);
        } else {
            hmilyTransaction = new HmilyTransaction();
        }
        hmilyTransaction.setStatus(HmilyActionEnum.PRE_TRY.getCode());
        hmilyTransaction.setRole(role);
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> clazz = point.getTarget().getClass();
        Object[] args = point.getArgs();
        final Hmily hmily = method.getAnnotation(Hmily.class);
        final PatternEnum pattern = hmily.pattern();
        hmilyTransaction.setTargetClass(clazz.getName());
        hmilyTransaction.setTargetMethod(method.getName());
        hmilyTransaction.setPattern(pattern.getCode());
        HmilyInvocation confirmInvocation = null;
        String confirmMethodName = hmily.confirmMethod();
        String cancelMethodName = hmily.cancelMethod();
        if (StringUtils.isNoneBlank(confirmMethodName)) {
            hmilyTransaction.setConfirmMethod(confirmMethodName);
            confirmInvocation = new HmilyInvocation(clazz, confirmMethodName, method.getParameterTypes(), args);
        }
        HmilyInvocation cancelInvocation = null;
        if (StringUtils.isNoneBlank(cancelMethodName)) {
            hmilyTransaction.setCancelMethod(cancelMethodName);
            cancelInvocation = new HmilyInvocation(clazz, cancelMethodName, method.getParameterTypes(), args);
        }
        final HmilyParticipant hmilyParticipant = new HmilyParticipant(hmilyTransaction.getTransId(), confirmInvocation, cancelInvocation);
        hmilyTransaction.registerParticipant(hmilyParticipant);
        return hmilyTransaction;
    }

开始存储事务信息,HmilyTransactionEventPublisher实现了ApplicationListener<ContextRefreshedEvent>接口,在容器初始化结束后会调用onApplicationEvent,这里会创建disruptor高并发处理框架异步存储事务信息。这里实现了一个一致性哈希线程池选择器ConsistentHashSelector,分散压力,提供并发。

public void onApplicationEvent(final ContextRefreshedEvent event) {
        start(hmilyConfig.getBufferSize(), hmilyConfig.getConsumerThreads());
    }

 private void start(final int bufferSize, final int threadSize) {
        disruptor = new Disruptor<>(new HmilyTransactionEventFactory(), bufferSize, runnable -> {
            return new Thread(new ThreadGroup("hmily-disruptor"), runnable,
                    "disruptor-thread-" + INDEX.getAndIncrement());
        }, ProducerType.MULTI, new BlockingWaitStrategy());
        HmilyConsumerDataHandler[] consumers = new HmilyConsumerDataHandler[1];
        List<SingletonExecutor> selects = new ArrayList<>();
        for (int i = 0; i < threadSize; i++) {
            selects.add(new SingletonExecutor("hmily-log-disruptor" + i));
        }
        ConsistentHashSelector selector = new ConsistentHashSelector(selects);
        consumers[0] = new HmilyConsumerDataHandler(selector, coordinatorService);
        disruptor.handleEventsWithWorkerPool(consumers);
        disruptor.setDefaultExceptionHandler(new IgnoreExceptionHandler());
        disruptor.start();
    }

发布保存事务事件hmilyTransactionEventPublisher.publishEvent(hmilyTransaction, EventTypeEnum.SAVE.getCode());处理类是HmilyConsumerDataHandler,调用不同的存储引擎进行保存,更新状态,更新参与者,删除等操作。

public void onEvent(final HmilyTransactionEvent event) {
        String transId = event.getHmilyTransaction().getTransId();
        executor.select(transId).execute(() -> {
            if (event.getType() == EventTypeEnum.SAVE.getCode()) {
                coordinatorService.save(event.getHmilyTransaction());
            } else if (event.getType() == EventTypeEnum.UPDATE_PARTICIPANT.getCode()) {
                coordinatorService.updateParticipant(event.getHmilyTransaction());
            } else if (event.getType() == EventTypeEnum.UPDATE_STATUS.getCode()) {
                final HmilyTransaction hmilyTransaction = event.getHmilyTransaction();
                coordinatorService.updateStatus(hmilyTransaction.getTransId(), hmilyTransaction.getStatus());
            } else if (event.getType() == EventTypeEnum.DELETE.getCode()) {
                coordinatorService.remove(event.getHmilyTransaction().getTransId());
            }
            event.clear();
        });
    }

最后设置事务上下文HmilyTransactionContextLocal后返回事务信息。preTry操作执行完成,开始执行各个RPC以及内部方法,也就是业务方法。returnValue = point.proceed();因为我们使用的是dubbo,所以调用需要经过过滤器DubboHmilyTransactionFilter,他需要配置META-INF/dubbo/com.alibaba.dubbo.rpc.Filter文件,这是dubbo自己扩展的spi。@Activate(group = {Constants.SERVER_KEY, Constants.CONSUMER})表明只是在消费者端起作用,此刻我们就是消费者方,即使用方。解析注解,获取事务上下文的ThreadLocal并把它设置到RpcContext中一块传递到提供方,然后开始调用invoke

public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
        String methodName = invocation.getMethodName();
        Class clazz = invoker.getInterface();
        Class[] args = invocation.getParameterTypes();
        final Object[] arguments = invocation.getArguments();
        Method method = null;
        Hmily hmily = null;
        try {
            converterParamsClass(args, arguments);
            method = clazz.getMethod(methodName, args);
            hmily = method.getAnnotation(Hmily.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
            LogUtil.error(LOGGER, "hmily find method error {} ", ex::getMessage);
        }
        if (Objects.nonNull(hmily)) {
            try {
                final HmilyTransactionContext hmilyTransactionContext = HmilyTransactionContextLocal.getInstance().get();
                if (Objects.nonNull(hmilyTransactionContext)) {
                    if (hmilyTransactionContext.getRole() == HmilyRoleEnum.LOCAL.getCode()) {
                        hmilyTransactionContext.setRole(HmilyRoleEnum.INLINE.getCode());
                    }
                    RpcContext.getContext()
                            .setAttachment(CommonConstant.HMILY_TRANSACTION_CONTEXT, GsonUtils.getInstance().toJson(hmilyTransactionContext));
                    final Result result = invoker.invoke(invocation);
                    //if result has not exception
                    if (!result.hasException()) {
                        final HmilyParticipant hmilyParticipant = buildParticipant(hmilyTransactionContext, hmily, method, clazz, arguments, args);
                        if (hmilyTransactionContext.getRole() == HmilyRoleEnum.INLINE.getCode()) {
                            hmilyTransactionExecutor.registerByNested(hmilyTransactionContext.getTransId(),
                                    hmilyParticipant);
                        } else {
                            hmilyTransactionExecutor.enlistParticipant(hmilyParticipant);
                        }
                    } else {
                        throw new HmilyRuntimeException("rpc invoke exception{}", result.getException());
                    }
                    return result;
                }
                return invoker.invoke(invocation);
            } catch (RpcException e) {
                e.printStackTrace();
                throw e;
            }
        } else {
            return invoker.invoke(invocation);
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值