SpringBoot學習日記 Day6:解鎖微服務與高效任務處理

一、開篇:從單體到微服務的思維轉變

剛開始接觸微服務時,我總習慣把所有功能寫在一個項目里。直到項目越來越臃腫,每次修改都要全量部署,才意識到微服務架構的價值。今天我們就來探索SpringBoot在微服務場景下的強大能力!

二、多模塊項目:微服務的雛形

1. 創建父工程(pom.xml關鍵配置)

<packaging>pom</packaging>
<modules><module>weather-service</module><module>user-service</module><module>common</module>
</modules><!-- 統一依賴管理 -->
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.7.3</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

2. 子模塊示例:common模塊

common/
├── src/
│ ? ├── main/
│ ? │ ? ├── java/com/example/common/
│ ? │ ? │ ? ├── exception/ ?# 公共異常類
│ ? │ ? │ ? ├── utils/ ? ? ?# 工具類
│ ? │ ? │ ? └── config/ ? ? # 公共配置
│ ? ├── resources/
├── pom.xml

子模塊pom.xml特點:

<parent><groupId>com.example</groupId><artifactId>parent-project</artifactId><version>1.0.0</version>
</parent><dependencies><!-- 模塊間依賴 --><dependency><groupId>com.example</groupId><artifactId>common</artifactId><version>${project.version}</version></dependency>
</dependencies>

三、REST客戶端:服務間通信的橋梁

1. RestTemplate基礎用法

@Service
public class WeatherService {private final RestTemplate restTemplate;// 推薦使用構造器注入public WeatherService(RestTemplateBuilder builder) {this.restTemplate = builder.rootUri("https://api.weather.com").setConnectTimeout(Duration.ofSeconds(3)).build();}public WeatherData getWeather(String city) {String url = "/v1/current?city={city}";try {return restTemplate.getForObject(url, WeatherData.class, city);} catch (RestClientException e) {throw new BusinessException("天氣服務調用失敗", e);}}
}

2. WebClient響應式調用

@Service
public class ReactiveWeatherService {private final WebClient webClient;public ReactiveWeatherService(WebClient.Builder builder) {this.webClient = builder.baseUrl("https://api.weather.com").build();}public Mono<WeatherData> getWeatherAsync(String city) {return webClient.get().uri("/v1/current?city={city}", city).retrieve().bodyToMono(WeatherData.class).timeout(Duration.ofSeconds(2)).onErrorResume(e -> Mono.error(new BusinessException("天氣服務異常")));}
}

3. 重試機制增強健壯性

@Bean
public RestTemplate restTemplate() {return new RestTemplateBuilder().interceptors(new RetryableRestTemplateInterceptor()).build();
}// 自定義攔截器
public class RetryableRestTemplateInterceptor implements ClientHttpRequestInterceptor {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body,?ClientHttpRequestExecution execution) throws IOException {int retryCount = 0;ClientHttpResponse response;while (retryCount < 3) {try {response = execution.execute(request, body);if (response.getStatusCode().is5xxServerError()) {throw new IOException("Server error");}return response;} catch (IOException e) {retryCount++;if (retryCount >= 3) {throw e;}Thread.sleep(1000 * retryCount);}}throw new IOException("Request failed after retries");}
}

四、定時任務:后臺執行的瑞士軍刀

1. 基礎定時任務

@Slf4j
@Component
@EnableScheduling
public class WeatherDataSyncTask {// 每30分鐘執行一次@Scheduled(fixedRate = 30 * 60 * 1000)public void syncWeatherData() {log.info("開始同步天氣數據...");// 業務邏輯}// 每天凌晨1點執行@Scheduled(cron = "0 0 1 * * ?")public void clearOldData() {log.info("清理過期數據...");}
}

2. 動態定時任務(數據庫配置觸發時間)

@Service
public class DynamicTaskService {@Autowiredprivate ThreadPoolTaskScheduler taskScheduler;private ScheduledFuture<?> future;public void startTask(String taskId, Runnable task, String cron) {stopTask(taskId); // 先停止已有任務future = taskScheduler.schedule(task, new CronTrigger(cron));}public void stopTask(String taskId) {if (future != null) {future.cancel(true);}}
}// 配置線程池
@Configuration
public class TaskConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);scheduler.setThreadNamePrefix("task-");return scheduler;}
}

五、異步處理:釋放系統吞吐潛力

1. 快速啟用異步

@SpringBootApplication
@EnableAsync
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}// 自定義線程池
@Configuration
public class AsyncConfig {@Bean(name = "asyncExecutor")public Executor asyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix("Async-");executor.initialize();return executor;}
}

2. 異步方法實踐

@Service
public class LogService {@Async("asyncExecutor")public CompletableFuture<Void> saveLogAsync(Log log) {// 模擬耗時操作Thread.sleep(1000);logRepository.save(log);return CompletableFuture.completedFuture(null);}@Asyncpublic void processInBackground() {// 無返回值的異步方法}
}// 調用示例
@RestController
public class LogController {@PostMapping("/logs")public Result<Void> addLog(@RequestBody Log log) {logService.saveLogAsync(log); // 異步執行return Result.success();}
}

六、實戰項目:天氣服務系統

1. 系統架構

weather-service (主模塊)
├── 調用外部天氣API
├── 定時緩存數據
├── 提供REST接口
│
common (公共模塊)
├── 異常處理
├── 工具類

2. 核心代碼片段

天氣數據緩存:

@Cacheable(value = "weather", key = "#city")
public WeatherData getCachedWeather(String city) {return externalApiClient.getWeather(city);
}@Scheduled(fixedRate = 30 * 60 * 1000)
@CacheEvict(value = "weather", allEntries = true)
public void refreshCache() {log.info("清空天氣緩存");
}

異步日志記錄:

@Async
public void asyncAddAccessLog(HttpServletRequest request) {AccessLog log = new AccessLog();log.setPath(request.getRequestURI());log.setIp(request.getRemoteAddr());log.setCreateTime(LocalDateTime.now());logRepository.save(log);
}

七、避坑指南

1. 跨模塊掃描問題:
- 主類添加@ComponentScan("com.example")
- 確保包結構有共同父包

2. RestTemplate單例問題:
- 推薦通過RestTemplateBuilder創建
- 為不同服務創建不同的RestTemplate實例

3. 定時任務阻塞:
- 默認使用單線程,長時間任務會影響其他任務
- 務必配置線程池

4. 異步失效場景:
- 同事務問題:自調用或private方法無效
- 異常處理:主線程無法捕獲異步方法異常

八、明日計劃

1. 學習SpringBoot Actuator監控
2. 集成Prometheus+Grafana
3. 實現健康檢查與指標暴露
4. 探索SpringBoot Admin

思考題:在微服務架構下,如果天氣服務和用戶服務需要頻繁通信,RestTemplate和WebClient哪種方式更適合?為什么?歡迎在評論區分享你的見解!

如果覺得這篇學習日記有幫助,請點贊收藏支持~完整天氣服務示例代碼可通過私信獲取。在實際開發中遇到異步或定時任務問題也歡迎留言討論!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92597.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92597.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92597.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機械學習--DBSCAN 算法(附實戰案例)

DBSCAN 算法詳解DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff0c;帶噪聲的基于密度的空間聚類應用&#xff09;是一種經典的密度聚類算法&#xff0c;由 Martin Ester 等人于 1996 年提出。與 K-means 等基于距離的聚類算法不同&am…

【昇騰】基于RK3588 arm架構Ubuntu22.04系統上適配Atlas 200I A2加速模塊安裝EP模式下的驅動固件包_20250808

一、背景 1.1 主要的硬件是&#xff1a;1.2 主要的軟件是&#xff1a; RK3588跑操作系統Atlas 200I A2加速模塊作為EP模式關鍵參數版本說明CPU架構aarch64OS版本Ubuntu 22.04.5 LTSkernel版本5.10.198 二、適配 準備固件run包文件&#xff1a;Ascend-hdk-310b-npu-firmware_7.…

如何在 VS Code 中進行 `cherry-pick`

cherry-pick 是 Git 的一個功能&#xff0c;允許你選擇某個 commit 并將其應用到當前分支&#xff0c;而無需合并整個分支。在 VS Code 中&#xff0c;你可以通過 內置的 Git 功能 或 終端 來完成 cherry-pick。方法 1&#xff1a;使用 VS Code 的 Git 圖形界面&#xff08;GUI…

STM32CubeMX(十三)FatFs文件系統(SPI驅動W25Qxx)

目錄 一、知識點 1. 什么是Fatfs文件系統? 2. Fatfs操作系統控制流程 二、實戰操作 1.CubeMX配置 2. 配置串口以及SPI 3. 修改功能映射接口 4. 添加測試代碼 5. 實驗現象 在完成本章之前需要完成一些基礎配置,詳情查看下面的文章。 STM32CubeMX(二)新建工…

【前端后端部署】將前后端項目部署到云服務器

更多筆記在這里? 全棧之路&#xff1a; https://gitee.com/oldbe/notes 【跳轉到】 覺得有用請點個 star &#xff0c;非常感謝&#xff01; 現在AI太強大&#xff0c;開發個人產品的門檻和成本太低了&#xff0c;只要你有好的想法都可以很快速的開發一款產品 1.…

vue如何監聽localstorage

在Vue中監聽localStorage的變化可以通過幾種方式實現&#xff0c;但需要注意的是&#xff0c;localStorage本身不提供原生的事件監聽機制&#xff0c;如DOM元素的MutationObserver。不過&#xff0c;你可以通過一些間接的方法來監聽localStorage的變化。方法1&#xff1a;使用w…

灰狼算法+四模型對比!GWO-CNN-LSTM-Attention系列四模型多變量時序預測

摘要&#xff1a;聚劃算&#xff01;大對比&#xff01;灰狼算法四模型對比&#xff01;GWO-CNN-LSTM-Attention系列四模型多變量時序預測&#xff0c;該代碼特別適合需要橫向對比不同深度學習模型性能的時序預測場景&#xff0c;研究者可通過參數快速適配不同預測需求&#xf…

冒泡排序實現以及優化

一&#xff0c;冒泡排序說明冒泡排序是從第一個元素開始和后面一個元素進行判斷是否滿足左小右大&#xff0c;如果不滿足就交換位置&#xff0c;再拿第二個和第三個進行上述操作一直到第n-1和第n個。經過上述的一輪操作就可以把第一個最大值放到最右邊&#xff0c;在進行n輪上述…

水下管道巡檢機器人cad【10張】三維圖+設計說明書

摘 要 水下管道是水下油氣管道的生命線&#xff0c;水下管道巡檢機器人可以替代人工完成水下油氣管道狀態的實時監測和數據反饋&#xff0c;有助于工作人員對水下油氣管道的運行情況實時掌握。 本文完成了水下管道巡檢機器人的總體設計&#xff0c;采用三維設計軟件Solidwor…

SQL(結構化查詢語言)的四大核心分類

這張圖展示了 SQL&#xff08;結構化查詢語言&#xff09;的四大核心分類&#xff0c;分別對應不同的數據庫操作場景。以下是逐類解析&#xff1a;1. 數據操作語言&#xff08;DML&#xff1a;Data Manipulation Language&#xff09;作用&#xff1a;用于操作數據庫中的數據&a…

AI(1)-神經網絡(正向傳播與反向傳播)

&#x1f34b;&#x1f34b;AI學習&#x1f34b;&#x1f34b;&#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 用力所能及&#xff0c;改變世界。 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4dd;支持一下博主…

嵌入式Linux學習 - 數據結構6

五、哈希表1. 哈希算法將數據通過哈希算法映射成一個鍵值&#xff0c;存取都在同一位置實現數據的高效存儲和查找將時間復雜度盡可能降低至O(1)2. 哈希碰撞多個數據通過哈希算法得到的鍵值相同&#xff0c;稱為產生哈希碰撞3. 哈希表構建哈希表存放0-100之間的數據將0 - 100之間…

GitHub 趨勢日報 (2025年08月07日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖1894nautilus_trader354stagehand315openai-cookbook263sim242ollama230prisma154v…

android 使用openimagelib OpenImage 實現點擊放大圖片,瀏覽

在 Android 中使用 OpenImageLib(假設這是一個開源圖片加載庫,類似于 Glide 或 Picasso)實現 點擊放大圖片并瀏覽 的功能,通常需要結合 圖片查看器庫(如 PhotoView)和 圖片加載庫(如 OpenImageLib)。以下是完整的實現方案: 1. 添加依賴 (1) 添加 OpenImageLib 依賴 …

計算機視覺CS231n學習(4)

深度學習軟件 &#xff08;這一部分去看tensorflow和pytorch的筆記&#xff09; &#xff08;見專欄&#xff09;tensorflow和pytorch區別 tensorflow&#xff0c;我們先構建顯示的圖&#xff0c;然后重復運行它 pytorch&#xff0c;我們每次做前向傳播時&#xff0c;都構建一個…

【具身智能】具身智能的革命——人形機器人如何重塑人類日常生活

還在為高昂的AI開發成本發愁?這本書教你如何在個人電腦上引爆DeepSeek的澎湃算力! 2025年被譽為具身智能的元年,人形機器人技術迅猛發展,將深刻改變人類生活方式。本文從具身智能的核心概念入手,探討人形機器人的硬件架構、感知系統、運動控制和決策算法等技術基礎。結合…

Jira Service Management企業服務管理:IT、HR、法務、財務等部門如何落地現代企業服務管理理念與實踐

Jira Service Management 服務管理方法Jira Service Management 服務管理方法將開發、IT運營和業務團隊整合至一個統一平臺&#xff0c;以實現更高效的協作。任何團隊都能夠快速響應業務變化&#xff0c;為客戶和員工提供卓越體驗。Jira Service Management 提供直觀、經濟高效…

軟件開發 - danger 與 dangerous、warn 與 warning

danger 與 dangerous 1、danger詞性&#xff1a;n.含義&#xff1a;指可能造成傷害或損失的情況或事物# 例詞in 【danger】&#xff08;處于危險中&#xff09; out of 【danger】&#xff08;脫離危險&#xff09;# 例句After the surgery, the doctor said the patient was o…

為何毫米波需要采用不同的DPD方法?如何量化其值?

摘要 在5G新無線電技術標準中&#xff0c;除了sub-6 GHz頻率外&#xff0c;還利用毫米波(mmWave)頻率來提高吞吐量。毫米波頻率的使用為大幅提高數據吞吐量帶來了獨特的機會&#xff0c;同時也帶來了新的實施挑戰。本文探討sub-6 GHz和毫米波基站無線電之間的架構差異&#xff…

【數據結構入門】棧和隊列的OJ題

目錄 1. 有效的括號 分析&#xff1a; 代碼&#xff1a; 2. 用隊列實現棧 分析&#xff1a; 代碼&#xff1a; 3. 用棧實現隊列 分析&#xff1a; 代碼&#xff1a; 4. 設計循環隊列 思路&#xff1a; 代碼&#xff1a; 定義循環隊列結構體&#xff1a; 初始化結…