解決SeaTunnel 2.3.4版本寫入S3文件報錯問題

在使用Apache SeaTunnel時,我遇到了一個寫入S3文件的報錯問題。通過深入調試和分析,找到了問題所在,并提出了相應的解決方案。 file

本文將詳細介紹報錯情況、參考資料、解決思路以及后續研究方向,希望對大家有幫助!

一、詳細報錯

2024-04-12 20:44:18,647 ERROR [.c.FileSinkAggregatedCommitter] [hz.main.generic-operation.thread-43] - commit aggregatedCommitInfo error, aggregatedCommitInfo = FileAggregatedCommitInfo(transactionMap={/xugurtp/seatunnel/tmp/seatunnel/831147703474847745/476b6a6fc7/T_831147703474847745_476b6a6fc7_0_1={/xugurtp/seatunnel/tmp/seatunnel/831147703474847745/476b6a6fc7/T_831147703474847745_476b6a6fc7_0_1/NON_PARTITION/output_params_0.json=/xugurtp/seatunnel/tmp/6af80b38f3434aceb573cc65b9cd12216a/39111/output_params_0.json}}, partitionDirAndValuesMap={}) java.lang.IllegalStateException: Connection pool shut down

二、參考資料

  • HADOOP-16027:https://issues.apache.org/jira/browse/HADOOP-16027
  • CSDN Blog:https://blog.csdn.net/a18262285324/article/details/112470363
  • AWS SDK Java Issue #2337:https://github.com/aws/aws-sdk-java/issues/2337
  • Amazon SQS Java Messaging Lib Issue #96:https://github.com/awslabs/amazon-sqs-java-messaging-lib/issues/96
  • 博客園:https://www.cnblogs.com/xhy-shine/p/10772736.html

三、解決思路

1. 遠程調試

在本地IDEA中進行debug未發現報錯,但在服務器上執行時卻報錯,因此決定進行遠程debug。執行以下命令添加JVM參數:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

實際命令是:

 java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dhazelcast.client.config=/opt/module/seatunnel-2.3.4/config/hazelcast-client.yaml -Dseatunnel.config=/opt/module/seatunnel-2.3.4/config/seatunnel.yaml -Dhazelcast.config=/opt/module/seatunnel-2.3.4/config/hazelcast.yaml -Dlog4j2.configurationFile=/opt/module/seatunnel-2.3.4/config/log4j2_client.properties -Dseatunnel.logs.path=/opt/module/seatunnel-2.3.4/logs -Dseatunnel.logs.file_name=seatunnel-starter-client -Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/seatunnel/dump/zeta-client -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -cp /opt/module/seatunnel-2.3.4/lib/*:/opt/module/seatunnel-2.3.4/starter/seatunnel-starter.jar org.apache.seatunnel.core.starter.seatunnel.SeaTunnelClient -e local --config job/s3_sink.conf -cn xxx

2. 定位問題

通過調試發現問題出在hadoop-aws使用的緩存連接池對象。關鍵在于if判斷部分,如果上游傳遞了fs.s3a.impl.disable.cache=true,則不使用緩存。深入debug發現:有時hadoopConf.getSchema獲取的不是s3a而是s3n

s3和s3n / s3a的區別

  • s3:基于塊的文件系統
  • s3n:基于對象存儲的文件系統,支持高達5GB的對象
  • s3a:基于對象存儲的文件系統,支持高達5TB的對象,并具有更高的性能

在配置文件中設置的是s3a,但實際獲取到的是s3n,這顯然不合理。

3. 深入挖掘

我仔細看了一下報錯的截圖發現:

file

確實是commit期間報的錯:那么也就是說commit初始化s3conf并沒有走buildWithConfig方法,而是用的默認值,而且我根本沒找到commit里面有new s3Conf的代碼,再次debug看看誰去重新初始化了S3Conf

file

定位到這里就很頭疼了,已經涉及到引擎層而非插件層面了,涉及到classloader的使用以及反序列化操作:

file

反序列化代碼:

        logicalDag =CustomClassLoadedObject.deserializeWithCustomClassLoader(nodeEngine.getSerializationService(),classLoader,jobImmutableInformation.getLogicalDag());

很明顯可以看出,S3Conf(靜態類)被重新初始化了,導致SHEMA被重新賦值成s3n

file

因為s3conf它本身的屬性都是靜態的,而對classloader反序列化是時會重新加載靜態屬性的,所以導致shema被重新賦值為默認s3n

綜上所述

除了sourcesink階段,AggregatedCommit操作也會寫入s3File。錯誤發生在commit期間,說明初始化S3Conf時并沒有走buildWithConfig方法,而是使用了默認值。

由于S3Conf類的屬性是靜態的,反序列化時會重新加載靜態屬性,導致SCHEMA被重新賦值為默認的s3n

資料參考:https://wiki.apache.org/hadoop/AmazonS3

s3:基于Block塊的文件系統

S3 Block FileSystem(URI scheme:s3)由S3支持的基于塊的文件系統。 文件存儲為塊,就像HDFS一樣。 這樣可以有效地實現重命名。 此文件系統需要您為文件系統專用一個存儲桶 - 您不應使用包含文件的現有存儲桶,或將其他文件寫入同一存儲區。 此文件系統存儲的文件大于5GB,但不能與其他S3工具進行互操作。

s3n:基于對象存儲的文件系統

S3 Native FileSystem(URI scheme:s3n)用于在S3上讀取和寫入常規文件的本機文件系統。 這個文件系統的優點是您可以訪問使用其他工具編寫的S3上的文件。 相反,其他工具可以訪問使用Hadoop編寫的文件。 缺點是S3的文件大小限制為5GB。

s3a:基于對象存儲的文件系統

S3A(URI方案:s3a)是S3 Native,s3n fs的繼承者,S3a:系統使用Amazon的庫與S3進行交互。 這允許S3A支持較大的文件(不超過5GB的限制),更高的性能操作等等。 文件系統旨在替代S3 Native:從s3n:// URL可訪問的所有對象也應該通過替換URL模式從s3a訪問。

public class S3Conf extends HadoopConf {private static final String HDFS_S3N_IMPL = "org.apache.hadoop.fs.s3native.NativeS3FileSystem";private static final String HDFS_S3A_IMPL = "org.apache.hadoop.fs.s3a.S3AFileSystem";private static final String S3A_SCHEMA = "s3a";private static final String DEFAULT_SCHEMA = "s3n";private static String SCHEMA = DEFAULT_SCHEMA;@Overridepublic String getFsHdfsImpl() {return switchHdfsImpl();}@Overridepublic String getSchema() {return SCHEMA;}private S3Conf(String hdfsNameKey) {super(hdfsNameKey);}public static HadoopConf buildWithConfig(Config config) {HadoopConf hadoopConf = new S3Conf(config.getString(S3ConfigOptions.S3_BUCKET.key()));String bucketName = config.getString(S3ConfigOptions.S3_BUCKET.key());if (bucketName.startsWith(S3A_SCHEMA)) {SCHEMA = S3A_SCHEMA;}HashMap<String, String> s3Options = new HashMap<>();putS3SK(s3Options, config);if (CheckConfigUtil.isValidParam(config, S3ConfigOptions.S3_PROPERTIES.key())) {config.getObject(S3ConfigOptions.S3_PROPERTIES.key()).forEach((key, value) -> s3Options.put(key, String.valueOf(value.unwrapped())));}s3Options.put(S3ConfigOptions.S3A_AWS_CREDENTIALS_PROVIDER.key(),config.getString(S3ConfigOptions.S3A_AWS_CREDENTIALS_PROVIDER.key()));s3Options.put(S3ConfigOptions.FS_S3A_ENDPOINT.key(),config.getString(S3ConfigOptions.FS_S3A_ENDPOINT.key()));hadoopConf.setExtraOptions(s3Options);return hadoopConf;}public static HadoopConf buildWithReadOnlyConfig(ReadonlyConfig readonlyConfig) {Config config = readonlyConfig.toConfig();HadoopConf hadoopConf = new S3Conf(readonlyConfig.get(S3ConfigOptions.S3_BUCKET));String bucketName = readonlyConfig.get(S3ConfigOptions.S3_BUCKET);if (bucketName.startsWith(S3A_SCHEMA)) {SCHEMA = S3A_SCHEMA;}HashMap<String, String> s3Options = new HashMap<>();putS3SK(s3Options, config);if (CheckConfigUtil.isValidParam(config, S3ConfigOptions.S3_PROPERTIES.key())) {config.getObject(S3ConfigOptions.S3_PROPERTIES.key()).forEach((key, value) -> s3Options.put(key, String.valueOf(value.unwrapped())));}s3Options.put(S3ConfigOptions.S3A_AWS_CREDENTIALS_PROVIDER.key(),readonlyConfig.get(S3ConfigOptions.S3A_AWS_CREDENTIALS_PROVIDER).getProvider());s3Options.put(S3ConfigOptions.FS_S3A_ENDPOINT.key(),readonlyConfig.get(S3ConfigOptions.FS_S3A_ENDPOINT));hadoopConf.setExtraOptions(s3Options);return hadoopConf;}private String switchHdfsImpl() {switch (SCHEMA) {case S3A_SCHEMA:return HDFS_S3A_IMPL;default:return HDFS_S3N_IMPL;}}private static void putS3SK(Map<String, String> s3Options, Config config) {if (!CheckConfigUtil.isValidParam(config, S3ConfigOptions.S3_ACCESS_KEY.key())&& !CheckConfigUtil.isValidParam(config, S3ConfigOptions.S3_SECRET_KEY.key())) {return;}String accessKey = config.getString(S3ConfigOptions.S3_ACCESS_KEY.key());String secretKey = config.getString(S3ConfigOptions.S3_SECRET_KEY.key());if (S3A_SCHEMA.equals(SCHEMA)) {s3Options.put("fs.s3a.access.key", accessKey);s3Options.put("fs.s3a.secret.key", secretKey);return;}// default s3ns3Options.put("fs.s3n.awsAccessKeyId", accessKey);s3Options.put("fs.s3n.awsSecretAccessKey", secretKey);}
}

參考了反序列的知識才了解到這個情況:

當對一個包含靜態成員的類進行反序列化時,靜態成員不會恢復為之前的狀態,而是保持在其初始狀態。任何靜態變量的值都是與該類本身相關的,

4. 解決方案

  • 1.去掉stastic修飾,把有參構造換成無參構造和靜態工廠方法:

  • 2.保留stastic靜態方法,使用getSchema方法代替靜態屬性調用:

由此可見,代碼中的細節問題,即使看似微不足道,也可能引發嚴重的后果。一個簡單的靜態修飾符的誤用,不僅能導致程序行為異常,更可能導致系統穩定性和安全性的大問題。

相關的issues已提交,大家有興趣可以查看:

  • [bigfix][S3 File]:Change the [SCHEMA] attribute of the [S3CONF class] to be non-static to avoid being reassigned after deserialization by LeonYoah · Pull Request #6717 · apache/seatunnel (github.com)

  • [Bug] [S3File] [zeta-local] Error writing to S3File in version 2.3.4:: Java lang. An IllegalStateException: Connection pool shut down · Issue #6678 · apache/seatunnel (github.com)

四、有待研究

1.為什么只有local模式會報錯:

推測可能是cluster模式是分布式的,每個算子分布在不同的機器上,所以本地緩存不會被使用,類似于沒有走緩存。

2.為什么本地IDEA執行local模式卻沒問題

可能是Windows和Linux的線程調度機制不同導致的。

結論

通過這次對Apache SeaTunnel S3 File寫入報錯問題的分析與解決,希望這些經驗能幫助到遇到類似問題的開發者,同時也提醒大家在處理分布式系統時注意細節問題,以免引發不必要的故障。

本文由 白鯨開源科技 提供發布支持!

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

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

相關文章

代碼隨想錄算法訓練營第二天|【數組】977.有序數組的平方

題目 給你一個按 非遞減順序 排序的整數數組 nums&#xff0c;返回 每個數字的平方 組成的新數組&#xff0c;要求也按 非遞減順序 排序。 示例 1&#xff1a; 輸入&#xff1a;nums [-4,-1,0,3,10] 輸出&#xff1a;[0,1,9,16,100] 解釋&#xff1a;平方后&#xff0c;數組…

修改頭文件版本需要修改的文件

以修改ui的頭文件版本為例&#xff0c;還需要同時更新 PJ10PC20240120041_c928\components\master-t5\hikauto\module\app\include PJ10PC20240120041_c928\components\master-t5\hikauto\module\app\include\dsp PJ10PC20240120041_c928\components\master-t5\hikauto\incl…

C# Halcon目標檢測算法

在Halcon中進行目標檢測可以使用傳統的計算機視覺方法&#xff0c;也可以使用深度學習的方法。Halcon提供了豐富的函數庫來處理這些任務&#xff0c;而在C#中使用Halcon&#xff0c;你需要通過Halcon .NET接口。 以下是使用Halcon進行目標檢測的一般步驟&#xff0c;這里我將給…

DDL:針對于數據庫、數據表、數據字段的操作

數據庫的操作 # 查詢所有數據 SHOW DATABASE; #創建數據庫 CREATE DATABASE 2404javaee; #刪除數據庫 DROP DATABASE 2404javaee; 數據表的操作 #創建表 CREATE TABLE s_student( name VARCHAR(64), s_sex VARCHAR(32), age INT(3), salary FLOAT(8,2), c_course VARC…

Windows 的 MFC開發的使用示例——講得挺好的

【Visual Studio 2019】創建 MFC 桌面程序 ( 安裝 MFC 開發組件 | 創建 MFC 應用 | MFC 應用窗口編輯 | 為按鈕添加點擊事件 | 修改按鈕文字 | 打開應用 )-騰訊云開發者社區-騰訊云 (tencent.com)

【算法】(C語言):堆排序

堆&#xff08;二叉樹的應用&#xff09;&#xff1a; 完全二叉樹。最大堆&#xff1a;每個節點比子樹所有節點的數值都大&#xff0c;根節點是最大值。父子索引號關系&#xff08;根節點為0&#xff09;&#xff1a;&#xff08;向上&#xff09;子節點x&#xff0c;父節點(x…

datawhale大模型應用開發夏令營學習筆記一

參考自 基于LangChainLLM的本地知識庫問答&#xff1a;從企業單文檔問答到批量文檔問答datawhale的llm-universe 作者現在在datawhale夏令營的大模型應用開發這個班中&#xff0c;作為一個小白&#xff0c;為了能為團隊做出一點貢獻&#xff0c;現在就要開始學習怎么使用langch…

實戰教程:如何用JavaScript構建一個功能強大的音樂播放器,兼容本地與在線資源

項目地址&#xff1a;Music Player App 作者&#xff1a;Reza Mehdikhanlou 視頻地址&#xff1a;youtube 我將向您展示如何使用 javascript 編寫音樂播放器。我們創建一個項目&#xff0c;您可以使用 javascript 從本地文件夾或任何 url 播放音頻文件。 項目目錄 assets 1…

頂級10大AI測試工具

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

暑期編程預習指南

暑期編程預習指南 高考結束后&#xff0c;迎來的是一段難得的假期時光。對于那些有志于踏入IT領域的高考生來說&#xff0c;這段時間無疑是一個重要的起點。為了幫助你們更好地利用這個假期&#xff0c;為未來的學習和職業生涯打下堅實的基礎&#xff0c;特此提供一份編程預習…

JWT入門

JWT與TOKEN JWT&#xff08;JSON Web Token&#xff09;是一種基于 JSON 格式的輕量級安全令牌&#xff0c;通常用于在網絡應用間安全地傳遞信息。而“token”一詞則是一個更廣泛的術語&#xff0c;用來指代任何形式的令牌&#xff0c;用于在計算機系統中進行身份驗證或授權。J…

【?講解下Laravel為什么會成為最優雅的PHP框架?】

&#x1f3a5;博主&#xff1a;程序員不想YY啊 &#x1f4ab;CSDN優質創作者&#xff0c;CSDN實力新星&#xff0c;CSDN博客專家 &#x1f917;點贊&#x1f388;收藏?再看&#x1f4ab;養成習慣 ?希望本文對您有所裨益&#xff0c;如有不足之處&#xff0c;歡迎在評論區提出…

cloudreve 設置開機服務

創建一個Systemd服務文件&#xff1a; 打開終端并創建一個新的服務文件&#xff1a; sudo nano /etc/systemd/system/cloudreve.service 在服務文件中添加以下內容&#xff1a; 根據你的設置調整路徑和參數&#xff0c;然后將以下配置粘貼到文件中&#xff1a; [Unit] Descri…

Django學習第四天

啟動項目命令 python manage.py runserver 分頁功能封裝到類中去 封裝的類的代碼 """ 自定義的分頁組件,以后如果想要使用這個分頁組件&#xff0c;你需要做&#xff1a; def pretty_list(request):# 靚號列表data_dict {}search_data request.GET.get(q, &…

Excel為數據繪制拆線圖,并將均值線疊加在圖上,以及整個過程的區域錄屏python腳本

Excel為數據繪制拆線圖,并將均值線疊加在圖上,以及整個過程的區域錄屏python腳本 1.演示動畫A.視頻B.gif動畫 2.跟蹤鼠標區域的錄屏腳本 Excel中有一組數據,希望畫出曲線,并且能把均值線也繪制在圖上,以下動畫演示了整個過程,并且提供了區域錄屏腳本,原理如下: 為節約空間,避免…

從華為和特斯拉之爭,看智能駕駛的未來

“一旦特斯拉完全解決自動駕駛問題并量產Optimus&#xff0c;任何空頭都將被消滅&#xff0c;即使是比爾-蓋茨也不例外。”7月2日&#xff0c;馬斯克再次在社交媒體X上畫下了這樣的“大餅”。 與此同時&#xff0c;特斯拉的股價在最近的三個交易日也迎來了24%的漲幅&#xff0c…

中俄汽車產業鏈合作前景廣闊,東方經濟論壇助力雙邊合作與創新

隨著中國汽車零部件企業的競爭力和創新能力不斷增強&#xff0c;中國汽車及零部件行業在俄羅斯的市場份額和品牌影響力顯著提升&#xff0c;中俄兩國在汽車產業鏈上的合作展現出巨大的潛力和廣闊的前景。2024年5月&#xff0c;俄羅斯乘用車新車銷量達到12.8萬輛&#xff0c;同比…

7.基于SpringBoot的SSMP整合案例-表現層開發

目錄 1.基于Restfu1進行表現層接口開發 1.1創建功能類 1.2基于Restful制作表現層接口 2.接收參數 2使用Apifox測試表現層接口功能 保存接口&#xff1a; 分頁接口&#xff1a; 3.表現層一致性處理 3.1先創建一個工具類&#xff0c;用作后端返回格式統一類&#xff1a;…

SpringMVC 的工作流程和詳細解釋

Spring MVC&#xff08;Model-View-Controller&#xff09;框架是基于經典的 MVC 設計模式構建的&#xff0c;用于開發 Web 應用程序。下面是 Spring Boot MVC 的工作流程和詳細解釋&#xff1a; 1.客戶端發起請求 1.客戶端&#xff08;通常是瀏覽器&#xff09;發起 HTTP 請求…

招聘智能管理系統設計

設計一個招聘智能管理系統&#xff0c;需要從多個維度考慮&#xff0c;包括但不限于用戶界面、功能模塊、數據安全、算法模型等。以下是一個基本的設計框架&#xff1a; 1. 系統架構&#xff1a; 前端&#xff1a;提供直觀的用戶界面&#xff0c;包括應聘者和招聘者的登錄/注冊…