欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot默認(rèn)配置的具體使用

 更新時(shí)間:2025年08月27日 10:43:36   作者:一只叫煤球的貓  
本文主要介紹了SpringBoot默認(rèn)配置的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

引言

彼時(shí) SpringBoot 初興,萬(wàn)象更新,號(hào)稱“開箱即用”“約定優(yōu)于配置”,一時(shí)間風(fēng)靡四方。

開發(fā)者趨之若鶩,紛紛稱快,仿佛自此架構(gòu)之重可卸、配置之繁可省,一行 main() 即可氣定神閑、縱橫沙場(chǎng)。

然則時(shí)光久遠(yuǎn),方知此言非虛,卻也未盡其真。所謂默認(rèn),不過(guò)是你未曾開口,框架自作主張。表面無(wú)礙,實(shí)則步步殺機(jī),線上事故十有八九,皆因“未曾配置”的“默認(rèn)”。

回首往昔,實(shí)堪自嘲。曾自詡熟稔底層、精通原理,然于這些藏于陰影處的默認(rèn)設(shè)定,竟茫然不覺(jué)。故障一起,倉(cāng)皇失措,耗時(shí)良久,方才發(fā)現(xiàn),不過(guò)是框架做了一個(gè)并不適合的決定。

是以今日提筆,將過(guò)往種種記錄于此,只盼后來(lái)者少走彎路。

正文

Tomcat連接池

SpringBoot默認(rèn)使用Tomcat作為Web容器,但默認(rèn)的連接池配置在高并發(fā)場(chǎng)景下會(huì)成為瓶頸。

默認(rèn)配置下,Tomcat的最大連接數(shù)只有200,最大線程數(shù)也只有200。這意味著當(dāng)并發(fā)請(qǐng)求超過(guò)200時(shí),后續(xù)請(qǐng)求就會(huì)排隊(duì)等待。在生產(chǎn)環(huán)境中,這個(gè)配置明顯不夠用。

server:
  tomcat:
    max-connections: 10000  # 最大連接數(shù)
    threads:
      max: 800              # 最大工作線程數(shù)
      min-spare: 100        # 最小空閑線程數(shù)
    accept-count: 100       # 等待隊(duì)列長(zhǎng)度
    connection-timeout: 20000

更坑的是,SpringBoot的默認(rèn)超時(shí)時(shí)間是無(wú)限長(zhǎng)。這會(huì)導(dǎo)致連接一直占用,直到客戶端主動(dòng)斷開。

在網(wǎng)絡(luò)不穩(wěn)定的環(huán)境下,大量連接會(huì)一直掛著不釋放,最終耗盡服務(wù)器資源。

數(shù)據(jù)庫(kù)連接池

SpringBoot默認(rèn)使用HikariCP作為數(shù)據(jù)庫(kù)連接池,但默認(rèn)的連接池配置在生產(chǎn)環(huán)境下會(huì)成為瓶頸。默認(rèn)最大連接數(shù)只有10個(gè),對(duì)于稍微復(fù)雜一點(diǎn)的應(yīng)用來(lái)說(shuō)根本不夠用。

spring:
  datasource:
    hikari:
      maximum-pool-size: 50
      minimum-idle: 10
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      leak-detection-threshold: 60000

特別要注意leak-detection-threshold這個(gè)配置。默認(rèn)情況下這個(gè)檢測(cè)是關(guān)閉的,如果代碼中存在連接泄漏問(wèn)題,根本發(fā)現(xiàn)不了。

開啟后,HikariCP會(huì)監(jiān)控連接的使用時(shí)間,超過(guò)閾值就會(huì)打印警告日志。

JPA懶加載

SpringBoot集成JPA時(shí),默認(rèn)開啟了懶加載。這個(gè)設(shè)計(jì)初衷是好的,但在實(shí)際使用中經(jīng)常會(huì)導(dǎo)致N+1查詢問(wèn)題。

@Entity
public class User {
    @Id
    private Long id;
    
    @OneToMany(fetch = FetchType.LAZY)  // 默認(rèn)就是LAZY
    private List<Order> orders;
}

當(dāng)查詢用戶列表時(shí),每訪問(wèn)一次orders屬性,就會(huì)觸發(fā)一次數(shù)據(jù)庫(kù)查詢。

如果有100個(gè)用戶,就會(huì)執(zhí)行101次SQL。

這種情況下,要么使用@EntityGraph指定加載策略,要么在Repository中使用JOIN FETCH。

@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders();

Jackson時(shí)區(qū)序列化

SpringBoot默認(rèn)使用Jackson處理JSON序列化,但時(shí)區(qū)處理經(jīng)常出問(wèn)題。

默認(rèn)情況下,Jackson會(huì)使用系統(tǒng)時(shí)區(qū),這在分布式部署時(shí)會(huì)導(dǎo)致不一致的問(wèn)題。

spring:
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
    serialization:
      write-dates-as-timestamps: false

更要命的是,如果你的應(yīng)用部署在不同時(shí)區(qū)的服務(wù)器上,同樣的時(shí)間可能會(huì)被序列化成不同的值。

這個(gè)問(wèn)題在國(guó)際化應(yīng)用中特別突出。

日志配置

SpringBoot默認(rèn)使用Logback,但默認(rèn)配置下沒(méi)有對(duì)日志文件進(jìn)行滾動(dòng)和清理。

長(zhǎng)時(shí)間運(yùn)行的應(yīng)用會(huì)產(chǎn)生巨大的日志文件,最終占滿磁盤空間。

logging:
  file:
    name: app.log
  logback:
    rollingpolicy:
      max-file-size: 100MB
      max-history: 30
      total-size-cap: 3GB

另外,默認(rèn)的日志級(jí)別是INFO,在生產(chǎn)環(huán)境中會(huì)產(chǎn)生大量不必要的日志。

合理設(shè)置日志級(jí)別可以顯著提升性能。

緩存配置

SpringBoot的@Cacheable注解默認(rèn)使用ConcurrentHashMap作為緩存實(shí)現(xiàn),但這個(gè)實(shí)現(xiàn)沒(méi)有過(guò)期機(jī)制,也沒(méi)有大小限制。在高并發(fā)場(chǎng)景下,緩存會(huì)無(wú)限增長(zhǎng),最終導(dǎo)致內(nèi)存溢出。

spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=10000,expireAfterWrite=600s

可以考慮使用Caffeine替代默認(rèn)實(shí)現(xiàn),可以提供更好的性能和內(nèi)存管理能力。

監(jiān)控端點(diǎn)

SpringBoot Actuator默認(rèn)暴露了很多監(jiān)控端點(diǎn),包括健康檢查、配置信息、環(huán)境變量等。

這些信息在開發(fā)環(huán)境中很有用,但在生產(chǎn)環(huán)境中可能泄漏敏感信息。

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: when-authorized

只暴露必要的端點(diǎn),并且配置適當(dāng)?shù)陌踩呗?,避免信息泄漏?/p>

文件上傳大小限制

SpringBoot默認(rèn)的文件上傳限制非常小,單個(gè)文件只能上傳1MB,整個(gè)請(qǐng)求大小限制10MB。

在實(shí)際業(yè)務(wù)中,這個(gè)限制經(jīng)常不夠用,用戶上傳稍大一點(diǎn)的文件就會(huì)報(bào)錯(cuò)。

這個(gè)屬于是比較常見的問(wèn)題,因?yàn)殚_發(fā)環(huán)境測(cè)試時(shí)通常用小文件,一切正常。等到用戶上傳幾MB的PDF文檔或者高清圖片時(shí),系統(tǒng)就開始報(bào) MaxUploadSizeExceededException 異常。

這個(gè)異常往往還發(fā)生在文件傳輸完成之后,用戶等了半天上傳完畢,結(jié)果被告知文件過(guò)大,體驗(yàn)極差。

spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
      file-size-threshold: 2KB
      location: /tmp
      resolve-lazily: false

file-size-threshold 這個(gè)參數(shù)也很重要,它決定了多大的文件會(huì)直接寫入內(nèi)存。如果設(shè)置過(guò)大,大量并發(fā)上傳會(huì)占用過(guò)多內(nèi)存;設(shè)置過(guò)小,小文件也要寫磁盤,影響性能。一般設(shè)置為幾KB比較合適。

異步線程池配置

使用@Async注解時(shí),SpringBoot默認(rèn)使用SimpleAsyncTaskExecutor,這個(gè)執(zhí)行器每次都會(huì)創(chuàng)建新線程,沒(méi)有線程池復(fù)用機(jī)制。高并發(fā)情況下會(huì)創(chuàng)建大量線程,最終導(dǎo)致系統(tǒng)資源耗盡。

這個(gè)問(wèn)題在開發(fā)階段很難發(fā)現(xiàn),因?yàn)楫惒饺蝿?wù)通常不多。但在生產(chǎn)環(huán)境,如果有大量異步任務(wù)執(zhí)行,比如發(fā)送短信、推送、記錄日志等,系統(tǒng)會(huì)不斷創(chuàng)建新線程。每個(gè)線程默認(rèn)占用1MB的??臻g,創(chuàng)建幾千個(gè)線程就是幾GB內(nèi)存。

更嚴(yán)重的是線程切換的開銷,CPU大部分時(shí)間都在做上下文切換,真正的業(yè)務(wù)邏輯反而執(zhí)行很慢。

spring:
  task:
    execution:
      pool:
        core-size: 8
        max-size: 16
        queue-capacity: 100
        keep-alive: 60s
      thread-name-prefix: async-task-
    scheduling:
      pool:
        size: 4
      thread-name-prefix: scheduling-

線程池大小的設(shè)置也有講究。

如果是CPU密集型任務(wù),線程數(shù)設(shè)置為CPU核心數(shù)就夠了;如果是IO密集型任務(wù),可以設(shè)置為CPU核心數(shù)的2-3倍。

queue-capacity設(shè)置了任務(wù)隊(duì)列長(zhǎng)度,當(dāng)線程池滿了之后,新任務(wù)會(huì)放到隊(duì)列里等待執(zhí)行。

靜態(tài)資源緩存策略

SpringBoot默認(rèn)不為靜態(tài)資源設(shè)置HTTP緩存頭,這意味著瀏覽器每次都會(huì)重新請(qǐng)求CSS、JS、圖片等靜態(tài)文件,嚴(yán)重影響頁(yè)面加載性能。

用戶每次訪問(wèn)頁(yè)面,瀏覽器都要重新下載所有靜態(tài)資源,即使這些文件根本沒(méi)有變化。對(duì)于資源較多的單頁(yè)應(yīng)用來(lái)說(shuō),這個(gè)問(wèn)題特別明顯。用戶看到的就是頁(yè)面加載慢,特別是網(wǎng)絡(luò)條件不好的時(shí)候,體驗(yàn)很差。

spring:
  web:
    resources:
      cache:
        cachecontrol:
          max-age: 365d
          cache-public: true
      chain:
        strategy:
          content:
            enabled: true
            paths: /**
        cache: true
      static-locations: classpath:/static/

開啟內(nèi)容版本化策略后,SpringBoot會(huì)根據(jù)文件內(nèi)容生成MD5哈希值作為版本號(hào),文件名變成style-abc123.css這樣的格式。當(dāng)文件內(nèi)容發(fā)生變化時(shí),哈希值也會(huì)變化,瀏覽器會(huì)認(rèn)為這是新文件重新下載;如果文件沒(méi)變化,瀏覽器就直接使用緩存,有效提升頁(yè)面加載速度。

數(shù)據(jù)庫(kù)事務(wù)超時(shí)

@Transactional注解默認(rèn)沒(méi)有設(shè)置超時(shí)時(shí)間,長(zhǎng)時(shí)間運(yùn)行的事務(wù)會(huì)一直持有數(shù)據(jù)庫(kù)鎖,影響其他操作的執(zhí)行。特別是在批量數(shù)據(jù)處理時(shí),很容易出現(xiàn)鎖表問(wèn)題。

這個(gè)問(wèn)題在并發(fā)量不高的時(shí)候不明顯,但隨著業(yè)務(wù)增長(zhǎng),長(zhǎng)事務(wù)的危害就暴露出來(lái)了。

比如一個(gè)數(shù)據(jù)導(dǎo)入任務(wù)需要處理幾萬(wàn)條記錄,如果放在一個(gè)事務(wù)里,可能要運(yùn)行幾分鐘甚至更長(zhǎng)時(shí)間。在這期間,相關(guān)的表都被鎖住,其他用戶的操作只能等待,系統(tǒng)響應(yīng)變得很慢。

@Transactional(timeout = 30, rollbackFor = Exception.class)
public void batchProcess(List<Data> dataList) {
    // 分批處理,避免長(zhǎng)事務(wù)
    int batchSize = 100;
    for (int i = 0; i < dataList.size(); i += batchSize) {
        List<Data> batch = dataList.subList(i, 
            Math.min(i + batchSize, dataList.size()));
        processBatch(batch);
    }
}

對(duì)于大批量數(shù)據(jù)處理,建議分成多個(gè)小事務(wù),每個(gè)事務(wù)處理少量數(shù)據(jù)。這樣即使某個(gè)小事務(wù)失敗,也不會(huì)影響整體進(jìn)度,而且可以及時(shí)釋放數(shù)據(jù)庫(kù)鎖,提高系統(tǒng)并發(fā)性能。

同時(shí)再加上rollbackFor = Exception.class確保所有異常都會(huì)觸發(fā)回滾,避免數(shù)據(jù)不一致。

寫在最后

Spring Boot 的“約定優(yōu)于配置”確實(shí)省心,但省的是開發(fā)者的心,不是系統(tǒng)的責(zé)任。每一項(xiàng)默認(rèn)配置背后,其實(shí)都藏著設(shè)計(jì)者的假設(shè)和權(quán)衡,而這些假設(shè),在我們的業(yè)務(wù)場(chǎng)景中也許未必成立。

這些坑我?guī)缀醵疾冗^(guò),有些甚至反復(fù)踩了好幾次。

愿你讀到這里,能少走幾步彎路,可不能拿生產(chǎn)事故去交學(xué)費(fèi)。

提前優(yōu)化配置,是對(duì)系統(tǒng)負(fù)責(zé),也是對(duì)自己負(fù)責(zé)。

到此這篇關(guān)于SpringBoot默認(rèn)配置的具體使用(遲早踩坑)的文章就介紹到這了,更多相關(guān)SpringBoot默認(rèn)配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Java實(shí)現(xiàn)動(dòng)態(tài)生成MySQL數(shù)據(jù)庫(kù)

    使用Java實(shí)現(xiàn)動(dòng)態(tài)生成MySQL數(shù)據(jù)庫(kù)

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)動(dòng)態(tài)生成MySQL數(shù)據(jù)庫(kù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • IntelliJ?IDEA軟件內(nèi)如何實(shí)現(xiàn)更新到最新版本

    IntelliJ?IDEA軟件內(nèi)如何實(shí)現(xiàn)更新到最新版本

    文章介紹了如何在IntelliJIDEA中更新到最新版本以及如何回到之前忽略的版本,解決辦法是通過(guò)選擇"IgnoreThisUpdate"來(lái)跳過(guò)舊版本,重復(fù)操作即可更新到最新版本
    2024-12-12
  • java理論基礎(chǔ)Stream性能論證測(cè)試示例

    java理論基礎(chǔ)Stream性能論證測(cè)試示例

    這篇文章主要為大家介紹了java理論基礎(chǔ)Stream性能論證的測(cè)試示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • JAVAlogback日志管理詳解

    JAVAlogback日志管理詳解

    本篇文章主要介紹了在SpringBoot中使用Logback管理記錄日志,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-09-09
  • Java中的包(Package)與導(dǎo)入(Import)示例詳解

    Java中的包(Package)與導(dǎo)入(Import)示例詳解

    這篇文章主要詳細(xì)介紹了Java中的包(Package)和導(dǎo)入(Import)概念,包括包的定義、作用、JDK中主要的包、導(dǎo)入的目的與用法、特殊情況的導(dǎo)入、靜態(tài)導(dǎo)入、包的訪問(wèn)權(quán)限和命名規(guī)范,文章通過(guò)豐富的解釋和代碼示例,幫助讀者深入理解這些概念的實(shí)際應(yīng)用,需要的朋友可以參考下
    2024-11-11
  • springboot如何使用assembly打包項(xiàng)目和啟動(dòng)腳本

    springboot如何使用assembly打包項(xiàng)目和啟動(dòng)腳本

    這篇文章主要介紹了springboot如何使用assembly打包項(xiàng)目和啟動(dòng)腳本問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java 實(shí)戰(zhàn)項(xiàng)目之疫情防控管理系統(tǒng)詳解

    Java 實(shí)戰(zhàn)項(xiàng)目之疫情防控管理系統(tǒng)詳解

    讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)疫情防控管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • SpringMVC 參數(shù)綁定之視圖傳參到控制器的實(shí)現(xiàn)代碼

    SpringMVC 參數(shù)綁定之視圖傳參到控制器的實(shí)現(xiàn)代碼

    這篇文章主要介紹了SpringMVC 參數(shù)綁定之視圖傳參到控制器的相關(guān)知識(shí),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • SpringBoot集成E-mail發(fā)送各種類型郵件

    SpringBoot集成E-mail發(fā)送各種類型郵件

    這篇文章主要為大家詳細(xì)介紹了SpringBoot集成E-mail發(fā)送各種類型郵件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • JAVA基礎(chǔ)-GUI

    JAVA基礎(chǔ)-GUI

    這篇文章主要介紹了JAVA中關(guān)于GUI的相關(guān)知識(shí),文中代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06

最新評(píng)論