高途資料平臺遷移與成本治理實踐

帶你聊技術發表於2023-02-28


導讀 隨著國家在教育領域推行了“雙減”政策,網際網路線上教育巨頭高途遇到降本增效的挑戰,其中在大資料平臺方面也面臨成本巨大、人員變動等問題,所以資料平臺叢集上雲迫在眉睫。從 2021 年 9 月開始,歷時 3 個月,高途完成了底層叢集從阿里雲的自建平臺遷移到騰訊 EMR,以及眾多資料引擎遷移上雲的工作。

今天對高途資料平臺上雲遷移的實踐的介紹會圍繞以下四個方面展開:

1. 高途上雲遷移資料平臺背景

2. 遷移面臨的困難與挑戰

3. 遷移具體實施方案及心得總結

4. 高途成本管控現狀及未來規劃

分享嘉賓|李明慶 (前)高途 技術專家

編輯整理|Henry hypers

出品社群|DataFun


01

高途上雲遷移資料平臺背景

1. 自建資料平臺的架構與潛在問題

高途資料平臺遷移與成本治理實踐

上圖中可以看到,這是遷移之前的叢集狀態。當時是為了支援業務的快速增長,但隱患也是暗藏其中。
● 第一是成本問題:線上教育火熱的階段,招聘和花錢都不限制,儲存和算力不夠都可以用“買買買”來解決,完全沒時間精力考慮資源浪費的問題;
● 第二是技術氾濫:從架構圖中可以看到,僅實時框架就包含了 Storm,Spark Streaming,Flink 這老中青三代;資料引擎更多,有 HBase,ES,Clickhouse, Impala,Kudu,Presto,Kylin 等,技術眾多無形增加了運維的成本;
● 第三是中臺工具缺失:比如當時使用者想把資料從 Hive 離線的複製到 Kudu;按照大廠常規做法,我們應該提供一個 Web 頁面,使用者在頁面上只需要做源端和目的端的配置,提供兩個表名就可以完成整個操作;但因為當時業務發展太快,技術跟不上業務,導致我們沒有時間去開發這種基礎能力,使用者只能寫指令碼來完成;
● 第四是歷史問題沉積:線上教育行業風起雲湧,瞬息萬變,經常是剛上線一兩個月的東西就要重構,而廢棄鏈路並沒有及時的銷燬,這也就形成了一系列的歷史遺留問題。
2021 年 7 月 24 日國家為減輕義務教育階段學生過重作業負擔和校外培訓負擔釋出了“雙減”政策,政策釋出後,高途迅速積極響應,根據政策要求在第一時間展開行動,進行了針對性的業務調整,企業內部也進行降本增效。其中大資料平臺出於計算、儲存成本和人員維護的考慮,選擇了大資料平臺上雲方案。
2. 分期上雲方案

高途資料平臺遷移與成本治理實踐

經過組裡討論,我們設立了三步走的規劃第一步是短期內是把原來自建的叢集遷到雲上;第二是啟用雲端可用的 Paas 產品,替換掉現有系統;第三個長期規劃是在我們沒有用過的技術能力和前沿科技,透過新的應用把我們的競爭力提升上去。設定規劃後,下一步我們就開始討論遷移面臨的困難。
02
遷移面臨的困難與挑戰
當企業選擇從自建平臺往雲上遷移的時候,往往會面臨很多挑戰。首先,積累多年的歷史遺留問題,都會在遷移中都暴露出來。另外,遷移時使用者還在使用服務和系統可能受影響,所以既要照顧使用者的使用,還要解決遷移中一些不相容的問題。
1. 雲產品眾多帶來選擇困難症

高途資料平臺遷移與成本治理實踐

首先要面對選型的問題。已經確定選雲以後,各個廠家紛至沓來,介紹其產品。但是直到做決策的時候,才發現是非常難的。因為我們心裡想解決的問題很多,既想降成本少花錢,又想有優質服務,還想遷移能輕鬆一些,並且以後迭代能更順暢。一旦考慮太多,總想著“既要又要也要還要”,那決策就十分難做了。
2. 遷移面臨的問題
下一步遷移時具體面臨的問題,情況更為複雜和具有挑戰性。
● 實際問題:比如說大批次資料複製、結果比對;再比如說遷移任務需要業務方的支援,特別還需要說服他們支援和給於一定的容錯的空間;
● 互斥性問題:比如遷移的速度和質量往往就存在天然的矛盾;再比如有一些表沒人認領,不知道是否還在使用,如果一直跑就會佔用計算資源和儲存資源,如果停了又可能會出事。

高途資料平臺遷移與成本治理實踐

問題和矛盾無法避免,遷移的工作還是得幹,所以接下來就是制定遷移的流程。高途從 2021 年 9 月開始,一共用時三個月基本完成遷移。除少數長尾工作以外,大多數業務都已經在雲上跑通,下面將分享其間的一些心得。
03
遷移具體實施方案及心得總結
1. 雲產品選型:取捨五邊形

高途資料平臺遷移與成本治理實踐

選定廠家產品的過程中,我們總結歸納了上圖所示的一個五邊形:
● 經濟成本和售後服務:對於上層領導來說,最關心經濟成本和售後服務,因為這兩個都是直接跟經濟收益相關的;
● 遷移複雜度:對於執行遷移工作的團隊來說最看重這點,要保證最終的可行性;
● 前沿科技:這也是我們考量的一個標準,會影響到長期目標,架構調整和架構升級;
● 團隊穩定性:最後廠商的團隊穩定性也是需要考量的,大家都不希望廠商三天兩頭換對接人,從這一點來說大廠可能更有優勢一些。
對於成熟的資料平臺,像高途已經運營了兩三年,有很多自身烙印了,已經沒有任何一家雲產品可以無縫銜接,所以只能針對功能做選擇篩分。
2. 高途的最終選擇:

高途資料平臺遷移與成本治理實踐

高途最終選擇了騰訊雲,此處並非對其它廠商存在否定之意,只是綜合考量,在當時場景下,這是最貼合我們需求的一個選項。具體到模組,能替換原有服務的都儘量做到物為我用。
● 實時框架:騰訊雲產品 Oceanus 是一個實時平臺,與我們原來自研的實時系統是很接近的,直接替換自研的排程平臺;
● 離線系統:騰訊的離線系統,和我們自己的有很大差距,所以我們就沿用原來自研的資料管理系統,而只使用他們的 EMR
● 其它引擎:例如 HBase、Kudu、ClickHouse 等,雲廠商的運維能力更強,成本也更低,都做相應的切換。
3. 遷移的原則
① C 端業務絕對不能受影響,所有遷移工作都要在夜間低谷執行;
② B 端業務也儘量在低谷期操作,但可接受短期(預設1小時)的不可用,並保證最終可用;
③ 無人認領的任務,可做暫停處理並等待反饋,同時要保證在一段時間(預設3個月)內可隨時恢復;
④ 離線鏈路全部雙跑,非重要鏈路行數一致即放行,重要鏈路除對比行數外還要比對關鍵指標,極重要鏈路延長比對週期;
⑤ 實時鏈路可不雙跑,遷移前做好資料同步(一般為快照同步)準備,並確保新叢集與訊息佇列和輸出引擎間的網路可通;
⑥ 老叢集任務和表下線採用自頂向下模式,隨時做好任務回滾準備(離線任務做重跑,實時任務重置偏移量消費),表可禁用的引擎(如 HBase)做禁用,其它的做停寫處理,觀察使用者反饋;
⑦ 事事留後招,不做一錘子買賣。
遷移工作中,我們總結了 7 點原則。提出這些原則是由於,我們人數不足而且精力有限,不可能一次性完全做到位,所以我們只能把事情拆分出來,哪些重要的提高優先順序,花費精力做好遷移,哪些不重要的可以做一些讓步。
原則的 4~6 項主要是對於安全性方面的支援不詳細展開了,簡單解釋一下前三點:
● C 端業務:比如說使用者有學生在高途平臺上面買課,結果一提交訂單時發現賬戶餘額都沒了,這就是大失誤,是完全不能接受的;C 端的業務是絕對不能受影響的,所有遷移都在夜間低谷進行;
● B 端業務:反過來說對於 B 端業務,因為使用者都是自己人,可能相對更寬容一些,所以能接受短期的不可用,我們當時預設設定是一小時,但以實際情況來說有時還可以適當的放寬;
● 無人認領的任務:不論任務還是表,找不到負責人了怎麼辦?我的想法是暫停維護,但同時要滿足一點,如果有人找上來的話,讓它隨時處於一個可以恢復的狀態;保留時間設為了三個月,三個月以後如果還沒人找,任務和表會徹底刪除;
最後提醒一點:事事留後招,不做一錘子買賣。做遷移這種大事,一定要杜絕“不成功便成仁”的想法。
4. 資料遷移--後設資料和資料組合遷移
接下來介紹遷移工作中的一些具體事項。

高途資料平臺遷移與成本治理實踐

首先是資料遷移。在遷移資料以前我們查了一些資料和大廠遷移的規範,發現大家普遍的精力都是放在了資料遷移上,而很少提到資料和後設資料的搭配遷移;資料遷移過以後,如果沒有後設資料輔佐的話,它只是一堆不可讀的檔案,所以我們當時設立了一整套的組合遷移(上圖是組合遷移的流程)。
● 標記無用的表並清理:第一步是瘦身,舊系統先根據自身情況,把一些無用的、不用遷移的資料提前幹掉,這樣在後邊遷移的時候能節約很多頻寬;
● Metastore 全量快照:第二步“設定時間點”,以這個點為中心,把後設資料全量的 dump 到新叢集的 metastore,這時兩邊的表包括 ID 都是一致的,舊數倉的 partition 在分割槽新的叢集裡也有,但此時新叢集的分割槽中查不到資料,因為資料還沒匯入進來;
● Data 全量快照:第三步是歷史全量資料的複製,這需要相當長的時間,用時跟資料量正相關,我們當初完成複製用時超過一個月;複製完成後,“設定時間點”之前的資料就是既可讀又可用了;
● Data 增量快照:複製歷史資料過程中,舊叢集還在不斷產生新資料,所以在歷史層面的一次全面複製之外,還有數次的輪巡增量複製;增量複製的邏輯跟全量是相反的,全量是先複製後設資料再複製資料,增量是直接複製資料,然後利用 Hive MSCK  Repair 功能把後設資料給補齊,這對應的主要是分割槽增加的情況;還有一種情況是,因為舊叢集還在提供服務,所以可能還在產生新表,而此時新叢集可能也會產生新表,這樣如果未來複製後設資料時,很可能會造成 tbls 表裡邊的 ID 有衝突;解決方案是臨時調整舊叢集後設資料 tbls 表 increment 的方式,手動進行主鍵規避。
5. 資料遷移--方案示例
圖中是一些當時雲廠商給我們的遷移資料方案,包括離線的,以及如 Kudu、HBase、ClickHouse 等各種引擎的,每一個都代表了當時一系列的重複性勞動。

高途資料平臺遷移與成本治理實踐

6. 任務遷移--四象限評估鏈路

高途資料平臺遷移與成本治理實踐

資料遷移說完談談任務遷移。任務遷移也是講主次分明,要把有限精力都放在刀刃上,重點還是說不會影響 C 端使用者,不會影響“不接受任何停頓和不可用狀態”的這種服務;然後根據修復難易度做四象限的拆分,確認哪些應該投入更多精力,哪些簡單處理就可以了,原則還是抓大放小。
7. 任務遷移--重要鏈路的遷移流程

高途資料平臺遷移與成本治理實踐

重要鏈路遷移流程,如圖所示大致分為了三個階段。
實際遷移的重點,首先是單次任務的遷移和比對,每到發現問題的時候,立刻要檢查,可以根據整個鏈路從底向上檢查,如果底層最後一個環節多次比對資料都一致的話,則認為這個鏈路是可靠的,可以透過了,如果最後一個環節不行就逐層往上走,看是哪一層出了問題。
對於不重要的鏈路,對數相對簡單,比如如果連續幾天新舊環境行數是一致的,那麼就可以認為透過了;重要鏈路可能就要麻煩一些,需要核對指標,比如某個列的 sum 值,average 值,然後再去更長週期比對,確保一致才可以放心。
8. 業務部門的協作

高途資料平臺遷移與成本治理實踐

與業務人員的合作中遇到過很多麻煩,業務方可能基於各種原因不配合遷移工作,原因無外乎兩個,一是沒有時間,二是擔心風險。如果能解決這兩個問題,那麼使用者積極性自然就上來了。
我們的做法是:第一,針對使用者繁忙,我們把力所能及的事都處理掉,比如複製資料,重置偏移量,搭建測試環境等,到業務側就只需要做簡單的修改配置、重啟程式、重啟服務,這樣就解決了時間不足的問題;第二,針對風險擔憂,推功攬過,排除其後顧之憂;另外,還是要主次分明,有一些很瑣碎問題,比如是否有人在外部直連我們的主服務,遷移是否有影響等等,只要抱著“做大放小、主次分明”的態度,問題就會迎刃而解。
04
高途成本管控現狀及未來規劃
下面分享下成本管控的現狀和未來規劃。
高途剛遷移完成時,在騰訊雲上的成本相比平臺自建時期降低了 40%。但隨著業務重點發力成人與職業教育、素質教育,大資料計算和儲存資源的使用量又開始快速增長,所以大資料平臺需要進一步進行成本治理和資源利用率治理。
1. 成本管控的最終目的
成本管控的最終目的是什麼?
很多人可能第一感覺就是省錢,降低支出,其實不然。我們的投入是要求產出的,如果花了 50 賺回 100,那麼這 50 就花的值;我花了 20 結果都打水漂了,那 20 花的就不值。所以僅看投入支出,不看產出,實際上是一個錯誤的想法。
因此我們要提高利用率。那怎麼提高利用率呢?
如果叢集 CPU 利用率是 20%,現在提到 80%了,那麼就做到成本管控了?這裡有悖論,假如只寫一個死迴圈,然後在後邊一直刷單,那麼 CPU 利用率肯定高漲,這其實是一個自欺欺人的偽命題,並沒有真的做到成本管控。所以我們最終目的是提高有效利用率,既能把利用率提上去,還要減少浪費,這才是成本管控的最終目的。
那麼如何提高利用率呢?
有兩方面,一是儲存資源,二是計算資源。途徑還是開源節流
有 1 個必須維護的任務,以前可能花 10 個單位的成本,因為運用新技術後可能 5 個單位就解決了,這是開源。原來任務得花 5 個單位的成本去維護,但是發現這個任務無人使用,後把它給將其下線,這就是節流。
2. 成本管控前的儲存資源狀態
先說一下儲存資源當時的狀態和問題,儲存資源的浪費無外乎以下三點:
● 表空跑:表沒人訪問,還每天都在跑,還在生成新的資料;
● 分割槽膨脹:有一些業務線的表是小時級,這樣分割槽就過度膨脹,分割槽數量可能達到幾千上萬個;而且大家也感受到當分割槽數量過多的時候,重啟hiveserver2,就會有相當長的時間一直在載入後設資料,無法正常服務;
● 碎檔案:主要來自 ods 層,因為我們是用 waterdrop 匯入資料,該工具天然的存在一些碎檔案問題,這樣不僅給檔案系統(不管是 hdfs namenode,還是我們現在使用的 cos)的中心程式帶來巨大壓力;當查表的時候,如果表裡同樣是 1GB 的資料,資料分散在 10 個檔案裡邊和分散在 1 萬個檔案裡邊,效果也是不一樣的,在1萬個檔案裡邊的話,可能 hive2 還沒有把這個任務提交到 yarn,就因為記憶體不足任務先崩潰了。
以上就是儲存資源實現成本管控要解決的三座大山。
3. 成本管控前的計算資源狀態

高途資料平臺遷移與成本治理實踐

上圖是計算資源的狀態。每天夜間會有大批次排程去執行,資源使用率飆到很高,接近100%;但是在白天的時候卻顯得風平浪靜,僅在小時級任務執行時有輕微的波動,說明在白天存在極其嚴重的浪費,這些錢是白花的。
4. 表訪問監控

高途資料平臺遷移與成本治理實踐

對於表訪問控制是怎麼解決的?
● 傳統監測方式:熟悉 metastore 人都瞭解可能見過,在關於表的元表 tbls 裡邊有一個列 LAST_ACCESS_TIME,這個列預設是不更新的,一直是 0;透過在 hive 配置中新增 PREHOOK,就能接收到 MapReduce 這種引擎的表訪問記錄,可以把時間戳更新;其缺點是隻能記錄 mapreduce 的訪問,但我們還有其他資料引擎,比如 spark、impala、presto 的查詢是記錄不到的,所以它對我們監控表的訪問有借鑑意義但覆蓋得不夠全面;
● 高途的改進:不論什麼引擎來查表都要經過 metastore,所以我們在 metastore 裡改寫了 preEventListener,metastore 監聽到表被查詢時,就去修改 tbls 表的 LAST_ACCESS_TIME 欄位把時間記錄下來;經過這個改進以後,所有來源的查詢行為都真真切切的被記錄到後設資料裡邊了。
● 靜默率:這時候我們引出了靜默的概念,定義是一個表如果連續 30 天沒有任何訪問,它就是“靜默”的;當時遷移上線以後發現我們的數倉裡高達 80% 以上的表都處於靜默狀態,這也是一個很嚴重的浪費,需要進行管控。
監控了所有表的訪問並統計了靜默率後,前文提到的表的浪費和分割槽的浪費問題就可以解決了。
5. ODS表匯入改造

高途資料平臺遷移與成本治理實踐

下一個要解決的是碎檔案問題。碎檔案基本都來源於 ods 匯入,不管是用傳統的 Apache Sqoop、阿里 dataX,或者我們現在用的 waterdrop,天然都存在碎檔案問題,原因如下:
● 碎檔案產生原理:當拉數的時候,waterdrop 總是去算你取得切分鍵的最小值和最大值,然後根據兩個極值及提交的併發度去算 span,即每一個 worker 的上下限額。比如要查的部分資料,最小的 ID=1 最大 ID=1,000,000,000(10億),併發度設定是 10,000;所以要求就是每個 worker 查最多 10 萬條記錄,此時 worker1 條件就是 where ID>=1 and ID<100,001,worker2 條件是 where ID>=100,001 and ID<200,001,以此類推;但是資料的實際情況有可能是第一條記錄 ID=1,第二條記錄 ID 就已經是5億多了,因為第一條資料奇異歧義的分佈導致了整個任務分佈向左拉伸,結果是很多工的空跑,第一個 worker 可能產生 1 條資料的檔案,中間這些都會產生行數為 0 的空檔案,最後一個 worker 任務幹了絕大部分的活但執行還慢,然後會產生很大的檔案,甚至出現很多小檔案或者碎檔案,這是拉數時存在的問題;

高途的改進是,拉取資料的時候去掃描庫裡的切分鍵鏈,當然一般選主鍵,所以它的速度順序還可以,然後根據我自己提供的 span 去拉數。

比如說我看的第一條資料 ID=1,並且要求每個 worker 就查 10 萬條,然後第 100,001 條可能是 ID=a,那麼 worker1 的查詢條件就是 where ID>=1 and ID<a;第二十萬條資料可能是 id=b;worker2 條件就是 where>=a and ID<b;這樣的結果就是每一個 worker 拉取的行數都是一樣的(但是最後一個 worker 除外,作為一個邊界點,可能資料會比較少,其他 worker 行數完全一樣),而且大家工作壓力也是基本上均攤,所以執行速度提升上來了,而且小檔案問題也解決掉了。

6. 表清理機制
解決了表靜默、分割槽膨脹和靜默,以及碎檔案這三座大山,下一步就要提出制度來實現我們的目的,儲存成本管控,所以我們制定並執行了表清理機制。

高途資料平臺遷移與成本治理實踐


● 靜默表處理:首先針對相當時間內無人訪問的表,特別是佔用空間、分割槽數和檔案數較大的表,優先處理處理採用先通告再冷藏最後刪除的方式;
● 開發規範:對開發環節的邏輯規範增加了要求,比如要建臨時的任務裡用的表,那麼要加上關鍵詞 temporary,這樣會話結束以後,表名就消失掉了,別人不會看到,也會把數倉裡一些垃圾清除掉;
● 機制執行效果:現在儲存管控已經持續了一段時間,靜默率從 80% 降到 40%,儲存空間下降 5%,還在持續最佳化中。
7. 計算資源成本治理
和儲存管控相比,高途現在計算資源管控才剛剛起步,目前很多地方還沒有很直觀的進展,預計可能 Q4 才能看到成效了。
我們規劃了六步最佳化實現計算任務的成本治理,這裡重點介紹兩點,潮汐資源管理任務監控。

高途資料平臺遷移與成本治理實踐

8. 排程資源潮汐式管理

高途資料平臺遷移與成本治理實踐

潮汐資源管理是屬於使用雲原生的技術能力,依賴叢集的容量排程的標籤工具,在每天夜晚把資源擴容,保證能扛住夜間的排程高峰;然後到白天比如早上 8 點的時候,我們知道白天時間段可能不再用這麼多資源,就把夜晚的擴容部分縮掉;假如按剛才說到的白天常規 30% 的資源使用率,就將這些作為常規儲備,另外 70% 作為夜間的潮汐性擴容進來的資源(假定擴容資源每天只用 8 小時),這樣計算成本也就是 30%,再加上 70% 乘以 1/3,也就只剩 51% 的綜合成本了。
9. 任務消耗資源監控

高途資料平臺遷移與成本治理實踐

任務的監控,依賴於 yarn rest API 週期性的收集平臺跑的任務,要針對設定的閾值,比如這個任務佔用 core 的核數超過了一定數量或超過了一個比例,或者資源超過了一定數量比例,而且持續時間達到了確定分鐘數的話,就在企業內部 im 上給負責人發出報警,強制其整改,這樣也能間接的把資源浪費問題解決掉。
10. 規劃的技術替換

高途資料平臺遷移與成本治理實踐

最後介紹一下未來規劃:
● Paas 工具應用:可能有一些 Paas 工具可以較好地取代我們現有的某些系統,這樣可以減輕我們自己的運維壓力;
● 新技術應用:應用新技術,會對業務水平和輸入能力有很大提高;
● 歷史問題的處理:一些問題,比如 kudu/impala 這一板塊運維能力差,會想辦法遷走。
● 計劃 Q4 驗收:我們計劃把整個成本再降低20%,實現有效管控。
05

問答環節

Q1:先遷移任務,再每日核對,再同步歷史任務,會有讀很久歷史分割槽資料的任務,這樣整條鏈路的資料都是不準確的,然後不能把所有的讀取很久的歷史分割槽資料的任務單獨都撈取出來,所以說有什麼好的辦法?

A1:這種情況是說,如果你的上游不穩定的話,那麼儘量把上一層資料都原樣複製,從舊叢集同步到新叢集;每次只是檢查當前這一塊任務的一個準備性,驗證條件是說我輸入是確定的情況下,我的任務是不是準,而不是說連帶的去校驗我輸入是否都正確,這是上一環節它考慮的事情。
Q2:對於選型,像騰訊雲、阿里雲、華為雲等,從業務的角度來考慮的話,都會對比哪些?
A2:初期考慮的主要幾項,一是經濟成本,二是運維能力,還有很重要的是運維的責任心;當時來看我們選擇的廠商它折扣還是很大的,對我們當前的狀態是有很大幫助。
第二點是當時我們人員變動,運維的能力不夠,當下的人力是不可能把這個遷移完全搞起來的,而那個時候騰訊雲不僅有很多專家可以遠端支援,甚至還派了一些人到我們現場駐紮來協助遷移環節,這些都是讓我們很能接受的一個方面。
長期來說還是前邊總結的五邊形,我選用你們廠家,那麼你們以後在技術方面打造的策略什麼?你是固步自封一直還用當前這點一畝三分地,還是說以後如果是業內有新的技術方案,你就能相對及時的把它引進來?
還有遷移的是否容易,因為像剛才所說,每家的自研系統都帶了自己的烙印,其實這是雲廠商雲產品所不能支援的,所以是我來相容你還是你來相容我,這些都是看出這個廠商是否可選的一點。
最後要強調穩定性,毋庸多言。
Q3:需要遷移的歷史資料太多了,每天又不斷寫入,有的還不斷重新整理歷史資料,這樣寫叢集的資料的問題如何解決?
A3:這個問題確實存在著,當時我們以那個時間卡點,卡住以後,舊的叢集還是會有一些資料重刷,所以這塊確實也是一種比較 low 的方式。先看這個資料更新時間是晚於這個時間,然後在下一期增量更新的時候,可能問一下負責人他是需要你從舊叢集裡面複製到新的,還是在新叢集裡邊去跑出來這部分資料。如果是他能接受新叢集裡邊跑的話,這是簡單的。如果他還要拷的話,那麼只能我們費點勁給他拉過去,這確實沒有太好辦法,但是苦一陣子比苦一輩子要強吧。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2937359/,如需轉載,請註明出處,否則將追究法律責任。

相關文章