|
|
@@ -18,7 +18,6 @@ package io.seata.server.coordinator;
|
|
|
import io.netty.channel.Channel;
|
|
|
import io.seata.common.thread.NamedThreadFactory;
|
|
|
import io.seata.common.util.CollectionUtils;
|
|
|
-import io.seata.common.util.DurationUtil;
|
|
|
import io.seata.config.ConfigurationFactory;
|
|
|
import io.seata.core.constants.ConfigurationKeys;
|
|
|
import io.seata.core.context.RootContext;
|
|
|
@@ -36,11 +35,12 @@ import io.seata.core.rpc.netty.NettyRemotingServer;
|
|
|
import io.seata.server.AbstractTCInboundHandler;
|
|
|
import io.seata.server.metrics.MetricsPublisher;
|
|
|
import io.seata.server.session.*;
|
|
|
+import io.seata.server.store.StoreConfig;
|
|
|
+import org.apache.commons.lang.time.DateFormatUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.slf4j.MDC;
|
|
|
|
|
|
-import java.time.Duration;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
|
@@ -105,13 +105,13 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
/**
|
|
|
* the pool size of branch asynchronous remove thread pool
|
|
|
*/
|
|
|
- private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors();
|
|
|
+ private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
|
|
|
|
|
|
- private static final Duration MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(
|
|
|
- ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT);
|
|
|
+ private static final long MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong(
|
|
|
+ ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT);
|
|
|
|
|
|
- private static final Duration MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(
|
|
|
- ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DurationUtil.DEFAULT_DURATION, DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT);
|
|
|
+ private static final long MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong(
|
|
|
+ ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT);
|
|
|
|
|
|
private static final boolean ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE = ConfigurationFactory.getInstance().getBoolean(
|
|
|
ConfigurationKeys.ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE, DEFAULT_ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE);
|
|
|
@@ -134,15 +134,9 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
private final GlobalStatus[] rollbackingStatuses = new GlobalStatus[] {GlobalStatus.TimeoutRollbacking,
|
|
|
GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.RollbackRetrying, GlobalStatus.Rollbacking};
|
|
|
|
|
|
- private final GlobalStatus[] retryCommittingStatuses =
|
|
|
- new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying};
|
|
|
+ private final GlobalStatus[] retryCommittingStatuses = new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Committed};
|
|
|
|
|
|
- private final ThreadPoolExecutor branchRemoveExecutor = new ThreadPoolExecutor(BRANCH_ASYNC_POOL_SIZE, BRANCH_ASYNC_POOL_SIZE,
|
|
|
- Integer.MAX_VALUE, TimeUnit.MILLISECONDS,
|
|
|
- new ArrayBlockingQueue<>(
|
|
|
- CONFIG.getInt(ConfigurationKeys.SESSION_BRANCH_ASYNC_QUEUE_SIZE, DEFAULT_BRANCH_ASYNC_QUEUE_SIZE)
|
|
|
- ), new NamedThreadFactory("branchSessionRemove", BRANCH_ASYNC_POOL_SIZE),
|
|
|
- new ThreadPoolExecutor.CallerRunsPolicy());
|
|
|
+ private final ThreadPoolExecutor branchRemoveExecutor;
|
|
|
|
|
|
private RemotingServer remotingServer;
|
|
|
|
|
|
@@ -161,6 +155,19 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
}
|
|
|
this.remotingServer = remotingServer;
|
|
|
this.core = new DefaultCore(remotingServer);
|
|
|
+ boolean enableBranchAsyncRemove = CONFIG.getBoolean(
|
|
|
+ ConfigurationKeys.ENABLE_BRANCH_ASYNC_REMOVE, DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE);
|
|
|
+ // create branchRemoveExecutor
|
|
|
+ if (enableBranchAsyncRemove && StoreConfig.getSessionMode() != StoreConfig.SessionMode.FILE) {
|
|
|
+ branchRemoveExecutor = new ThreadPoolExecutor(BRANCH_ASYNC_POOL_SIZE, BRANCH_ASYNC_POOL_SIZE,
|
|
|
+ Integer.MAX_VALUE, TimeUnit.MILLISECONDS,
|
|
|
+ new ArrayBlockingQueue<>(
|
|
|
+ CONFIG.getInt(ConfigurationKeys.SESSION_BRANCH_ASYNC_QUEUE_SIZE, DEFAULT_BRANCH_ASYNC_QUEUE_SIZE)
|
|
|
+ ), new NamedThreadFactory("branchSessionRemove", BRANCH_ASYNC_POOL_SIZE),
|
|
|
+ new ThreadPoolExecutor.CallerRunsPolicy());
|
|
|
+ } else {
|
|
|
+ branchRemoveExecutor = null;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public static DefaultCoordinator getInstance(RemotingServer remotingServer) {
|
|
|
@@ -296,7 +303,8 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- LOGGER.info("Global transaction[{}] is timeout and will be rollback.", globalSession.getXid());
|
|
|
+ LOGGER.warn("Global transaction[{}] is timeout and will be rollback,transaction begin time:{} and now:{}", globalSession.getXid(),
|
|
|
+ DateFormatUtils.ISO_DATE_FORMAT.format(globalSession.getBeginTime()), DateFormatUtils.ISO_DATE_FORMAT.format(System.currentTimeMillis()));
|
|
|
|
|
|
globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
|
|
|
globalSession.close();
|
|
|
@@ -338,13 +346,10 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
// The function of this 'return' is 'continue'.
|
|
|
return;
|
|
|
}
|
|
|
- if (isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT.toMillis(), rollbackingSession.getBeginTime())) {
|
|
|
+ if (isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT, rollbackingSession.getBeginTime())) {
|
|
|
if (ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE) {
|
|
|
rollbackingSession.clean();
|
|
|
}
|
|
|
- // Prevent thread safety issues
|
|
|
- SessionHolder.getRetryRollbackingSessionManager().removeGlobalSession(rollbackingSession);
|
|
|
- LOGGER.error("Global transaction rollback retry timeout and has removed [{}]", rollbackingSession.getXid());
|
|
|
|
|
|
SessionHelper.endRollbackFailed(rollbackingSession, true, true);
|
|
|
|
|
|
@@ -354,7 +359,7 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
rollbackingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
|
|
|
core.doGlobalRollback(rollbackingSession, true);
|
|
|
} catch (TransactionException ex) {
|
|
|
- LOGGER.info("Failed to retry rollbacking [{}] {} {}", rollbackingSession.getXid(), ex.getCode(), ex.getMessage());
|
|
|
+ LOGGER.error("Failed to retry rollbacking [{}] {} {}", rollbackingSession.getXid(), ex.getCode(), ex.getMessage());
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
@@ -374,15 +379,11 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
SessionHelper.forEach(committingSessions, committingSession -> {
|
|
|
try {
|
|
|
// prevent repeated commit
|
|
|
- if (committingSession.getStatus() == GlobalStatus.Committing
|
|
|
- && !committingSession.isDeadSession()) {
|
|
|
+ if (GlobalStatus.Committing.equals(committingSession.getStatus()) && !committingSession.isDeadSession()) {
|
|
|
// The function of this 'return' is 'continue'.
|
|
|
return;
|
|
|
}
|
|
|
- if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT.toMillis(), committingSession.getBeginTime())) {
|
|
|
- // Prevent thread safety issues
|
|
|
- SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(committingSession);
|
|
|
- LOGGER.error("Global transaction commit retry timeout and has removed [{}]", committingSession.getXid());
|
|
|
+ if (isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT, committingSession.getBeginTime())) {
|
|
|
|
|
|
// commit retry timeout event
|
|
|
SessionHelper.endCommitFailed(committingSession, true, true);
|
|
|
@@ -390,10 +391,14 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
//The function of this 'return' is 'continue'.
|
|
|
return;
|
|
|
}
|
|
|
+ if (GlobalStatus.Committed.equals(committingSession.getStatus())
|
|
|
+ && committingSession.getBranchSessions().isEmpty()) {
|
|
|
+ SessionHelper.endCommitted(committingSession,true);
|
|
|
+ }
|
|
|
committingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
|
|
|
core.doGlobalCommit(committingSession, true);
|
|
|
} catch (TransactionException ex) {
|
|
|
- LOGGER.info("Failed to retry committing [{}] {} {}", committingSession.getXid(), ex.getCode(), ex.getMessage());
|
|
|
+ LOGGER.error("Failed to retry committing [{}] {} {}", committingSession.getXid(), ex.getCode(), ex.getMessage());
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
@@ -500,14 +505,18 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
asyncCommitting.shutdown();
|
|
|
timeoutCheck.shutdown();
|
|
|
undoLogDelete.shutdown();
|
|
|
- branchRemoveExecutor.shutdown();
|
|
|
+ if (branchRemoveExecutor != null) {
|
|
|
+ branchRemoveExecutor.shutdown();
|
|
|
+ }
|
|
|
try {
|
|
|
retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
undoLogDelete.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
- branchRemoveExecutor.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
+ if (branchRemoveExecutor != null) {
|
|
|
+ branchRemoveExecutor.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
} catch (InterruptedException ignore) {
|
|
|
|
|
|
}
|
|
|
@@ -549,6 +558,9 @@ public class DefaultCoordinator extends AbstractTCInboundHandler implements Tran
|
|
|
*/
|
|
|
public BranchRemoveTask(GlobalSession globalSession, BranchSession branchSession) {
|
|
|
this.globalSession = globalSession;
|
|
|
+ if (branchSession == null) {
|
|
|
+ throw new IllegalArgumentException("BranchSession can`t be null!");
|
|
|
+ }
|
|
|
this.branchSession = branchSession;
|
|
|
}
|
|
|
|