SpringBoot CommandLineRunner的異步任務(wù)機(jī)制使用
在SpringBoot中,CommandLineRunner
本身并不是一個(gè)直接支持異步任務(wù)的機(jī)制。
CommandLineRunner
接口定義了一個(gè)在 Spring Boot 應(yīng)用程序啟動(dòng)后立即同步執(zhí)行的方法 run(String... args)
。
這意味著,通過實(shí)現(xiàn) CommandLineRunner
接口定義的任務(wù)將在主線程中順序執(zhí)行,而不會(huì)創(chuàng)建新的線程來異步執(zhí)行這些任務(wù)。
然而,如果你希望在 CommandLineRunner
中執(zhí)行異步任務(wù),你可以手動(dòng)創(chuàng)建線程或使用 Spring 的異步執(zhí)行功能。
以下是一些實(shí)現(xiàn)異步任務(wù)的方法。
1.概要分析
1.1 手動(dòng)創(chuàng)建線程
在 CommandLineRunner
的 run
方法中,你可以直接創(chuàng)建并啟動(dòng)一個(gè)新的線程來執(zhí)行異步任務(wù)。
這種方法簡(jiǎn)單直接,但需要注意線程管理和異常處理。
@Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { new Thread(() -> { // 異步執(zhí)行的代碼 System.out.println("異步任務(wù)執(zhí)行中..."); // 模擬耗時(shí)操作 try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("異步任務(wù)完成"); }).start(); // 主線程繼續(xù)執(zhí)行,不會(huì)等待異步任務(wù)完成 System.out.println("CommandLineRunner 執(zhí)行完畢,主線程繼續(xù)"); } }
1.2 使用 Spring 的異步執(zhí)行功能
如果你希望利用 Spring 的異步支持來執(zhí)行異步任務(wù),你可以在 CommandLineRunner
中注入一個(gè)使用 @Async
注解的服務(wù)。但是,需要注意的是,由于 CommandLineRunner
的 run
方法本身是在 Spring 容器完全初始化之后同步執(zhí)行的,因此即使你調(diào)用了一個(gè)異步服務(wù)方法,run
方法本身仍然會(huì)立即返回,不會(huì)等待異步任務(wù)完成。
首先,你需要在 Spring Boot 應(yīng)用中啟用異步支持,通過在啟動(dòng)類上添加 @EnableAsync
注解。
然后,你可以創(chuàng)建一個(gè)異步服務(wù):
@Service public class AsyncService { @Async public void executeAsyncTask() { // 異步執(zhí)行的代碼 System.out.println("異步任務(wù)執(zhí)行中..."); // 模擬耗時(shí)操作 try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("異步任務(wù)完成"); } }
在 CommandLineRunner
中注入并使用這個(gè)服務(wù):
@Component public class MyCommandLineRunner implements CommandLineRunner { @Autowired private AsyncService asyncService; @Override public void run(String... args) throws Exception { asyncService.executeAsyncTask(); // 調(diào)用異步方法,但 CommandLineRunner 的 run 方法會(huì)立即返回 System.out.println("CommandLineRunner 執(zhí)行完畢,主線程繼續(xù),不會(huì)等待異步任務(wù)完成"); } }
雖然 CommandLineRunner
本身不支持異步執(zhí)行,但你可以通過手動(dòng)創(chuàng)建線程或使用 Spring 的異步支持來在 CommandLineRunner
中執(zhí)行異步任務(wù)。然而,需要注意的是,CommandLineRunner
的 run
方法本身仍然是同步執(zhí)行的,它不會(huì)等待任何異步任務(wù)完成。
如果你的應(yīng)用程序依賴于異步任務(wù)的結(jié)果,你可能需要采用其他機(jī)制(如 Future
、CompletableFuture
或消息隊(duì)列)來管理異步任務(wù)的執(zhí)行和結(jié)果。
2.核心原理分析
org.springframework.boot.CommandLineRunner
是 Spring Boot 框架中的一個(gè)核心接口,其原理分析可以從以下幾個(gè)方面進(jìn)行。
2.1 接口定義與功能
CommandLineRunner
是一個(gè)函數(shù)式接口(Functional Interface),它只定義了一個(gè)抽象方法 run(String... args)
。
這個(gè)方法在 Spring Boot 應(yīng)用程序啟動(dòng)完成后被調(diào)用,允許開發(fā)者執(zhí)行一些初始化操作或啟動(dòng)后的任務(wù)。這些任務(wù)可能包括數(shù)據(jù)初始化、緩存預(yù)熱、日志記錄等。
2.2 執(zhí)行時(shí)機(jī)
當(dāng) Spring Boot 應(yīng)用程序啟動(dòng)時(shí),Spring 容器會(huì)完成一系列的初始化操作,包括 Bean 的加載和依賴注入等。
在所有 Spring Bean 都初始化完成后,Spring Boot 會(huì)查找所有實(shí)現(xiàn)了 CommandLineRunner
接口的 Bean,并依次調(diào)用它們的 run
方法。
這意味著 CommandLineRunner
的執(zhí)行時(shí)機(jī)是在 Spring 上下文準(zhǔn)備好之后,但在應(yīng)用程序?qū)ν馓峁┓?wù)之前。
2.3 命令行參數(shù)傳遞
CommandLineRunner
的 run
方法接收一個(gè) String... args
參數(shù),這個(gè)參數(shù)包含了啟動(dòng)應(yīng)用程序時(shí)傳遞給它的命令行參數(shù)。
這使得開發(fā)者可以根據(jù)命令行參數(shù)的不同來執(zhí)行不同的初始化邏輯。
2.4 實(shí)現(xiàn)與注冊(cè)
要使用 CommandLineRunner
,開發(fā)者需要?jiǎng)?chuàng)建一個(gè)類并實(shí)現(xiàn)這個(gè)接口,然后重寫 run
方法以定義自己的初始化邏輯。
為了讓 Spring 容器能夠掃描到這個(gè)實(shí)現(xiàn)類并將其注冊(cè)為一個(gè) Bean,通常會(huì)在類上添加 @Component
或其他類似的注解(如 @Service
、@Repository
等)。此外,也可以通過編程方式在配置類中顯式地注冊(cè)這個(gè) Bean。
2.5 執(zhí)行順序
如果應(yīng)用程序中有多個(gè)實(shí)現(xiàn)了 CommandLineRunner
接口的類,那么它們的 run
方法將按照一定的順序執(zhí)行。
默認(rèn)情況下,執(zhí)行順序取決于 Spring 容器注冊(cè)這些 Bean 的順序。但是,開發(fā)者可以通過 @Order
注解或?qū)崿F(xiàn) Ordered
接口來指定執(zhí)行順序。
@Order
注解的值越小,優(yōu)先級(jí)越高,相應(yīng)的 run
方法就會(huì)越早執(zhí)行。
2.6 與 ApplicationRunner 的區(qū)別
值得注意的是,Spring Boot 還提供了另一個(gè)類似的接口 ApplicationRunner
,它也用于在應(yīng)用程序啟動(dòng)后執(zhí)行初始化任務(wù)。與 CommandLineRunner
不同的是,ApplicationRunner
的 run
方法接收一個(gè) ApplicationArguments
參數(shù)而不是 String... args
。
ApplicationArguments
提供了對(duì)命令行參數(shù)的更高級(jí)別訪問,包括選項(xiàng)和非選項(xiàng)參數(shù)等。此外,如果同時(shí)存在 CommandLineRunner
和 ApplicationRunner
的實(shí)現(xiàn),那么 CommandLineRunner
的實(shí)現(xiàn)會(huì)先于 ApplicationRunner
的實(shí)現(xiàn)被調(diào)用。
2.7 應(yīng)用場(chǎng)景
CommandLineRunner
適用于需要在應(yīng)用程序啟動(dòng)后立即執(zhí)行的任務(wù)場(chǎng)景,如數(shù)據(jù)初始化、配置加載、緩存預(yù)熱等。通過使用 CommandLineRunner
,開發(fā)者可以確保這些任務(wù)在應(yīng)用程序?qū)ν馓峁┓?wù)之前完成,從而提高應(yīng)用程序的性能和用戶體驗(yàn)。
綜上所述,org.springframework.boot.CommandLineRunner
是 Spring Boot 框架中用于執(zhí)行啟動(dòng)后任務(wù)的強(qiáng)大機(jī)制,它通過簡(jiǎn)單的接口定義和靈活的注冊(cè)方式,為開發(fā)者提供了方便、高效的初始化操作手段。
3.部分源碼分析
3.1 啟動(dòng)Spring Boot應(yīng)用程序
/** * 啟動(dòng)應(yīng)用程序。 * * @param args 命令行參數(shù) * @return ConfigurableApplicationContext 應(yīng)用程序上下文 */ public ConfigurableApplicationContext run(String... args) { // 記錄應(yīng)用程序啟動(dòng)時(shí)間 long startTime = System.nanoTime(); // 創(chuàng)建引導(dǎo)上下文 DefaultBootstrapContext bootstrapContext = createBootstrapContext(); ConfigurableApplicationContext context = null; // 配置無(wú)頭模式屬性 configureHeadlessProperty(); // 獲取啟動(dòng)監(jiān)聽器 SpringApplicationRunListeners listeners = getRunListeners(args); // 通知監(jiān)聽器應(yīng)用程序即將啟動(dòng) listeners.starting(bootstrapContext, this.mainApplicationClass); try { // 創(chuàng)建并配置應(yīng)用參數(shù) ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 配置忽略BeanInfo的設(shè)置 configureIgnoreBeanInfo(environment); // 打印啟動(dòng)橫幅 Banner printedBanner = printBanner(environment); // 創(chuàng)建應(yīng)用程序上下文 context = createApplicationContext(); // 設(shè)置應(yīng)用啟動(dòng)器 context.setApplicationStartup(this.applicationStartup); // 準(zhǔn)備應(yīng)用程序上下文 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 刷新上下文,使配置生效 refreshContext(context); // 啟動(dòng)后配置 afterRefresh(context, applicationArguments); // 計(jì)算應(yīng)用程序啟動(dòng)時(shí)間 Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); // 如果啟用了啟動(dòng)信息日志,則記錄啟動(dòng)信息 if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup); } // 通知監(jiān)聽器應(yīng)用程序已啟動(dòng) listeners.started(context, timeTakenToStartup); // 調(diào)用應(yīng)用程序運(yùn)行者 callRunners(context, applicationArguments); } catch (Throwable ex) { // 處理啟動(dòng)失敗 handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try { // 計(jì)算應(yīng)用程序就緒時(shí)間 Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); // 通知監(jiān)聽器應(yīng)用程序已就緒 listeners.ready(context, timeTakenToReady); } catch (Throwable ex) { // 處理就緒失敗 handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } // 返回應(yīng)用程序上下文 return context; }
3.2 調(diào)用所有的Runner實(shí)現(xiàn)類
/** * 調(diào)用所有的Runner實(shí)現(xiàn)類。 * * 本方法的目的是遍歷ApplicationContext中所有的Runner實(shí)例,并根據(jù)它們的類型分別調(diào)用相應(yīng)的方法。 * Runner和CommandLineRunner是Spring Boot提供的一組接口,用于在應(yīng)用程序啟動(dòng)后執(zhí)行一些自定義的初始化邏輯。 * 這里通過判斷Runner的類型,來決定是調(diào)用ApplicationRunner還是CommandLineRunner的方法,從而實(shí)現(xiàn)對(duì)不同類型Runner的兼容處理。 * * @param context Spring應(yīng)用上下文,用于獲取BeanProvider以獲取Runner實(shí)例。 * @param args 命令行參數(shù),傳遞給每個(gè)Runner的調(diào)用方法。 */ private void callRunners(ApplicationContext context, ApplicationArguments args) { // 通過BeanProvider獲取所有Runner類型的bean,并以有序的方式遍歷它們 context.getBeanProvider(Runner.class).orderedStream().forEach((runner) -> { // 如果runner是ApplicationRunner類型,則調(diào)用callRunner方法,并傳入ApplicationRunner和命令行參數(shù) if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } // 如果runner是CommandLineRunner類型,則同樣調(diào)用callRunner方法,并傳入CommandLineRunner和命令行參數(shù) if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } }); }
4.典型的應(yīng)用場(chǎng)景分析
Seata中的TM(Transaction Manager,事務(wù)管理器)和RM(Resource Manager,資源管理器)是分布式事務(wù)框架中的關(guān)鍵角色,它們各自承擔(dān)著特定的職責(zé),以確保分布式事務(wù)的一致性和完整性。
4.1 TM(Transaction Manager,事務(wù)管理器)
4.1.1 定義與職責(zé)
- (1)TM負(fù)責(zé)定義全局事務(wù)的范圍,即開始全局事務(wù)、提交或回滾全局事務(wù)。它是分布式事務(wù)的發(fā)起者和終結(jié)者,類似于本地事務(wù)中的begin…commit…rollback操作,但針對(duì)的是全局的分布式事務(wù)。
- (2)在Seata框架中,TM與業(yè)務(wù)系統(tǒng)集成在一起,作為客戶端存在。當(dāng)業(yè)務(wù)操作需要跨多個(gè)服務(wù)或數(shù)據(jù)庫(kù)時(shí),TM會(huì)啟動(dòng)一個(gè)全局事務(wù),并管理這個(gè)事務(wù)的生命周期。
4.1.2 工作流程
- (1)TM向TC(Transaction Coordinator,事務(wù)協(xié)調(diào)者)請(qǐng)求開啟一個(gè)全局事務(wù),TC生成一個(gè)全局唯一的事務(wù)ID(XID)并返回給TM。
- (2)TM攜帶XID進(jìn)行遠(yuǎn)程服務(wù)調(diào)用,XID在微服務(wù)調(diào)用鏈中傳播,確保所有參與的分支事務(wù)都能被正確關(guān)聯(lián)到全局事務(wù)中。
- (3)當(dāng)業(yè)務(wù)操作完成后,TM根據(jù)業(yè)務(wù)邏輯向TC發(fā)起全局事務(wù)的提交或回滾請(qǐng)求。
- (4)TC根據(jù)各分支事務(wù)的執(zhí)行結(jié)果,決定全局事務(wù)的提交或回滾,并通知所有RM進(jìn)行相應(yīng)的操作。
4.2 RM(Resource Manager,資源管理器)
4.2.1 定義與職責(zé)
- (1)RM負(fù)責(zé)管理分支事務(wù)處理的資源,如數(shù)據(jù)庫(kù)連接、消息隊(duì)列等。它是分布式事務(wù)中具體執(zhí)行操作的組件。
- (2)RM與TC進(jìn)行通信,注冊(cè)分支事務(wù)、報(bào)告分支事務(wù)的狀態(tài),并根據(jù)TC的指令驅(qū)動(dòng)分支事務(wù)的提交或回滾。
- (3)在Seata框架中,RM同樣與業(yè)務(wù)系統(tǒng)集成在一起,作為客戶端存在。每個(gè)參與全局事務(wù)的服務(wù)或數(shù)據(jù)庫(kù)操作,都會(huì)有一個(gè)對(duì)應(yīng)的RM來管理。
4.2.2 工作流程
- (1)在執(zhí)行具體業(yè)務(wù)操作之前,RM會(huì)向TC注冊(cè)分支事務(wù),并將其納入全局事務(wù)的管轄范圍。
- (2)RM執(zhí)行本地事務(wù)操作,如數(shù)據(jù)庫(kù)更新、消息發(fā)送等,并確保這些操作是可回滾和持久化的。
- (3)RM將分支事務(wù)的執(zhí)行結(jié)果(提交或回滾)上報(bào)給TC。
- (4)當(dāng)TC收到TM的全局事務(wù)提交或回滾請(qǐng)求時(shí),它會(huì)根據(jù)各分支事務(wù)的狀態(tài)決定全局事務(wù)的結(jié)果,并通知所有RM進(jìn)行相應(yīng)的提交或回滾操作。
4.3 Seata RM和TM與Seata Server之間的RPC通信
在Seata中,TM(Transaction Manager,事務(wù)管理器)與Seata Server(即TC,Transaction Coordinator,事務(wù)協(xié)調(diào)者)之間的通信是通過RPC(Remote Procedure Call,遠(yuǎn)程過程調(diào)用)實(shí)現(xiàn)的。
RPC是一種允許程序在網(wǎng)絡(luò)上調(diào)用遠(yuǎn)程計(jì)算機(jī)上程序的技術(shù),就像調(diào)用本地計(jì)算機(jī)上的程序一樣。
4.3.1 TM與Seata Server之間的RPC通信
(1)建立連接
- TM在啟動(dòng)時(shí)會(huì)嘗試與Seata Server建立長(zhǎng)連接。這個(gè)連接是通過Netty等網(wǎng)絡(luò)通信框架實(shí)現(xiàn)的,Netty提供了高效、異步的網(wǎng)絡(luò)通信能力。
- 在建立連接的過程中,TM會(huì)向Seata Server發(fā)送注冊(cè)請(qǐng)求,包括應(yīng)用ID、事務(wù)組名稱等信息,以便Seata Server能夠識(shí)別和管理該TM。
(2)事務(wù)管理
- 一旦連接建立,TM就可以通過RPC調(diào)用Seata Server提供的服務(wù)來管理全局事務(wù)。
- 例如,當(dāng)業(yè)務(wù)操作需要跨多個(gè)服務(wù)或數(shù)據(jù)庫(kù)時(shí),TM會(huì)向Seata Server請(qǐng)求開啟一個(gè)全局事務(wù),并獲取一個(gè)全局唯一的事務(wù)ID(XID)。
- 在執(zhí)行遠(yuǎn)程服務(wù)調(diào)用時(shí),TM會(huì)將XID攜帶在調(diào)用中,以便參與的RM能夠識(shí)別并將分支事務(wù)注冊(cè)到全局事務(wù)中。
- 當(dāng)業(yè)務(wù)操作完成后,TM會(huì)根據(jù)業(yè)務(wù)邏輯向Seata Server發(fā)起全局事務(wù)的提交或回滾請(qǐng)求。
(3)通信協(xié)議
- Seata使用自定義的通信協(xié)議來進(jìn)行RPC通信,該協(xié)議支持事務(wù)的創(chuàng)建、提交、回滾等操作。
- 通信過程中,Seata還實(shí)現(xiàn)了心跳檢測(cè)、超時(shí)重試等機(jī)制來確保通信的可靠性和穩(wěn)定性。
(4)性能優(yōu)化
- 為了提高RPC通信的性能,Seata采用了多種優(yōu)化策略,如使用Netty的主從Reactor多線程模型來處理并發(fā)請(qǐng)求、采用批量發(fā)送請(qǐng)求來減少網(wǎng)絡(luò)開銷等。
4.3.2 RM與Seata Server之間的RPC通信
在Seata中,RM負(fù)責(zé)管理分支事務(wù)處理的資源,如數(shù)據(jù)庫(kù)連接等。
當(dāng)RM執(zhí)行分支事務(wù)時(shí),它需要與Seata Server進(jìn)行通信,以注冊(cè)分支事務(wù)、報(bào)告分支事務(wù)的狀態(tài),并根據(jù)Seata Server的指令驅(qū)動(dòng)分支事務(wù)的提交或回滾。
這種通信是通過RPC機(jī)制實(shí)現(xiàn)的,它允許RM遠(yuǎn)程調(diào)用Seata Server上的服務(wù)。
(1)建立連接
- 當(dāng)RM啟動(dòng)時(shí),它會(huì)根據(jù)配置嘗試與Seata Server建立長(zhǎng)連接。這個(gè)連接是通過Netty等網(wǎng)絡(luò)通信框架實(shí)現(xiàn)的,Netty提供了高效、異步的網(wǎng)絡(luò)通信能力。
- 在建立連接的過程中,RM會(huì)向Seata Server發(fā)送注冊(cè)請(qǐng)求,包括應(yīng)用ID、事務(wù)組名稱等信息,以便Seata Server能夠識(shí)別和管理該RM。
(2)分支事務(wù)注冊(cè)
- 當(dāng)RM執(zhí)行一個(gè)分支事務(wù)時(shí),它會(huì)向Seata Server注冊(cè)該分支事務(wù)。注冊(cè)過程中,RM會(huì)攜帶全局事務(wù)ID(XID)等信息,以便Seata Server能夠?qū)⒃摲种聞?wù)關(guān)聯(lián)到相應(yīng)的全局事務(wù)中。
- Seata Server在收到注冊(cè)請(qǐng)求后,會(huì)為該分支事務(wù)分配一個(gè)唯一的分支事務(wù)ID,并將其注冊(cè)到全局事務(wù)中。
(3)狀態(tài)報(bào)告與指令執(zhí)行
- 在分支事務(wù)執(zhí)行過程中,RM會(huì)定期向Seata Server報(bào)告分支事務(wù)的狀態(tài),如正在執(zhí)行、已提交、已回滾等。
- 當(dāng)全局事務(wù)需要提交或回滾時(shí),Seata Server會(huì)根據(jù)各分支事務(wù)的狀態(tài)和結(jié)果,向RM發(fā)送相應(yīng)的提交或回滾指令。
- RM在收到指令后,會(huì)執(zhí)行相應(yīng)的操作,如提交本地事務(wù)、回滾本地事務(wù)等,并將執(zhí)行結(jié)果報(bào)告給Seata Server。
(4)心跳檢測(cè)與異常處理
- 為了保持連接的活躍狀態(tài),RM會(huì)定期向Seata Server發(fā)送心跳消息。
- 如果Seata Server在一段時(shí)間內(nèi)沒有收到RM的心跳消息,它可能會(huì)認(rèn)為RM已經(jīng)離線,并采取相應(yīng)的異常處理措施,如重試連接、記錄日志等。
Seata RM與Seata Server之間的RPC通信是Seata分布式事務(wù)框架中的重要組成部分。通過高效的RPC通信機(jī)制,RM能夠遠(yuǎn)程調(diào)用Seata Server提供的服務(wù)來管理分支事務(wù),確保分布式事務(wù)的一致性和完整性。同時(shí),Seata還通過多種優(yōu)化策略來提高RPC通信的性能和可靠性。
4.4 Seata Server利用SpringBoot CommandLineRunner啟動(dòng)服務(wù)端通信渠道
在Seata Server中,ServerRunner
類是一個(gè)重要的組件,它繼承自Spring Boot的CommandLineRunner
接口。
這意味著在Spring Boot應(yīng)用啟動(dòng)后,ServerRunner
的run()
方法會(huì)被自動(dòng)執(zhí)行。這種方法通常用于在應(yīng)用啟動(dòng)后立即執(zhí)行一段特定的代碼,比如初始化資源、啟動(dòng)服務(wù)等。
ServerRunner
類的主要職責(zé)是初始化Netty通信渠道,即NettyRemotingServer
。
Netty是一個(gè)高性能的異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用于快速開發(fā)可維護(hù)的高性能協(xié)議服務(wù)器和客戶端。
在Seata中,Netty用于節(jié)點(diǎn)間的通信,包括事務(wù)協(xié)調(diào)器(TC)、事務(wù)管理器(TM)和資源管理器(RM)之間的通信。
以下是ServerRunner
類中run()
方法可能包含的邏輯的一個(gè)簡(jiǎn)單示例:
@Override public void run(String... args) throws Exception { // 初始化Netty通信服務(wù)器 NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(); nettyRemotingServer.setPort(serverPort); // 設(shè)置服務(wù)器端口 nettyRemotingServer.setHost(serverHost); // 設(shè)置服務(wù)器主機(jī)地址 nettyRemotingServer.start(); // 啟動(dòng)服務(wù)器 // 其他初始化邏輯,比如注冊(cè)服務(wù)等 }
在這個(gè)例子中,run()
方法首先創(chuàng)建了一個(gè)NettyRemotingServer
實(shí)例,并設(shè)置了服務(wù)器的主機(jī)地址和端口號(hào)。然后,它調(diào)用start()
方法來啟動(dòng)Netty服務(wù)器,這樣Seata Server就可以監(jiān)聽來自其他節(jié)點(diǎn)的請(qǐng)求了。
總的來說
ServerRunner
類在Seata Server中扮演著重要的角色,它負(fù)責(zé)初始化Netty通信渠道,為Seata節(jié)點(diǎn)間的通信提供基礎(chǔ)設(shè)施。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Dubbo?LoadBalance基于權(quán)重的隨機(jī)負(fù)載均衡算法提高服務(wù)性能
這篇文章主要為大家介紹了Dubbo?LoadBalance基于權(quán)重的隨機(jī)負(fù)載均衡算法提高服務(wù)性能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2023-10-10SpringMVC學(xué)習(xí)之JSON和全局異常處理詳解
在項(xiàng)目上線之后,往往會(huì)出現(xiàn)一些不可預(yù)料的異常信息,對(duì)于邏輯性或設(shè)計(jì)性問題,開發(fā)人員或者維護(hù)人員需要通過日志,查看異常信息并排除異常,這篇文章主要給大家介紹了關(guān)于SpringMVC學(xué)習(xí)之JSON和全局異常處理的相關(guān)資料,需要的朋友可以參考下2022-10-10Java Websocket Canvas實(shí)現(xiàn)井字棋網(wǎng)絡(luò)游戲
這篇文章主要介紹了Java Websocket Canvas實(shí)現(xiàn)井字棋網(wǎng)絡(luò)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08原生java代碼實(shí)現(xiàn)碼云第三方驗(yàn)證登錄的示例代碼
這篇文章主要介紹了原生java代碼實(shí)現(xiàn)碼云第三方驗(yàn)證登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04SpringBoot集成tomcat詳解實(shí)現(xiàn)過程
采用spring boot之后,一切變得如此簡(jiǎn)單,打包->java-jar->運(yùn)維,只需要一個(gè)jar包便可以隨意部署安裝。這篇文章,將對(duì) spring boot集成tomcat的源碼進(jìn)行分析,探索其內(nèi)部的原理2023-02-02springboot + swagger 實(shí)例代碼
本篇文章主要介紹了springboot + swagger 實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05