gpfdist可讀外部表協議介紹

原文鏈接

  • 作爲Greenplum所有ETL操作基本原理,我們有必要稍微多介紹一些gpfdist的細節,以便於理解爲什麼它比其他工具速度更快,以及將來我們應如何對其進行改進。
  • 本文將聚焦在gpfdist server和Greenplum 可讀外部表之間的通信細節上,介紹數據流以及gpfdist外部表協議。
  • Gpfdist使用HTTP協議和Greenplum segment通信。Gpfdist作爲HTTP Server,負責將靜態文件內容分發到GPDB,或從GPDB接收內容。每個Segment作爲一個HTTP client,通過get或post從gpfdist獲取數據。

HTTP Header 介紹

  • Gpfdist 協議使用特殊的HTTP Header傳遞GPDB和Gpfdist之間必要信息。下表列出了gpfdist 可讀外部表用到的所有特殊HTTP Hader。
Header Message type Required description
X-GP-XID Request Y transaction id
X-GP-CID Request Y command id
X-GP-SN Request Y scan counter
X-GP-SEGMENT-ID Request N segment id
X-GP-SEGMENT-COUNT Request N Segment count
X-GP-LINE-DELIM-LENGTH Request N length of line ending
X-GP-PROTO Request/Response Y protocol version, 0 or 1
X-GP-MASTER_HOST Request N GPDB master host address
X-GP-MASTER_PORT Request N GPDB master port
X-GP-CSVOPT Request Y CSV option format
X-GP_SEG_PG_CONF Request N config path of segment
X-GP_SEG_DATADIR Request N data directory of segment
X-GP-DATABASE Request N current database name
X-GP-USER Request N current login user
X-GP-SEG-PORT Request N Segment port
X-GP-SESSION-ID Request N gp_session_id
X-GPFDIST-VERSION Response Y gpfdist server version
  • 上述表中Message type一列表示對應的Header字段應該出現在什麼位置。
    • Request 表示出現在從Greenplum到gpfdist的HTTP請求頭中
    • Response表示出現在gpfdist的響應頭中
  • 並非所有字段都是必須的,具體參見required
  • 接下來將介紹最重要的幾個字段:

X-GP-SN

  • Greenplum外部表目前只支持順序掃描,因此一些self-join的查詢會對一個外部文件進行兩次掃描。X-GP-SN用來記錄當前掃描計數。Gpfdist將會使用該參數(連同command id和transaction id)來決定兩個連接是否屬於同一個session。

X-GP-PROTO

  • 可讀外部表有兩種不同的協議,Protocol 0 和 Protocol 1 目前都是可用的。我們稍後會介紹他們的區別。該參數是gpfdist識別一個請求是否來自GPDB還是其他工具的重要依據。Gpfdist會拒絕沒有X-GP-PROTO的連接。

X-GP-CSVOPT

  • GPfdist 支持text和csv格式。
    • Text很方便處理。每解析一行就發送數據給GPDB就可以了。
    • 對於CSV格式,gpfdist需要知道更多關於轉義(escape)或引號符(quote character)的信息。其格式爲m.x.q.n.h.。各小寫字母的含義如下:
Letter Meaning Example
m Csv or not 1 or 0
x Decimal number of escape byte 9 (TAB), 124 (|), etc
q Decimal number of quote byte 34(“)
n EOL type 0-(EOL_UNKNOWN), 1-(EOL_LF), 2-(EOL_CR), 3-(EOL_CRLF)
h With header or not 1 or 0
  • 示例m1x9q34n0h0

可讀外部表如何工作

  • 當用戶在可讀外部表上執行一個select查詢時,GPDB的每個segment各自發送已填好Header字段的HTTP GET請求到gpfdist,獲取和此次查詢相關的數據。
  • 當gpfdist收到來自GPDB segment的請求後,按照每個請求中的<transaction id,command id,scan count> 參數,分組到各個session。所有屬於同一個session的請求都是服務於同一個查詢的,且由不同的segment並行發送而來。gpfdist會根據URL路徑,讀取本地文件的數據,直到已經讀取足夠多的數據到緩存之後纔會發送。默認緩存大小是32KB,可通過-m參數修改。如果gpfdist正在讀的文件是一個管道,且管道輸入很慢,它會持續等待,且不會響應其他請求。這是gpfdist當前版本的一個侷限,在後續版本中將會得到改進。

可讀外部表GUC

gp_external_max_segs

  • 用於控制每個查詢中,允許連接到單個gpfdist上的最大segment數量。即對於同一個查詢session,最多允許gp_external_max_segs個segment連接到單個gpfdist server。默認值是64. Gpfdist在開始發送數據之前不需要等待所有segment都連接上來。每個segment一次只會創建一個到gpfdist的連接。第一個到gpfdist的連接會在gpfdist中創建一個session,之後屬於同一個查詢的連接都會加入這個session。只要session非空,gpfdist就會輪詢地(round robin)通過這些連接向segment發送數據。

readable_external_table_timeout

  • 該值控制GPDB在取消鏈接之前的等待時間。如果一個基於gpfdist的查詢執行了很長時間,將會回錯誤intermittent network connectivity issues。用戶可自己設置readable_external_table_timeout 的值。

可讀外部表工作流

  • 可讀外部表的工作流是很簡單的。GPDB發送HTTP請求到gpfdist,gpfdist返回HTTP響應和請求的數據。
  • 有兩個版本的協議可用於讀外部表,通過X-GP-PROTO區分。我們接下來將會解釋二者的區別。下面是可讀外部表在單個segment和gpfdist之間的工作流。

Protocol 0

  • Protocol 0很簡單:使用HTTP頭部字段來傳遞所有元數據。GPDB Segments 發送 GET請求,gpfdist向segment響應原始數據(raw data)
  • Protocol 0最大的缺陷在於當gpfdist內部發生錯誤時,沒有途徑告知GPDB。如果gpfdist被用戶殺掉,或原始文件損壞,gpfdist無法將此類消息告知GPDB。它唯一能做的就是立即關閉socket以結束HTTP連接。然後,這和普通的讀成功時表現一致,因此GPDB無法識別讀成功還是失敗。

Protocol 1

  • Protocol 1的目的就是解決Protocol 0最致命的缺陷。它爲每個數據塊(稱之爲package)定義了一個新的數據格式,封裝後再發送給GPDB。Gpfdist和GPDB不會直接發送原始數據。所有數據通過特殊格式封裝,然後通過一個個package發送。Package 由消息構成。有3中類型的package和4種類型的消息。每種消息有3個字段:message type,content length,content
Field name field length
Message type 1
Content length 4
Content data Value of Content length
  • 以下是對4種消息類型的描述:
Message Type Full name content
F filename file name that related data belong to
O offset approx office(譯註:疑爲筆誤,應該是offset) in file of current data
D data the real data
E error Error message of gpfdist
L line number approx line number in file
  • 由於gpfdist從文件夾中查找文件時支持通配符,F消息(filename)總是顯示數據所在的正確文件名。 Offset(O)和line number(L)是對數據在文件中位置的一個估值,在向用戶展示錯誤信息的時候很有意義,比如當Greenplum解析數據內容時發現格式錯誤。可以通過該信息知道文件中發生錯誤的大概位置。
  • Package 可對數據或消息進行封裝。
    • 對於數據package,消息序列是F,O,L,D。
    • 如果沒有更多消息可發送,gpfdist將發送空的package並攜帶長度爲0的D消息,用於關閉連接。
    • 如果有錯誤,gpfdist發送包含錯誤詳細信息的E消息
Package type Message content
Data FOLD
End zero-length D
Error E

- 下圖爲Protocol 1的連接的典型示例
這裏寫圖片描述l

  • 如果對HTTP協議熟悉,你會注意到上述消息和HTTP Chunked-mode很類似,但實際上二者是完全不同的,儘管其目的類似。
    • Chunked-mode 非常適合傳輸流式數據
    • Gpfdist的Protoco1響應,借鑑了HTTP並添加了其專有的特殊目的元數據。

概述

  • 本文介紹了gpfdist可讀外部表的兩種協議。可通過wireshark工具理解這些協議,該工具能捕獲TCP報文並以圖形化方式展示通信過程。建議和gpfdist相同的的主機上運行wireshark,以觀察來自GPDB segment的請求和響應。
  • 新寫一個基於上述協議、能夠發送數據到GPDB的簡單版本gpfdist並不難。事實上目前已有一些gpfdist的實現,比如Gemfire GPDB Connector 或者 一個C#版本的工具(https://github.com/pf-qiu/gpfdist.net)

參考

https://gpdb.docs.pivotal.io/43160/ref_guide/config_params/guc-list.html
https://github.com/greenplum-db/gpdb/tree/master/src/bin/gpfdist

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章