整合Atomikos、Quartz、Postgresql的踩坑日記

王子發表於2021-04-27

前言

由於業務需要,在單體Spring Boot專案中需要引入分散式事務,來保證單體應用連線的多個資料來源的事務統一。

而說到分散式事務,小夥伴們肯定會想到阿里的Seata,阿里Seata強大的AT模式確實是解決分散式事務的一劑良藥,

但是熟悉Seata的小夥伴肯定知道,使用Seata需要單獨搭建Seata服務端來支援分散式事務,而對於一個單體應用專案有必要專門搭建這套服務端嗎?

這是一個值得考慮的問題。王子認為技術選型的一個標準就是,用盡可能簡單的方式解決複雜的問題。

於是,Atomikos出現了。至於什麼是Atomikos這裡就不介紹了,網上資料一大堆。本文主要是介紹引入Atomikos後出現的一些問題和解決方案。

引入Atomikos後的第一個坑

好了,下面我們進入正題,看看王子是如何引入Atomikos的。

說明:以下內容不是引入Atomikos的所有工作,王子只是做了個簡單介紹,如果需要完整引入還需要參考其他文章。

要使用Atomikos當然要先在Maven中引入它的依賴了,它的依賴如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>

 

這裡我們省略一些必要的配置內容,

在配置資料來源的過程中一定會有類似下邊這部分的程式碼,用來配置Atomikos:

        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        ds.setUniqueResourceName(dataSourceName);
        ds.setMinPoolSize(5);
        ds.setMaxPoolSize(20);
        ds.setBorrowConnectionTimeout(60);
        ds.setXaProperties(prop);

第一個坑來了,在配置這部分內容中,王子開始時是沒有配置下邊這部分內容的。

        ds.setMinPoolSize(5);
        ds.setMaxPoolSize(20);
        ds.setBorrowConnectionTimeout(60);

這個時候,執行程式一切正常,包括它的分散式事務,王子也已經測試通過了。

但是,當執行應用中Quartz定時任務的時候,悲劇發生了,控制檯直接報如下異常:

[ERROR][-- ::,][org.hibernate.engine.jdbc.spi.SqlExceptionHelper]Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
[ERROR][-- ::,][org.apache.struts2.dispatcher.Dispatcher]Exception occurred during processing request: Could not open connection

現在對於這個第一個坑的解決方案相信大家已經清楚了,就是要配置剛才我們提到的那三行內容。

第二個坑

現在我們成功的解決了第一個坑,重啟程式再次測試Quartz定時任務,看到應用中那還是一直在轉的圈圈(頭痛)。

經過對報錯日誌的分析之後,發現了一行有用的資訊,如下:

Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled
  Suggerimento: Set max_prepared_transactions to a nonzero value.

看到這裡其實就很明顯了,翻譯過來就是給max_prepared_transactions這個引數設定一個非0的值。

解決方案就是找到Postgresql資料庫的postgresql.conf檔案,修改這個值即可。

max_prepared_transactions預設是0,我們把它改成與max_connections一樣大就可以了。

總結

本文主要是記錄一下日常工作中踩到的坑,防止再犯同樣的問題。

對於第一個坑,屬於Atomikos的配置問題,小夥伴們可以做一個瞭解。

對於第二個坑,王子這裡使用的是Postgresql資料庫,所以導致了這個問提,建議如果使用Postgre資料庫都開啟一下這個引數,防止後患。

最後王子說明一下,Atomikos只適用於類似本文中的這種小規模系統,它的底層是XA的2PC方案,會對資料庫資源有一定的鎖定過程,所以效能不是很高。

所以,對於要考慮高併發、高效能的系統,分散式事務框架還是要優先選擇Seata。

 

往期文章推薦:

JVM專欄

訊息中介軟體專欄

併發程式設計專欄

 

相關文章