java開(kāi)發(fā)主流定時(shí)任務(wù)解決方案全橫評(píng)詳解
引言
定時(shí)任務(wù)作為一種按照約定時(shí)間執(zhí)行預(yù)期邏輯的通用模式,在企業(yè)級(jí)開(kāi)發(fā)中承載著豐富的業(yè)務(wù)場(chǎng)景,諸如后臺(tái)定時(shí)同步數(shù)據(jù)生成報(bào)表,定時(shí)清理磁盤日志文件,定時(shí)掃描超時(shí)訂單進(jìn)行補(bǔ)償回調(diào)等。程序開(kāi)發(fā)人員在定時(shí)任務(wù)領(lǐng)域有著諸多框架和方案可供選擇,并借此快速實(shí)現(xiàn)業(yè)務(wù)功能實(shí)現(xiàn)產(chǎn)品上線。本文將就當(dāng)前主流定時(shí)任務(wù)解決方案進(jìn)行介紹和分析,期望可以在企業(yè)技術(shù)選型和項(xiàng)目架構(gòu)重構(gòu)時(shí)作為參考。
Crontab
目標(biāo)定位
Crontab 作為 Linux 內(nèi)置的可執(zhí)行命令,可以實(shí)現(xiàn)按照 cron 表達(dá)式生成的時(shí)間執(zhí)行指定的系統(tǒng)指令或 shell 腳本。
使用方式
crontab 命令語(yǔ)法:
crontab [-u username] [-l | -e | -r ] 參數(shù): -u : 只有root用戶才能進(jìn)行這個(gè)任務(wù),編輯某個(gè)用戶的crontab -e : 編輯 crontab 的工作內(nèi)容 -l : 查閱 crontab 的工作內(nèi)容 -r : 移除所有的 crontab 的工作內(nèi)容
配置文件示例:
* * * * * touch ~/crontab_test * 3 * * * ~/backup 0 */2 * * * /sbin/service httpd restart
實(shí)現(xiàn)原理
crond 守護(hù)進(jìn)程是通過(guò) Linux 啟動(dòng)時(shí)的 init 進(jìn)程啟動(dòng),由 cornd 每分鐘會(huì)檢查/etc/crontab 配置文件中是否有需要執(zhí)行的任務(wù),并通過(guò) /var/log/cron 文件輸出定時(shí)任務(wù)的執(zhí)行情況。用戶可以使用 Crontab 命令管理/etc/crontab 配置文件。
方案分析
借助 Crontab 用戶可以十分便利的快速實(shí)現(xiàn)簡(jiǎn)易的定時(shí)任務(wù)功能,但存在以下痛點(diǎn):
- 定時(shí)任務(wù)與指定 linux 機(jī)器綁定,當(dāng)機(jī)器擴(kuò)容或者更換時(shí)需要重新配置 contab,同時(shí)存在單點(diǎn)故障風(fēng)險(xiǎn)
- 隨著定時(shí)任務(wù)規(guī)模增多,無(wú)統(tǒng)一視角對(duì)其進(jìn)行任務(wù)進(jìn)度的追蹤和管控,難以維護(hù)
- 功能過(guò)于簡(jiǎn)單,沒(méi)有超時(shí),重試,阻塞等任務(wù)高級(jí)特性
- 可觀測(cè)能力差,問(wèn)題排查定位困難
- 任務(wù)常駐,當(dāng)無(wú)任務(wù)執(zhí)行時(shí)造成不必要的資源成本浪費(fèi)
Spring Task
目標(biāo)定位
Spring 框架提供了開(kāi)箱即用的定時(shí)調(diào)度功能,用戶可以通過(guò) xml 或者@Scheduled 注解的方式標(biāo)識(shí)指定方法執(zhí)行的周期。Spring Task 支持多種任務(wù)執(zhí)行模式,包括帶時(shí)區(qū)配置的 corn,固定延遲,固定速率等。
使用方式
代碼實(shí)例如下:
@EnableScheduling @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } @Component public class MyTask { @Scheduled(cron = "0 0 1 * * *") public void test() { System.out.println("test"); } }
實(shí)現(xiàn)原理
Spring Task 的原理是在初始化 bean 時(shí)借助 ScheduledAnnotationBeanPostProcessor 攔截@Scheduled 注解所標(biāo)識(shí)的方法,并根據(jù)每個(gè)方法及其注解配置構(gòu)建相應(yīng)的 Task 實(shí)例注冊(cè)到 ScheduledTaskRegistrar 中,并在單例 bean 初始化完成后通過(guò) afterSingletonsInstantiated 回調(diào)設(shè)置 ScheduledTaskRegistrar 中的調(diào)度器 TaskScheduler,其底層依賴于 jdk 并發(fā)包中的 ScheduledThreadPoolExecutor 實(shí)現(xiàn),并在 afterPropertiesSet 時(shí)將所有 Task 添加到 TaskScheduler 中調(diào)度執(zhí)行。
方案分析
借助 Spring Task 用戶可以通過(guò)注解快速實(shí)現(xiàn)對(duì)指定方法的周期性執(zhí)行,支持多種周期性策略。但與 crontab 相似,同樣有如下的痛點(diǎn):
- 默認(rèn)為單線程執(zhí)行,若前一個(gè)任務(wù)執(zhí)行時(shí)間較長(zhǎng)會(huì)導(dǎo)致后續(xù)任饑餓阻塞,需要用戶自行配置線程池
- 各個(gè)節(jié)點(diǎn)獨(dú)立運(yùn)行,存在單點(diǎn)風(fēng)險(xiǎn),無(wú)分布式協(xié)調(diào)機(jī)制,要考慮禁止并發(fā)執(zhí)行
- 隨著定時(shí)任務(wù)規(guī)模增多,無(wú)統(tǒng)一視角對(duì)其進(jìn)行任務(wù)進(jìn)度的追蹤和管控,難以維護(hù)
- 功能過(guò)于簡(jiǎn)單,沒(méi)有超時(shí),重試,阻塞等任務(wù)高級(jí)特性
- 可觀測(cè)能力差,問(wèn)題排查定位困難
- 任務(wù)常駐,當(dāng)無(wú)任務(wù)執(zhí)行時(shí)造成不必要的資源成本浪費(fèi)
ElasticJob
目標(biāo)定位
ElasticJob 作為當(dāng)當(dāng)網(wǎng)開(kāi)源的一款分布式任務(wù)框架,提供彈性調(diào)度,資源管控,作業(yè)治理等諸多特性,其已經(jīng)成為 Apache Shardingsphere 的子項(xiàng)目。ElasticJob 目前由 2 個(gè)相互獨(dú)立的子項(xiàng)目 ElasticJob-Lite 和 ElasticJob-Cloud 組成,ElasticJob-Lite 定位為輕量級(jí)無(wú)中心化解決方案,使用 jar 的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù);ElasticJob-Cloud 使用 Mesos 的解決方案,額外提供資源治理、應(yīng)用分發(fā)以及進(jìn)程隔離等服務(wù)。一般使用 ElasticJob-Lite 即可滿足需求。
使用方式
使用者需要在 yaml 中配置注冊(cè)中心 zk 的地址以及任務(wù)的配置信息:
elasticjob: regCenter: serverLists: localhost:6181 namespace: elasticjob-lite-springboot jobs: simpleJob: elasticJobClass: org.apache.shardingsphere.elasticjob.lite.example.job.SpringBootSimpleJob cron: 0/5 * * * * ? timeZone: GMT+08:00 shardingTotalCount: 3 shardingItemParameters: 0=Beijing,1=Shanghai,2=Guangzhou
實(shí)現(xiàn)對(duì)應(yīng)的接口即可標(biāo)識(shí)對(duì)應(yīng)的任務(wù),同時(shí)通過(guò)配置監(jiān)聽(tīng)器來(lái)實(shí)現(xiàn)任務(wù)執(zhí)行前后回調(diào):
public class MyElasticJob implements SimpleJob { @Override public void execute(ShardingContext context) { switch (context.getShardingItem()) { case 0: // do something by sharding item 0 break; case 1: // do something by sharding item 1 break; case 2: // do something by sharding item 2 break; // case n: ... } } } public class MyJobListener implements ElasticJobListener { @Override public void beforeJobExecuted(ShardingContexts shardingContexts) { // do something ... } @Override public void afterJobExecuted(ShardingContexts shardingContexts) { // do something ... } @Override public String getType() { return "simpleJobListener"; } }
實(shí)現(xiàn)原理
ElasticJob 底層時(shí)間調(diào)度基于 Quartz,Quartz 需要持久化業(yè)務(wù) Bean 到底層數(shù)據(jù)表中,系統(tǒng)侵入性相當(dāng)嚴(yán)重,同時(shí)通過(guò) db 鎖進(jìn)行任務(wù)搶占,不支持并行調(diào)度,不具備可擴(kuò)展性。而 ElasticJob 通過(guò)數(shù)據(jù)分片以及自定義分片參數(shù)的特性完成了水平擴(kuò)展,可以將一個(gè)任務(wù)拆分為 N 個(gè)獨(dú)立的任務(wù)項(xiàng),由分布式的服務(wù)器并行執(zhí)行各自分配到的分片項(xiàng)。比如一個(gè)數(shù)據(jù)庫(kù)中有 1 億條數(shù)據(jù),需要將這些數(shù)據(jù)讀取出來(lái)并進(jìn)行計(jì)算,就可以將這 1 億條數(shù)據(jù)劃分成 10 個(gè)分片,每一個(gè)分片讀取其中的 1 千萬(wàn)條數(shù)據(jù),然后計(jì)算后寫入數(shù)據(jù)庫(kù)。如果有三臺(tái)機(jī)器執(zhí)行,A 機(jī)器分到分片(0,1,2,9),B 機(jī)器分到分片(3,4,5),C 機(jī)器分到分片(6,7,8),這也是相比于 Quartz 最顯著的優(yōu)勢(shì)。
實(shí)現(xiàn)上 ElasticJob 使用 zookeeper 作為注冊(cè)中心進(jìn)行分布式調(diào)度協(xié)調(diào)以及 leader 節(jié)點(diǎn)的選舉,通過(guò)注冊(cè)中心的臨時(shí)節(jié)點(diǎn)的變化來(lái)感知服務(wù)器的增減,每當(dāng) leader 節(jié)點(diǎn)選舉,服務(wù)器上下線,分片總數(shù)變更時(shí)均會(huì)觸發(fā)后續(xù)的重新分片,由 leader 節(jié)點(diǎn)在下次定時(shí)任務(wù)觸發(fā)時(shí)進(jìn)行具體的分片劃分,再由各節(jié)點(diǎn)從注冊(cè)中心中獲取分片信息,作為任務(wù)的運(yùn)行參數(shù)進(jìn)行執(zhí)行。
方案分析
ElasticJob 作為分布式任務(wù)框架,解決了上述單節(jié)點(diǎn)任務(wù)無(wú)法保證任務(wù)執(zhí)行過(guò)程中的高可用和高并發(fā)下執(zhí)行的性能的問(wèn)題,并支持失敗轉(zhuǎn)移(failover)和錯(cuò)過(guò)執(zhí)行的作業(yè)重新執(zhí)行(misfire)等高級(jí)機(jī)制,但在使用過(guò)程中仍存在以下痛點(diǎn):
- 框架整體較重,需要依賴外置注冊(cè)中心zk,增加了至少三臺(tái)服務(wù)器的使用成本和維護(hù)復(fù)雜度
- 隨著任務(wù)量的不斷增多,zk 作為有狀態(tài)中間件將會(huì)成為性能瓶頸
- 可觀測(cè)能力弱,需要額外引入 db 并配置事件追蹤
- 任務(wù)常駐,當(dāng)無(wú)任務(wù)執(zhí)行時(shí)造成不必要的資源成本浪費(fèi)
XXLJob
目標(biāo)定位
XXLJob 作為大眾點(diǎn)評(píng)員工開(kāi)源的一款分布式任務(wù)框架,其核心設(shè)計(jì)目標(biāo)是開(kāi)發(fā)迅速、學(xué)習(xí)簡(jiǎn)單、輕量級(jí)、易擴(kuò)展。XXLJob 具備豐富的功能,如任務(wù)分片廣播,超時(shí)控制,失敗重試,阻塞策略等,并通過(guò)體驗(yàn)友好的白屏化控制臺(tái)對(duì)任務(wù)進(jìn)行管理和維護(hù)。
使用方式
XXLJob 分為中心式調(diào)度器和分布式執(zhí)行器兩部分組成,在使用時(shí)需要分別啟動(dòng),在調(diào)度中心啟動(dòng)時(shí)需要配置所依賴的 db 配置。
執(zhí)行器需要配置調(diào)度中心的地址:
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.accessToken= xxl.job.executor.appname=xxl-job-executor-sample xxl.job.executor.address= xxl.job.executor.ip= xxl.job.executor.port=9999 xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler xxl.job.executor.logretentiondays=30
通過(guò) bean 模式方法形式創(chuàng)建任務(wù)和前后回調(diào)的使用方式如下:
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy") public void demoJobHandler() throws Exception { int shardIndex = XxlJobHelper.getShardIndex(); int shardTotal = XxlJobHelper.getShardTotal(); XxlJobHelper.log("分片參數(shù):當(dāng)前分片序號(hào) = {}, 總分片數(shù) = {}", shardIndex, shardTotal); } public void init(){ logger.info("init"); } public void destroy(){ logger.info("destory"); }
創(chuàng)建任務(wù)完成后,需要在控制臺(tái)上配置任務(wù)的執(zhí)行策略:
實(shí)現(xiàn)原理
XXLJob 實(shí)現(xiàn)上將調(diào)度系統(tǒng)與任務(wù)解耦,其自研調(diào)度器負(fù)責(zé)管理調(diào)度信息,按照調(diào)度配置發(fā)出調(diào)度請(qǐng)求,支持可視化、簡(jiǎn)單且動(dòng)態(tài)的管理調(diào)度信息,自動(dòng)發(fā)現(xiàn)和路由,調(diào)度過(guò)期策略,重試策略,支持執(zhí)行器 Failover。執(zhí)行器負(fù)責(zé)接收調(diào)度請(qǐng)求并執(zhí)行任務(wù)邏輯,并接收任務(wù)終止請(qǐng)求和日志請(qǐng)求,負(fù)責(zé)任務(wù)超時(shí),阻塞策略等。調(diào)度器和執(zhí)行器通過(guò) restful api 進(jìn)行通信,調(diào)度器本身無(wú)狀態(tài)支持集群部署,提升調(diào)度系統(tǒng)容災(zāi)和可用性,通過(guò) mysql 維護(hù)鎖信息和持久化。執(zhí)行器無(wú)狀態(tài)支持集群部署,提升調(diào)度系統(tǒng)可用性,同時(shí)提升任務(wù)處理能力。
XXLJob 一次完整的任務(wù)調(diào)度通訊流程:首先調(diào)度中心向執(zhí)行器內(nèi)嵌 Server 發(fā)送 http 調(diào)度請(qǐng)求,然后執(zhí)行器執(zhí)行對(duì)應(yīng)的任務(wù)邏輯,待任務(wù)執(zhí)行完成或超時(shí)后執(zhí)行器發(fā)送 http 回調(diào)向調(diào)度中心返回調(diào)度結(jié)果。
方案分析
XXLJob 在開(kāi)源社區(qū)廣泛流行,憑借其簡(jiǎn)單的操作和豐富的功能已在多家公司投入使用,可以較好的滿足生產(chǎn)級(jí)別的需求,但下面的一些痛點(diǎn)需要改進(jìn):
- 需要依賴外置 DB,增加了數(shù)據(jù)庫(kù)的使用成本和維護(hù)復(fù)雜度
- 依賴 DB 鎖保證集群分布式調(diào)度的一致性,當(dāng)短時(shí)任務(wù)量不斷增多將對(duì) db 造成較大壓力,成為性能瓶頸
- 相較于無(wú)中心模式需要額外部署調(diào)度器,調(diào)度器和執(zhí)行器均需要常駐同時(shí)為保證高可用均至少兩臺(tái),當(dāng)無(wú)任務(wù)執(zhí)行時(shí)造成不必要的資源成本浪費(fèi)
Serverless Job
目標(biāo)定位
Serverless 作為云計(jì)算的最佳實(shí)踐和未來(lái)演進(jìn)趨勢(shì),其全托管免運(yùn)維的使用體驗(yàn)和按量付費(fèi)的成本優(yōu)勢(shì)使得其在云原生時(shí)代備受推崇。SAE (Serverless 應(yīng)用引擎)Job 作為首款面向任務(wù)的 Serverless PaaS 平臺(tái),提供傳統(tǒng)的用戶體驗(yàn)。當(dāng)前聚焦支持單機(jī)、廣播、并行分片模型的任務(wù),同時(shí)支持事件驅(qū)動(dòng)、并發(fā)策略和超時(shí)重試等諸多特性,提供低成本、多規(guī)格、高彈性的資源實(shí)例來(lái)滿足短時(shí)任務(wù)的執(zhí)行。
使用方式
對(duì)于使用上述所有方案的存量應(yīng)用,SAE (Serverless 應(yīng)用引擎) Job 在兼容功能體驗(yàn)的同時(shí)支持零改造無(wú)感遷移,無(wú)論用戶使用的是 Crontab,Spring Task,還是 ElasticJob, XXLJob,均可將代碼包或者鏡像直接部署到 SAE (Serverless 應(yīng)用引擎) Job中,直接升級(jí)成為 Serverless 架構(gòu), 從而即刻擁有 Serverless 所帶來(lái)的技術(shù)上的優(yōu)勢(shì),節(jié)省資源成本和運(yùn)維成本。
對(duì)于運(yùn)完即停的程序,無(wú)論是 Java,還是 Shell,Python,Go,Php 均可以直接部署到 SAE (Serverless 應(yīng)用引擎) Job 中, 從而即刻擁有白屏化管控,全托管免運(yùn)維的完備體驗(yàn)以及開(kāi)箱即用的可觀測(cè)功能。
實(shí)現(xiàn)原理
SAE (Serverless 應(yīng)用引擎)Job 底層為多租 Kubernetes,使用神龍裸金屬安全容器、VK 對(duì)接 ECI 兩種方式提供集群計(jì)算資源。用戶在 SAE(Serverless 應(yīng)用引擎)中運(yùn)行的任務(wù)會(huì)映射到 Kubernetes 中相應(yīng)的資源。其中多租能力是借助系統(tǒng)隔離、數(shù)據(jù)隔離、服務(wù)隔離和網(wǎng)絡(luò)隔離實(shí)現(xiàn)租戶間的隔離。SAE (Serverless 應(yīng)用引擎)Job 通過(guò) Event Bridge 作為事件驅(qū)動(dòng)源,在支持豐富調(diào)用方式的同時(shí)避免了 Kubernetes 內(nèi)置定時(shí)器不保證準(zhǔn)時(shí)觸發(fā)以及精度時(shí)區(qū)上的問(wèn)題。同時(shí)不斷完善 Job 控制器的企業(yè)級(jí)特性,新增自定義分片,注入配置,差異化 GC,sidecar 主動(dòng)退出,實(shí)時(shí)日志持久化,事件通知等機(jī)制。并借助 Java 字節(jié)碼增強(qiáng)技術(shù)接管任務(wù)調(diào)度,實(shí)現(xiàn)通用的 Java 目標(biāo)框架的零改造 Serverless 化。使用 KubeVela 軟件交付平臺(tái)作為任務(wù)發(fā)布和管理的載體,以任務(wù)為中心,以開(kāi)源開(kāi)放的標(biāo)準(zhǔn),通過(guò)聲明式的方式完成整個(gè)云原生交付。SAE (Serverless 應(yīng)用引擎)Job 將持續(xù)優(yōu)化 etcd 以及調(diào)度器在短時(shí)任務(wù)高并發(fā)創(chuàng)建場(chǎng)景下的效率以及實(shí)例啟動(dòng)的極致彈性能力,結(jié)合彈性資源池保證任務(wù)調(diào)度的低延遲和高可用。
方案分析
SAE (Serverless 應(yīng)用引擎)Job 解決了上述定時(shí)任務(wù)解決方案的各種痛點(diǎn),用戶無(wú)需關(guān)注任務(wù)的調(diào)度和集群資源,無(wú)需部署的額外的運(yùn)維依賴組件,也無(wú)需自建一整套監(jiān)控告警系統(tǒng),同時(shí)更重要的是無(wú)需云主機(jī) 7*24h 常駐,在低資源利用率的環(huán)境下持續(xù)消耗閑置資源。
SAE (Serverless 應(yīng)用引擎)Job 相較于傳統(tǒng)定時(shí)任務(wù)解決方案提供了三大核心價(jià)值:
- 完備全托管:提供了一站式全托管的管理界面,其任務(wù)生命周期管理、可觀測(cè)性開(kāi)箱即用,用戶可以低心智負(fù)擔(dān)、零成本地學(xué)習(xí)使用 SAE (Serverless 應(yīng)用引擎)。
- 簡(jiǎn)單免運(yùn)維:屏蔽了底層資源,用戶只需關(guān)注其核心的業(yè)務(wù)邏輯開(kāi)發(fā),無(wú)需操心集群可用性、容量、性能等方面的問(wèn)題。
- 超高性價(jià)比:采用按需使用、按量付費(fèi)的模式,只有任務(wù)執(zhí)行業(yè)務(wù)邏輯時(shí)才會(huì)拉起收費(fèi),其余時(shí)間不收取任何費(fèi)用,極大節(jié)省了資源的成本開(kāi)銷。
總結(jié)
本文對(duì)主流定時(shí)任務(wù)解決方案(Crontab, Spring Task, ElasticJob, XXLJob, Serverless Job)的目標(biāo)定位、使用方式、實(shí)現(xiàn)原理進(jìn)行了闡述,同時(shí)就企業(yè)密切關(guān)注的功能體驗(yàn),性能成本方面的問(wèn)題進(jìn)行橫評(píng)分析。最后期望大家選用 Serverless Job,感受其對(duì)傳統(tǒng)任務(wù)所帶來(lái)的新變革。
以上就是java開(kāi)發(fā)主流定時(shí)任務(wù)解決方案全橫評(píng)詳解的詳細(xì)內(nèi)容,更多關(guān)于java 主流定時(shí)任務(wù)解決方案的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot中l(wèi)ogback日志保存到mongoDB的方法
這篇文章主要介紹了SpringBoot中l(wèi)ogback日志保存到mongoDB的方法,2017-11-11SpringBoot如何配置獲取request中body的json格式參數(shù)
這篇文章主要介紹了SpringBoot如何配置獲取request中body的json格式參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06SpringBoot文件上傳功能的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot文件上傳功能的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08SpringCloud Feign遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解
Feign是Netflix公司開(kāi)發(fā)的一個(gè)聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進(jìn)行微服務(wù)開(kāi)發(fā)非?;A(chǔ)的組件,在使用的過(guò)程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似2022-11-11bool當(dāng)成函數(shù)參數(shù)錯(cuò)誤理解
經(jīng)常會(huì)在函數(shù)的參數(shù)里使用bool參數(shù),這會(huì)大大地降低代碼的可讀性2012-11-11詳解Java數(shù)組擴(kuò)容縮容與拷貝的實(shí)現(xiàn)和原理
這篇文章主要帶大家學(xué)習(xí)數(shù)組的擴(kuò)容、縮容及拷貝,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05Springboot整合Dubbo教程之項(xiàng)目創(chuàng)建和環(huán)境搭建
本篇文章主要介紹了Springboot整合Dubbo教程之項(xiàng)目創(chuàng)建和環(huán)境搭建,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12