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);
}
}