Shardingsphere整合Atomikos對XA分佈式事務的支持(2)

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Apache ShardingSphere 是一套開源的分佈式數據庫中間件解決方案組成的生態圈,它由 JDBC、Proxy 和 Sidecar(規劃中)這 3 款相互獨立,卻又能夠混合部署配合使用的產品組成。它們均提供標準化的數據分片、分佈式事務和數據庫治理功能,可適用於如 Java 同構、異構語言、雲原生等各種多樣化的應用場景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ShardingSphere 已於2020年4月16日成爲 Apache 軟件基金會的頂級項目。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"咱們話不多,接上篇,我們直接進入正題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Atomikos簡單介紹"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Atomikos(https:\/\/www.atomikos.com\/),其實是一家公司的名字,提供了基於"},{"type":"codeinline","content":[{"type":"text","text":"JTA規範的XA分佈式事務TM的實現"}]},{"type":"text","text":"。其旗下最著名的產品就是事務管理器。產品分兩個版本:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TransactionEssentials:開源的免費產品;"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ExtremeTransactions:上商業版,需要收費。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這兩個產品的關係如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/86\/c4\/8667010406bf89406aba30bc3a99efc4.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ExtremeTransactions在TransactionEssentials的基礎上額外提供了以下功能(重要的):"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"支持TCC:這是一種柔性事務"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"支持通過RMI、IIOP、SOAP這些遠程過程調用技術,進行事務傳播。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"事務日誌雲存儲,雲端對事務進行恢復,並且提供了完善的管理後臺。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"org.apache.shardingsphere.transaction.xa.XAShardingTransactionManager詳解"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們簡單的來回顧下"},{"type":"codeinline","content":[{"type":"text","text":"org.apache.shardingsphere.transaction.spiShardingTransactionManager"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public interface ShardingTransactionManager extends AutoCloseable {\n\n \/**\n * Initialize sharding transaction manager.\n *\n * @param databaseType database type\n * @param resourceDataSources resource data sources\n *\/\n void init(DatabaseType databaseType, Collection resourceDataSources);\n\n \/**\n * Get transaction type.\n *\n * @return transaction type\n *\/\n TransactionType getTransactionType();\n\n \/**\n * Judge is in transaction or not.\n * \n * @return in transaction or not\n *\/\n boolean isInTransaction();\n\n \/**\n * Get transactional connection.\n *\n * @param dataSourceName data source name\n * @return connection\n * @throws SQLException SQL exception\n *\/\n Connection getConnection(String dataSourceName) throws SQLException;\n\n \/**\n * Begin transaction.\n *\/\n void begin();\n\n \/**\n * Commit transaction.\n *\/\n void commit();\n\n \/**\n * Rollback transaction.\n *\/\n void rollback();\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們重點縣關注"},{"type":"codeinline","content":[{"type":"text","text":"init"}]},{"type":"text","text":"方法,從它的命名,你就應該能夠看出來,這是整個框架的初始化方法,讓我們來看看它是如何進行初始化的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" private final Map cachedDataSources = new HashMap<>();\n\n private final XATransactionManager xaTransactionManager = XATransactionManagerLoader.getInstance().getTransactionManager();\n\n @Override\n public void init(final DatabaseType databaseType, final Collection resourceDataSources) {\n for (ResourceDataSource each : resourceDataSources) {\n cachedDataSources.put(each.getOriginalName(), new XATransactionDataSource(databaseType, each.getUniqueResourceName(), each.getDataSource(), xaTransactionManager));\n }\n xaTransactionManager.init();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先SPI的方式加載XATransactionManager的具體實現類,這裏返回的就是"},{"type":"codeinline","content":[{"type":"text","text":"org.apache.shardingsphere.transaction.xa.atomikos.manager.AtomikosTransactionManager"}]},{"type":"text","text":"。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們在關注下 "},{"type":"codeinline","content":[{"type":"text","text":"new XATransactionDataSource()"}]},{"type":"text","text":" , 進入 "},{"type":"codeinline","content":[{"type":"text","text":"org.apache.shardingsphere.transaction.xa.jta.datasource。XATransactionDataSource"}]},{"type":"text","text":"類的構造方法。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public XATransactionDataSource(final DatabaseType databaseType, final String resourceName, final DataSource dataSource, final XATransactionManager xaTransactionManager) {\n this.databaseType = databaseType;\n this.resourceName = resourceName;\n this.dataSource = dataSource;\n if (!CONTAINER_DATASOURCE_NAMES.contains(dataSource.getClass().getSimpleName())) {\n \/\/ 重點關注 1 ,返回了xaDatasource\n xaDataSource = XADataSourceFactory.build(databaseType, dataSource);\n this.xaTransactionManager = xaTransactionManager;\n \/\/ 重點關注2 註冊資源\n xaTransactionManager.registerRecoveryResource(resourceName, xaDataSource);\n }\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們重點來關注 "},{"type":"codeinline","content":[{"type":"text","text":"XADataSourceFactory.build(databaseType, dataSource)"}]},{"type":"text","text":",從名字我們就可以看出,這應該是返回"},{"type":"codeinline","content":[{"type":"text","text":"JTA規範裏面的XADataSourc"}]},{"type":"text","text":",在ShardingSphere裏面很多的功能,可以從代碼風格的命名上就能猜出來,這就是優雅代碼(吹一波)。不多逼逼,我們進入該方法。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public final class XADataSourceFactory {\n\n public static XADataSource build(final DatabaseType databaseType, final DataSource dataSource) {\n return new DataSourceSwapper(XADataSourceDefinitionFactory.getXADataSourceDefinition(databaseType)).swap(dataSource);\n }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先又是一個SPI定義的 "},{"type":"codeinline","content":[{"type":"text","text":"XADataSourceDefinitionFactory"}]},{"type":"text","text":",它根據不同的數據庫類型,來加載不同的方言。然後我們進入 "},{"type":"codeinline","content":[{"type":"text","text":"swap"}]},{"type":"text","text":"方法。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" public XADataSource swap(final DataSource dataSource) {\n XADataSource result = createXADataSource();\n setProperties(result, getDatabaseAccessConfiguration(dataSource));\n return result;\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很簡明,第一步創建,"},{"type":"codeinline","content":[{"type":"text","text":"XADataSource"}]},{"type":"text","text":",第二步給它設置屬性(包含數據的連接,用戶名密碼等),然後返回。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"返回 "},{"type":"codeinline","content":[{"type":"text","text":"XATransactionDataSource"}]},{"type":"text","text":" 類,關注"},{"type":"codeinline","content":[{"type":"text","text":"xaTransactionManager.registerRecoveryResource(resourceName, xaDataSource);"}]},{"type":"text","text":" 從名字可以看出,這是註冊事務恢復資源。這個我們在事務恢復的時候詳解。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"返回 "},{"type":"codeinline","content":[{"type":"text","text":"XAShardingTransactionManager.init()"}]},{"type":"text","text":" ,我們重點來關注:"},{"type":"codeinline","content":[{"type":"text","text":"xaTransactionManager.init();"}]},{"type":"text","text":",最後進入"},{"type":"codeinline","content":[{"type":"text","text":"AtomikosTransactionManager.init()"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public final class AtomikosTransactionManager implements XATransactionManager {\n\n private final UserTransactionManager transactionManager = new UserTransactionManager();\n\n private final UserTransactionService userTransactionService = new UserTransactionServiceImp();\n\n @Override\n public void init() {\n userTransactionService.init();\n }\n\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"進入"},{"type":"codeinline","content":[{"type":"text","text":"UserTransactionServiceImp.init()"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"private void initialize() {\n \/\/添加恢復資源 不用關心\n for (RecoverableResource resource : resources_) {\n Configuration.addResource ( resource );\n }\n for (LogAdministrator logAdministrator : logAdministrators_) {\n Configuration.addLogAdministrator ( logAdministrator );\n }\n \/\/註冊插件 不用關心\n for (TransactionServicePlugin nxt : tsListeners_) {\n Configuration.registerTransactionServicePlugin ( nxt );\n }\n \/\/獲取配置屬性 重點關心\n ConfigProperties configProps = Configuration.getConfigProperties();\n configProps.applyUserSpecificProperties(properties_);\n \/\/進行初始化\n Configuration.init();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們重點關注,獲取配置屬性。最後進入"},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.icatch.provider.imp.AssemblerImp.initializeProperties()"}]},{"type":"text","text":"方法"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" @Override\n public ConfigProperties initializeProperties() {\n \/\/讀取classpath下的默認配置transactions-defaults.properties\n Properties defaults = new Properties();\n loadPropertiesFromClasspath(defaults, DEFAULT_PROPERTIES_FILE_NAME);\n \/\/讀取classpath下,transactions.properties配置,覆蓋transactions-defaults.properties中相同key的值\n Properties transactionsProperties = new Properties(defaults);\n loadPropertiesFromClasspath(transactionsProperties, TRANSACTIONS_PROPERTIES_FILE_NAME);\n \/\/讀取classpath下,jta.properties,覆蓋transactions-defaults.properties、transactions.properties中相同key的值\n Properties jtaProperties = new Properties(transactionsProperties);\n loadPropertiesFromClasspath(jtaProperties, JTA_PROPERTIES_FILE_NAME);\n\n \/\/讀取通過java -Dcom.atomikos.icatch.file方式指定的自定義配置文件路徑,覆蓋之前的同名配置\n Properties customProperties = new Properties(jtaProperties);\n loadPropertiesFromCustomFilePath(customProperties);\n \/\/最終構造一個ConfigProperties對象,來表示實際要使用的配置\n Properties finalProperties = new Properties(customProperties);\n return new ConfigProperties(finalProperties);\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來重點關注, "},{"type":"codeinline","content":[{"type":"text","text":"Configuration.init()"}]},{"type":"text","text":", 進行初始化。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"ublic static synchronized boolean init() {\n boolean startupInitiated = false;\n if (service_ == null) {\n startupInitiated = true;\n \/\/SPI方式加載插件註冊,無需過多關心 \n addAllTransactionServicePluginServicesFromClasspath();\n ConfigProperties configProperties = getConfigProperties();\n \/\/調用插件的beforeInit方法進行初始化話,無需過多關心\n notifyBeforeInit(configProperties);\n \/\/進行事務日誌恢復的初始化,很重要,接下來詳解\n assembleSystemComponents(configProperties);\n \/\/進入系統註解的初始化,一般重要\n initializeSystemComponents(configProperties);\n notifyAfterInit();\n if (configProperties.getForceShutdownOnVmExit()) {\n addShutdownHook(new ForceShutdownHook());\n }\n }\n return startupInitiated;\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們先來關注 "},{"type":"codeinline","content":[{"type":"text","text":"assembleSystemComponents(configProperties);"}]},{"type":"text","text":" 進入它,進入"},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.icatch.provider.imp.AssemblerImp.assembleTransactionService()"}]},{"type":"text","text":"方法:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"@Override\n public TransactionServiceProvider assembleTransactionService(\n ConfigProperties configProperties) {\n RecoveryLog recoveryLog =null;\n \/\/打印日誌\n logProperties(configProperties.getCompletedProperties());\n \/\/生成唯一名字\n String tmUniqueName = configProperties.getTmUniqueName();\n\n long maxTimeout = configProperties.getMaxTimeout();\n int maxActives = configProperties.getMaxActives();\n boolean threaded2pc = configProperties.getThreaded2pc();\n \/\/SPI方式加載OltpLog ,這是最重要的擴展地方,如果用戶沒有SPI的方式去擴展那麼就爲null \n OltpLog oltpLog = createOltpLogFromClasspath();\n if (oltpLog == null) {\n LOGGER.logInfo(\"Using default (local) logging and recovery...\"); \n \/\/創建事務日誌存儲資源\n Repository repository = createRepository(configProperties); \n oltpLog = createOltpLog(repository);\n \/\/??? Assemble recoveryLog\n recoveryLog = createRecoveryLog(repository); \n }\n StateRecoveryManagerImp recoveryManager = new StateRecoveryManagerImp();\n recoveryManager.setOltpLog(oltpLog);\n \/\/生成唯一id生成器,以後生成XID會用的到\n UniqueIdMgr idMgr = new UniqueIdMgr ( tmUniqueName );\n int overflow = idMgr.getMaxIdLengthInBytes() - MAX_TID_LENGTH;\n if ( overflow > 0 ) {\n \/\/ see case 73086\n String msg = \"Value too long : \" + tmUniqueName;\n LOGGER.logFatal ( msg );\n throw new SysException(msg);\n }\n return new TransactionServiceImp(tmUniqueName, recoveryManager, idMgr, maxTimeout, maxActives, !threaded2pc, recoveryLog);\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們重點來分析"},{"type":"codeinline","content":[{"type":"text","text":"createOltpLogFromClasspath()"}]},{"type":"text","text":", 採用SPI的加載方式來獲取,默認這裏會返回 "},{"type":"codeinline","content":[{"type":"text","text":"null"}]},{"type":"text","text":", 什麼意思呢?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就是當沒有擴展的時候,atomikos,會創建框架自定義的資源,來存儲事務日誌。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"private OltpLog createOltpLogFromClasspath() {\n OltpLog ret = null;\n ServiceLoader loader = ServiceLoader.load(OltpLogFactory.class,Configuration.class.getClassLoader());\n int i = 0;\n for (OltpLogFactory l : loader ) {\n ret = l.createOltpLog();\n i++;\n }\n if (i > 1) {\n String msg = \"More than one OltpLogFactory found in classpath - error in configuration!\";\n LOGGER.logFatal(msg);\n throw new SysException(msg);\n }\n return ret;\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們跟着進入 "},{"type":"codeinline","content":[{"type":"text","text":"Repository repository = createRepository(configProperties);"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" private CachedRepository createCoordinatorLogEntryRepository(\n ConfigProperties configProperties) throws LogException {\n \/\/創建內存資源存儲\n InMemoryRepository inMemoryCoordinatorLogEntryRepository = new InMemoryRepository();\n \/\/進行初始化\n inMemoryCoordinatorLogEntryRepository.init();\n \/\/創建使用文件存儲資源作爲backup\n FileSystemRepository backupCoordinatorLogEntryRepository = new FileSystemRepository();\n \/\/進行初始化\n backupCoordinatorLogEntryRepository.init();\n \/\/內存與file資源進行合併\n CachedRepository repository = new CachedRepository(inMemoryCoordinatorLogEntryRepository, backupCoordinatorLogEntryRepository);\n repository.init();\n return repository;\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏就會創建出 "},{"type":"codeinline","content":[{"type":"text","text":"CachedRepository"}]},{"type":"text","text":",裏面包含了 "},{"type":"codeinline","content":[{"type":"text","text":"InMemoryRepository"}]},{"type":"text","text":" 與 "},{"type":"codeinline","content":[{"type":"text","text":"FileSystemRepository"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回到主線 "},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.icatch.config.Configuration.init()"}]},{"type":"text","text":", 最後來分析下"},{"type":"codeinline","content":[{"type":"text","text":"notifyAfterInit();"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" private static void notifyAfterInit() {\n \/\/進行插件的初始化\n for (TransactionServicePlugin p : tsListenersList_) {\n p.afterInit();\n }\n for (LogAdministrator a : logAdministrators_) {\n a.registerLogControl(service_.getLogControl());\n }\n \/\/設置事務恢復服務,進行事務的恢復\n for (RecoverableResource r : resourceList_ ) {\n r.setRecoveryService(recoveryService_);\n }\n\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"插件的初始化會進入"},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.icatch.jta.JtaTransactionServicePlugin.afterInit()"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" public void afterInit() {\n TransactionManagerImp.installTransactionManager(Configuration.getCompositeTransactionManager(), autoRegisterResources);\n \/\/如果我們自定義擴展了 OltpLog ,這裏就會返回null,如果是null,那麼XaResourceRecoveryManager就是null\n RecoveryLog recoveryLog = Configuration.getRecoveryLog();\n long maxTimeout = Configuration.getConfigProperties().getMaxTimeout();\n if (recoveryLog != null) {\n XaResourceRecoveryManager.installXaResourceRecoveryManager(new DefaultXaRecoveryLog(recoveryLog, maxTimeout),Configuration.getConfigProperties().getTmUniqueName());\n }\n\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"重點注意 "},{"type":"codeinline","content":[{"type":"text","text":"RecoveryLog recoveryLog = Configuration.getRecoveryLog();"}]},{"type":"text","text":" ,如果用戶採用"},{"type":"codeinline","content":[{"type":"text","text":"SPI的方式"}]},{"type":"text","text":",擴展了"},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.recovery.OltpLog"}]},{"type":"text","text":" ,"},{"type":"codeinline","content":[{"type":"text","text":"這裏就會返回 null"}]},{"type":"text","text":"。如果是null,則不會對 "},{"type":"codeinline","content":[{"type":"text","text":"XaResourceRecoveryManager"}]},{"type":"text","text":" 進行初始化。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回到 "},{"type":"codeinline","content":[{"type":"text","text":"notifyAfterInit()"}]},{"type":"text","text":", 我們來分析 "},{"type":"codeinline","content":[{"type":"text","text":"setRecoveryService"}]},{"type":"text","text":"。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public void setRecoveryService ( RecoveryService recoveryService )\n throws ResourceException\n {\n\n if ( recoveryService != null ) {\n if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( \"Installing recovery service on resource \"\n + getName () );\n this.branchIdentifier=recoveryService.getName();\n recover();\n }\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們進入 "},{"type":"codeinline","content":[{"type":"text","text":"recover()"}]},{"type":"text","text":" 方法:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" public void recover() {\n XaResourceRecoveryManager xaResourceRecoveryManager = XaResourceRecoveryManager.getInstance();\n \/\/null for LogCloud recovery\n if (xaResourceRecoveryManager != null) { \n try {\n xaResourceRecoveryManager.recover(getXAResource());\n } catch (Exception e) {\n refreshXAResource(); \/\/cf case 156968\n }\n\n }\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看到最關鍵的註釋了嗎,如果用戶採用"},{"type":"codeinline","content":[{"type":"text","text":"SPI的方式"}]},{"type":"text","text":",擴展了"},{"type":"codeinline","content":[{"type":"text","text":"com.atomikos.recovery.OltpLog"}]},{"type":"text","text":",那麼"},{"type":"codeinline","content":[{"type":"text","text":"XaResourceRecoveryManager"}]},{"type":"text","text":" 爲null,則就會進行雲端恢復,反之則進行事務恢復。事務恢復很複雜,我們會單獨來講。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章