PXF故障排查

PXF错误

下表描述了使用PXF时可能会遇到的一些错误:

Error Message Discussion
Protocol “pxf” does not exist Cause: pxf扩展名未注册。
Solution: 按照PXF启用过程中的说明为Enable Procedure 为数据库创建(启用)PXF扩展
Invalid URI pxf://<path-to-data>: missing options section Cause: LOCATION URI配置项不包括配置或其他需要的信息。
Solution:在URI中提供配置和必需的选项。
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://<namenode>:8020/<path-to-file> Cause: 在<path-to-file>中指定的HDFS文件不存在。
Solution: 指定现有HDFS文件的路径
NoSuchObjectException(message:<schema>.<hivetable> table not found) Cause: <schema>.<hivetable>指定的Hive表不存在。
Solution: 提供存在的Hive表的名称。
Failed to connect to <segment-host> port 5888: Connection refused (libchurl.c:944) (<segment-id> slice<N> <segment-host>:40000 pid=<process-id>)
Cause: 在<segment-host>主机上PXF未运行。
Solution: <segment-host>主机上重启PXF
ERROR: failed to acquire resources on one or more segments
DETAIL: could not connect to server: Connection refused
    Is the server running on host “<segment-host>” and accepting
    TCP/IP connections on port 40000?(seg<N> <segment-host>:40000)
Cause: GPDB集群 <segment-host> 节点down
org.apache.hadoop.security.AccessControlException: Permission denied: user=, access=READ, inode=“”:::-rw——- Cause: 执行PXF操作的Greenplum数据库用户无权访问基础Hadoop服务(HDFS或Hive)。参阅Configuring User Impersonation and Proxying.

PXF日志

启用更详细的日志记录可能有助于PXF故障排除工作。 PXF提供了两类消息日志记录:服务级别和客户端级别。

服务级别日志记录

PXF利用log4j进行服务级别的日志记录。PXF-service-related日志消息捕获由$PXF_CONF/conf/pxf-log4j.properties文件中的log4j控制。默认的PXF日志记录配置会将INFO和更严格的日志记录写入$PXF_CONF/logs/pxf-service.log。您可以配置日志记录级别和日志文件位置。

启用DEBUG级别时,PXF提供更详细的日志记录。要配置PXFDEBUG日志记录并检查输出,请执行以下操作:

  1. 登录gpdb集群的master主机

    $ ssh gpadmin@<gpmaster>
    
  2. 使用编辑器打开 $PXF_CONF/conf/pxf-log4j.properties,取消以下行的注释,保存文件,然后退出编辑器:

    #log4j.logger.org.greenplum.pxf=DEBUG
    
  3. 使用 pxf cluster sync 命令拷贝更新的文件 pxf-log4j.properties 到Greenplum数据库集群。例如:

    gpadmin@gpmaster$ $GPHOME/pxf/bin/pxf cluster sync
    
  4. 依照Restarting PXF章节描述,重启gpdb集群的每个segment节点的pxf

  5. 现在启用了DEBUG级别的日志记录,您可以执行PXF操作。 确保记下时间; 这会将信息定向输出到 $PXF_CONF/logs/pxf-service.log中的相关日志。

    $ date
    Wed Oct  4 09:30:06 MDT 2017
    $ psql -d <dbname>
    
  6. 创建和查询外部表。例如:

    dbname=> CREATE EXTERNAL TABLE hdfstest(id int, newid int)
        LOCATION ('pxf://data/dir/hdfsfile?PROFILE=hdfs:text')
        FORMAT 'TEXT' (delimiter='E',');
    dbname=> SELECT * FROM hdfstest;
    <select output>
    
  7. 最后,从pxf-service.log检查/收集日志消息。

Note: DEBUG 记录非常冗长,并且会对性能产生影响. 在收集了所需的信息之后,请关闭PXF服务的DEBUG日志记录。

客户端级别日志记录

数据库级客户端日志记录可以提供对内部PXF服务操作的了解。

在psql会话中将client_min_messages服务器配置参数设置为DEBUG2,可以在对PXF外部表进行操作期间启用Greenplum数据库及PXF调试消息日志记录。

$ psql -d <dbname>
dbname=# SET client_min_messages=DEBUG2;
dbname=# SELECT * FROM hdfstest;
...
DEBUG2:  churl http header: cell #19: X-GP-URL-HOST: seghost1  (seg0 slice1 127.0.0.1:40000 pid=3981)
CONTEXT:  External table hdfstest
DEBUG2:  churl http header: cell #20: X-GP-URL-PORT: 5888  (seg0 slice1 127.0.0.1:40000 pid=3981)
CONTEXT:  External table hdfstest
DEBUG2:  churl http header: cell #21: X-GP-DATA-DIR: data/dir/hdfsfile  (seg0 slice1 127.0.0.1:40000 pid=3981)
CONTEXT:  External table hdfstest
DEBUG2:  churl http header: cell #22: X-GP-OPTIONS-PROFILE: hdfs:text  (seg0 slice1 127.0.0.1:40000 pid=3981)
CONTEXT:  External table hdfstest
...

检查/收集来自stdout的日志消息

Note: DEBUG2数据库会话日志记录会影响性能。记住,在收集了所需的信息之后,请关闭DEBUG2日志记录。

dbname=# SET client_min_messages=NOTICE;

解决PXF内存问题

因为单个PXF客户端服务(JVM)为segment主机上的多个segment实例提供服务,所以PXF堆大小可能是限制运行的瓶颈。在并发工作负载时针对大文件的查询,影响更加明显。您可能会遇到由于内存不足或Java垃圾收集器影响响应时间而导致查询挂起或失败的情况。要避免或纠正这些情况,请首先尝试增加Java最大堆大小或减少Tomcat最大线程数,这取决于最适合您系统配置的方式。您还可以选择将PXF配置为在检测到内存不足情况时执行特定的操作。

Note: 本主题中描述的配置更改需要在Greenplum数据库集群的每个节点上修改配置文件。 在主服务器上执行更新后,请确保将PXF配置同步到Greenplum数据库集群。

配置内存不足条件操作

在内存不足(OOM)的情况下,PXF返回以下错误以响应查询:

java.lang.OutOfMemoryError: Java heap space

您可以将PXF JVM配置为在检测到OOM条件时启用/禁用以下操作:

  • 自动杀死PXF服务器(默认情况下启用)。
  • 转储Java堆(默认情况下禁用)。

自动杀死PXF服务器

默认情况下,对PXF进行了配置,以便当PXF JVM在segment主机上检测到内存不足情况时,它将自动运行一个脚本,该脚本将杀死主机上运行的PXF服务器。 PXF_OOM_KILL配置属性控制此自动终止行为。

启用自动终止功能后,PXF JVM检测到OOM条件并终止segment主机上的PXF服务器:

  • PXF将以下消息记录到segment主机上的$PXF_CONF/logs/catalina.out中:

    =====> <date> PXF Out of memory detected <======
    =====> <date> PXF shutdown scheduled <======
    
  • 在PXF外部表上运行的任何查询都将失败,并显示以下错误,直到您在segment主机上重新启动PXF服务器为止:

    ... Failed to connect to <host> port 5888: Connection refused
    

当以这种方式关闭segment主机上的PXF服务器时,必须显式重新启动主机上的PXF服务器。 有关pxf start命令的更多信息,请参见pxf参考页。

有关禁用/启用此PXF配置属性的说明,请参考下面的配置procedure

转储Java堆

在内存不足的情况下,捕获Java堆转储以帮助确定导致资源耗尽的因素可能很有用。 您可以使用PXF_OOM_DUMP_PATH属性来配置PXF在检测到OOM条件时将堆转储写入文件。 默认情况下,PXF不会在OOM上转储Java堆。

如果选择在OOM上启用堆转储,则必须将PXF_OOM_DUMP_PATH设置为文件或目录的绝对路径:

  • 如果指定目录,则PXF JVM将堆转储写入文件<directory>/java_pid<pid>.hprof,其中<pid>标识PXF服务器实例的进程ID。 每次JVM进行OOM操作时,PXF JVM都会将新文件写入目录。
  • 如果指定文件,但该文件不存在,则PXF JVM在检测到OOM时会将堆转储写入文件。 如果文件已经存在,则JVM将不会转储堆。

确保gpadmin用户对转储文件或目录具有写权限。

Note: 堆转储文件通常很大。 如果在OOM上为PXF启用堆转储,并为PXF_OOM_DUMP_PATH指定一个目录,则多个OOM将在该目录中生成多个文件,并可能消耗大量磁盘空间。 如果为PXF_OOM_DUMP_PATH指定文件,则在文件名不变的情况下磁盘使用率是恒定的。 您必须重命名转储文件或配置其他PXF_OOM_DUMP_PATH才能生成后续的堆转储。

有关启用/禁用此PXF配置属性的说明,请参阅下面的配置步骤

步骤

默认情况下,将启用OOM上PXF服务器的自动终止功能。 默认情况下,在OOM上禁用堆转储生成。 要配置这些属性之一或全部,请执行以下步骤:

  1. 登录到您的Greenplum数据库主节点:

    $ ssh gpadmin@<gpmaster>
    
  2. 编辑$PXF_CONF/conf/pxf-env.sh文件。 例如:

    gpadmin@gpmaster$ vi $PXF_CONF/conf/pxf-env.sh
    
  3. 如果您想在OOM上配置(即关闭或重新打开)PXF服务器自动关闭功能,请在pxf-env.sh文件中找到PXF_OOM_KILL属性。 如果该设置已被注释掉,请取消注释它,然后更新该值。 例如,要关闭此行为,请将值设置为false

    export PXF_OOM_KILL=false
    
  4. 如果您要在PXF服务器达到OOM条件时配置(即打开或关闭)自动堆转储,请在pxf-env.sh文件中找到PXF_OOM_DUMP_PATH设置。

    1. 要打开此行为,请将PXF_OOM_DUMP_PATH属性值设置为您希望PXF JVM将Java堆转储到的文件系统位置。 例如,要转储到名为/home/gpadmin/pxfoom_segh1的文件:

      export PXF_OOM_DUMP_PATH=/home/pxfoom_segh1
      
    2. 要在打开堆转储后将其关闭,请注释掉PXF_OOM_DUMP_PATH属性设置:

      #export PXF_OOM_DUMP_PATH=/home/pxfoom_segh1
      
  5. 保存pxf-enf.sh文件并退出编辑器。

  6. 使用pxf cluster sync命令将更新的pxf-env.sh文件复制到Greenplum数据库集群。 例如:

    gpadmin@gpmaster$ $GPHOME/pxf/bin/pxf cluster sync
    
  7. 重新启动PXF中所述,在每个Greenplum数据库segment主机上重新启动PXF。

为PXF增加JVM内存

在segment主机上运行的每个PXF代理都配置有默认的最大Java堆大小2GB和初始堆大小1GB。 如果Greenplum数据库群集中的segment主机具有足够的内存,请尝试将最大堆大小增加到3-4GB之间的值。 如果可以,将初始堆大小和最大堆大小设置为相同的值最佳。

执行以下过程来增加在Greenplum数据库集群中每个segment主机上运行的PXF代理服务的堆大小。

  1. 登录gpdb集群的master主机

    $ ssh gpadmin@<gpmaster>
    
  2. 编辑$PXF_CONF/conf/pxf-env.sh文件。 例如:

    gpadmin@gpmaster$ vi $PXF_CONF/conf/pxf-env.sh
    
  3. pxf-env.sh文件中找到PXF_JVM_OPTS设置,然后将 -Xmx 和/或 -Xms 选项更新为所需的值。 例如:

    PXF_JVM_OPTS="-Xmx3g -Xms3g"
    
  4. 保存文件并退出编辑器。

  5. 使用pxf cluster sync 命令将更新的pxf-env.sh文件复制到Greenplum数据库集群。 例如:

    gpadmin@gpmaster$ $GPHOME/pxf/bin/pxf cluster sync
    
  6. 依照Restarting PXF描述,重启每个segment主机上的pxf服务。

资源受限的PXF segment主机的另一种选择

如果增加最大堆大小不适合您的Greenplum数据库部署,请尝试减少PXF的的并发工作线程数。正在运行的线程数量的减少将防止任何PXF节点耗尽其内存,同时确保当前查询运行完毕(尽管速度稍慢)。 Tomcat的默认行为是将请求排队,直到线程空闲或队列耗尽为止。

PXF的Tomcat线程的默认最大数量为200。PXF_MAX_THREADS配置属性控制此设置。

PXF线程容量由配置文件以及是否压缩数据确定。 如果计划在外部Hive数据存储中的大量文件上运行大型工作负载,或者正在读取压缩的ORC或Parquet数据,请考虑指定较低的PXF_MAX_THREADS值。

Note: 请记住,线程数用完后,线程数的增加与内存消耗的增加相关。

执行以下过程,以设置在Greenplum数据库部署中每个segment主机上运行的PXF代理的Tomcat线程的最大数量。

  1. 登录到gpdb集群的master节点

    $ ssh gpadmin@<gpmaster>
    
  2. 编辑$PXF_CONF/conf/pxf-env.sh。例如:

    gpadmin@gpmaster$ vi $PXF_CONF/conf/pxf-env.sh
    
  3. pxf-env.sh文件中找到PXF_MAX_THREADS设置。 取消注释设置,并将其更新为所需的值。 例如,要将Tomcat线程的最大数量设置为100:

    export PXF_MAX_THREADS=100
    
  4. 保存文件并退出编辑器。

  5. 使用pxf cluster sync命令将更新的pxf-env.sh文件复制到Greenplum数据库集群。 例如:

    gpadmin@gpmaster$ $GPHOME/pxf/bin/pxf cluster sync
    
  6. 依照Restarting PXF描述重启PXF服务

解决PXF JDBC连接器时区错误

您可以使用PXF JDBC连接器访问存储在外部SQL数据库中的数据。如果为PXF服务器设置的默认时区与为外部SQL数据库设置的时区不匹配,则取决于JDBC驱动程序,该程序可能会返回错误。

例如,如果使用PXF JDBC连接器访问时区冲突的Oracle数据库,则PXF会记录类似于以下内容的错误:

SEVERE: Servlet.service() for servlet [PXF REST Service] in context with path [/pxf] threw exception
java.io.IOException: ORA-00604: error occurred at recursive SQL level 1
ORA-01882: timezone region not found

如果遇到此错误,可以在$PXF_CONF/conf/pxf-env.sh配置文件中的PXF_JVM_OPTS属性设置中为PXF服务器设置默认时区选项。 例如,要设置时区:

export PXF_JVM_OPTS="<current_settings> -Duser.timezone=America/Chicago"

您也可以使用PXF_JVM_OPTS属性来设置其他Java选项。

如前几节所述,您必须将更新的PXF配置同步到Greenplum数据库集群,然后在每个segment主机上重新启动PXF服务器。

PXF片段元数据缓存

PXF连接器Fragmenter使用来自外部数据源的元数据将数据拆分为可并行读取的片段列表(块,文件等)。 PXF在每个查询的基础上缓存片段元数据:访问片段元数据的第一个线程将信息存储在缓存中,其他线程重用此缓存的元数据。 这种性质的缓存减少了具有大量片段的外部数据源对查询内存的需求。

默认情况下,PXF片段元数据缓存处于启用状态。 要关闭片段元数据缓存,或在关闭后重新启用片段元数据缓存,请执行以下过程:

  1. 登录到您的Greenplum数据库主节点:

    $ ssh gpadmin@<gpmaster>
    
  2. 编辑$PXF_CONF/conf/pxf-env.sh文件。 例如:

    gpadmin@gpmaster$ vi $PXF_CONF/conf/pxf-env.sh
    
  3. pxf-env.sh文件中找到PXF_FRAGMENTER_CACHE设置。 如果该设置已被注释掉,请取消注释它,然后更新该值。 例如,要关闭片段元数据缓存,请将值设置为false

    export PXF_FRAGMENTER_CACHE=false
    
  4. 保存文件并退出编辑器。

  5. 使用pxf cluster sync命令将更新的pxf-env.sh文件复制到Greenplum数据库集群。 例如:

    gpadmin@gpmaster$ $GPHOME/pxf/bin/pxf cluster sync
    
  6. 重新启动PXF中所述,在每个Greenplum数据库segment主机上重新启动PXF。