gpfdist可读外部表协议介绍

时间:2024-03-27 11:18:11

原文链接

  • 作为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的连接的典型示例
gpfdist可读外部表协议介绍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