tcc分散トランザクションソース解析シリーズ(五)のプロジェクト実戦
14262 ワード
前回、私たちはすでに消費全体の呼び出しの流れを分析して、今ただ本当のrpcの遠位呼び出しを開始するだけで、この文章、私たちは一緒に提供者の呼び出しの流れに入りましょう! accountServicesを開始します.payment(accountDTO); の呼び出しは、プロバイダでAccountServiceImpl: として表示されます.@Tcc注釈もあり,confrim,cancelなどの真の方法を提供していることが分かった.前の分析を通じて、彼はspringBeanの実装クラスであり、同じように面を切ることを知っています. TccTransactionFactoryServiceImplのfactoryOfメソッドを経て、P r o v i derTccTransactionHandler に戻ることがわかります.最終的に私たちはP r o v i derTccTransactionHandlerに来ました.handlerメソッド: TccTransactionContextはrpc jsonシーケンス化によって伝達されたオブジェクトであり、このときtryフェーズであることが分かったのでtry に入ります.まず、プロバイダのトランザクション情報を作成し、彼を保存し、threadlocalに保存し、pointを開始します.Proceed()が呼び出されると、tryフェーズで最終的に に入るため、TccCoordinatorMethodAspectに入ります.ここでは、実際のconfrim、cancelメソッドを取得し、現在のトランザクション情報に格納します.その後、実際のビジネスコール、すなわちpaymentメソッドを実行する: メソッドを実行すると、戻ってきます.私がどこでこのメソッドを実行したか覚えていますか.はい、もちろんうどんです.私たちはうどんの中で実行しています.私たちはPaymentServiceImplです.makePaymentうどんの中で実行されます!この点を理解してください.実行後、inventoryServicesを開始しました.decrease(inventoryDTO)は彼の呼び出し原理を上と同じように呼び出し、異なるモジュールで実行するだけだ.makePaymentメソッドの実行が完了したら、どのように実行しますか?StartTccTransactionHandlerを覚えていますか.ずっとそこで待っていますよ.彼のコードを振り返ってみましょう: 結局、私たちはこんなに長い間歩いていましたが、実はここまで来て、私たちはreturnValue=pointを実行しました.proceed(); このコード.
異常なし tcTransactionManagerを実行します.confirm(); コードを見てみましょう このコードの論理は、簡単に理解すると、まず現在のトランザクションステータス(confrim)を更新し、現在のトランザクションの呼び出しポイントのconfrimメソッドを取得し、コンテキストを設定し、反射呼び出しを開始します. 実はここではデバッグによってconfrimを開始する方法がAccountServicesであることがわかりました.payment(AccountDTO accountDTO)ですが、設定されたコンテキスト状態はconfrimで、反射呼び出しを開始するとP r o v i derTcccTransactionHandlerに着きます.handlerメソッド、このメソッドはまだ印象に残っているかもしれませんが、コードを見てみましょう. ここではコンテキスト設定の状態がCONFIRMINGであるため、 が実行されます. tcTransactionManagerを追跡します.confirm(); 以前と同じ方法であることがわかります.この方法はaccountマイクロサービスで を実行していることを知っておく必要があります.ですので、AccountServiceImplが最後に実行されます.confirmメソッドで、支払い確認を行いました.
同理cancel法も上述したような原理で実行される.
ここまで、私达は解析し终わって、全体のtcc过程の実行の流れ、みんなの肝心な点はAOPを理解して、切面の思想を理解して、実はとても简単な事で、もし何か疑问と问题があれば、QQ群に参加することを歓迎します:162614487
/**
*
*
* @param accountDTO dto
* @return true
*/
@Override
@Tcc(confirmMethod = "confirm", cancelMethod = "cancel")
public boolean payment(AccountDTO accountDTO) {
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().subtract(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().add(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int update = accountMapper.update(accountDO);
if (update != 1) {
throw new TccRuntimeException(" !");
}
return Boolean.TRUE;
}
public boolean confirm(AccountDTO accountDTO) {
LOGGER.debug("============ ===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
accountMapper.update(accountDO);
return Boolean.TRUE;
}
public boolean cancel(AccountDTO accountDTO) {
LOGGER.debug("============ ===============");
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().add(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().subtract(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
accountMapper.update(accountDO);
return Boolean.TRUE;
}
@Override
public Class factoryOf(TccTransactionContext context) throws Throwable {
// tcc ,
if (!tccTransactionManager.isBegin() && Objects.isNull(context)) {
return StartTccTransactionHandler.class;
} else if (tccTransactionManager.isBegin() && Objects.isNull(context)) {
return ConsumeTccTransactionIHandler.class;
} else if (Objects.nonNull(context)) {
return ProviderTccTransactionHandler.class;
}
return ConsumeTccTransactionIHandler.class;
}
/**
*
* tcc
*
* @param point point
* @param context context
* @return Object
* @throws Throwable
*/
@Override
public Object handler(ProceedingJoinPoint point, TccTransactionContext context) throws Throwable {
TccTransaction tccTransaction = null;
try {
switch (TccActionEnum.acquireByCode(context.getAction())) {
case TRYING:
try {
//
tccTransaction = tccTransactionManager.providerBegin(context);
//
return point.proceed();
} catch (Throwable throwable) {
tccTransactionManager.removeTccTransaction(tccTransaction);
throw throwable;
}
case CONFIRMING:
// confirm
final TccTransaction acquire = tccTransactionManager.acquire(context);
tccTransactionManager.confirm();
break;
case CANCELING:
// CANCELING
tccTransactionManager.acquire(context);
tccTransactionManager.cancel();
break;
default:
break;
}
} finally {
tccTransactionManager.remove();
}
Method method = ((MethodSignature) (point.getSignature())).getMethod();
return getDefaultValue(method.getReturnType());
}
try {
//
tccTransaction = tccTransactionManager.providerBegin(context);
//
return point.proceed();
} catch (Throwable throwable) {
tccTransactionManager.removeTccTransaction(tccTransaction);
throw throwable;
}
/**
*
*
* @param point
*/
private void registerParticipant(ProceedingJoinPoint point, String transId) throws NoSuchMethodException {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class> clazz = point.getTarget().getClass();
Object[] args = point.getArgs();
final Tcc tcc = method.getAnnotation(Tcc.class);
//
String confirmMethodName = tcc.confirmMethod();
/* if (StringUtils.isBlank(confirmMethodName)) {
confirmMethodName = method.getName();
}*/
String cancelMethodName = tcc.cancelMethod();
/* if (StringUtils.isBlank(cancelMethodName)) {
cancelMethodName = method.getName();
}
*/
//
final TccPatternEnum pattern = tcc.pattern();
tccTransactionManager.getCurrentTransaction().setPattern(pattern.getCode());
TccInvocation confirmInvocation = null;
if (StringUtils.isNoneBlank(confirmMethodName)) {
confirmInvocation = new TccInvocation(clazz,
confirmMethodName, method.getParameterTypes(), args);
}
TccInvocation cancelInvocation = null;
if (StringUtils.isNoneBlank(cancelMethodName)) {
cancelInvocation = new TccInvocation(clazz,
cancelMethodName,
method.getParameterTypes(), args);
}
//
final Participant participant = new Participant(
transId,
confirmInvocation,
cancelInvocation);
tccTransactionManager.enlistParticipant(participant);
}
@Override
@Tcc(confirmMethod = "confirm", cancelMethod = "cancel")
public boolean payment(AccountDTO accountDTO) {
final AccountDO accountDO = accountMapper.findByUserId(accountDTO.getUserId());
accountDO.setBalance(accountDO.getBalance().subtract(accountDTO.getAmount()));
accountDO.setFreezeAmount(accountDO.getFreezeAmount().add(accountDTO.getAmount()));
accountDO.setUpdateTime(new Date());
final int update = accountMapper.update(accountDO);
if (update != 1) {
throw new TccRuntimeException(" !");
}
return Boolean.TRUE;
}
@Override
public Object handler(ProceedingJoinPoint point, TccTransactionContext context) throws Throwable {
Object returnValue;
try {
tccTransactionManager.begin();
try {
// try
returnValue = point.proceed();
} catch (Throwable throwable) {
// cancel
tccTransactionManager.cancel();
throw throwable;
}
//try confirm confirm ,
tccTransactionManager.confirm();
} finally {
tccTransactionManager.remove();
}
return returnValue;
}
異常なし
/**
* confirm , confirm
* confirm 。。
*/
void confirm() throws TccRuntimeException {
LogUtil.debug(LOGGER, () -> " tcc confirm !start");
final TccTransaction currentTransaction = getCurrentTransaction();
if (Objects.isNull(currentTransaction)) {
return;
}
currentTransaction.setStatus(TccActionEnum.CONFIRMING.getCode());
coordinatorCommand.execute(new CoordinatorAction(CoordinatorActionEnum.UPDATE, currentTransaction));
final List participants = currentTransaction.getParticipants();
List participantList = Lists.newArrayListWithCapacity(participants.size());
boolean success = true;
Participant fail = null;
if (CollectionUtils.isNotEmpty(participants)) {
for (Participant participant : participants) {
try {
TccTransactionContext context = new TccTransactionContext();
context.setAction(TccActionEnum.CONFIRMING.getCode());
context.setTransId(participant.getTransId());
TransactionContextLocal.getInstance().set(context);
// rpc confrim
executeParticipantMethod(participant.getConfirmTccInvocation());
participantList.add(participant);
} catch (Exception e) {
LogUtil.error(LOGGER, " confirm :{}", () -> e);
success = false;
fail = participant;
break;
}
}
}
executeHandler(success, currentTransaction, fail, participantList, participants);
}
private void executeHandler(boolean success, final TccTransaction currentTransaction, Participant fail,
List participantList, final List participants) {
if (success) {
TransactionContextLocal.getInstance().remove();
coordinatorCommand.execute(new CoordinatorAction(CoordinatorActionEnum.DELETE, currentTransaction));
} else {
// ,
final List updateList =
participants.stream().skip(participantList.size()).collect(Collectors.toList());
currentTransaction.setParticipants(updateList);
coordinatorCommand.execute(new CoordinatorAction(CoordinatorActionEnum.UPDATE, currentTransaction));
assert fail != null;
throw new TccRuntimeException(fail.getConfirmTccInvocation().toString());
}
}
private void executeParticipantMethod(TccInvocation tccInvocation) throws Exception {
if (Objects.nonNull(tccInvocation)) {
final Class clazz = tccInvocation.getTargetClass();
final String method = tccInvocation.getMethodName();
final Object[] args = tccInvocation.getArgs();
final Class[] parameterTypes = tccInvocation.getParameterTypes();
final Object bean = SpringBeanUtils.getInstance().getBean(clazz);
MethodUtils.invokeMethod(bean, method, args, parameterTypes);
}
}
@Override
public Object handler(ProceedingJoinPoint point, TccTransactionContext context) throws Throwable {
TccTransaction tccTransaction = null;
try {
switch (TccActionEnum.acquireByCode(context.getAction())) {
case TRYING:
try {
//
tccTransaction = tccTransactionManager.providerBegin(context);
//
return point.proceed();
} catch (Throwable throwable) {
tccTransactionManager.removeTccTransaction(tccTransaction);
throw throwable;
}
case CONFIRMING:
// confirm
final TccTransaction acquire = tccTransactionManager.acquire(context);
tccTransactionManager.confirm();
break;
case CANCELING:
// CANCELING
tccTransactionManager.acquire(context);
tccTransactionManager.cancel();
break;
default:
break;
}
} finally {
tccTransactionManager.remove();
}
Method method = ((MethodSignature) (point.getSignature())).getMethod();
return getDefaultValue(method.getReturnType());
}
// confirm
final TccTransaction acquire = tccTransactionManager.acquire(context);
tccTransactionManager.confirm();
break;
同理cancel法も上述したような原理で実行される.
ここまで、私达は解析し终わって、全体のtcc过程の実行の流れ、みんなの肝心な点はAOPを理解して、切面の思想を理解して、実はとても简単な事で、もし何か疑问と问题があれば、QQ群に参加することを歓迎します:162614487