使用exchange-2.6.1从clickhouse导入数据至nebula报错 UnknownHostException以及中文显示乱码

问题描述

nebula 版本:2.6.2
安装部署方式:Docker-Compose
通过 nebula-exchange-2.6.1.jarclickhouse导入数据至nebula遇到几个问题。

问题1:

clickhouse_application.conf中:

  • 如果配置所有的metad节点地址,那么报错UnknownHostException
  • 如果只填写报错信息后的metad节点地址, 那么不会报错,导入成功
  • 如果只填写另两个metad节点地址中的任意一个, 那么报相同错UnknownHostException

报错信息如下:

22/02/21 08:07:21 ERROR MetaClient: Get Space Error: java.net.UnknownHostException: metad0
Exception in thread "main" com.facebook.thrift.transport.TTransportException: java.net.UnknownHostException: metad0
        at com.facebook.thrift.transport.TSocket.open(TSocket.java:206)
        at com.vesoft.nebula.client.meta.MetaClient.getClient(MetaClient.java:145)
        at com.vesoft.nebula.client.meta.MetaClient.freshClient(MetaClient.java:165)
        at com.vesoft.nebula.client.meta.MetaClient.getSpace(MetaClient.java:227)
        at com.vesoft.nebula.client.meta.MetaClient.getTags(MetaClient.java:255)
        at com.vesoft.nebula.exchange.MetaProvider.getLabelType(MetaProvider.scala:93)
        at com.vesoft.nebula.exchange.utils.NebulaUtils$.getDataSourceFieldType(NebulaUtils.scala:31)
        at com.vesoft.nebula.exchange.processor.VerticesProcessor.process(VerticesProcessor.scala:111)
        at com.vesoft.nebula.exchange.Exchange$$anonfun$main$2.apply(Exchange.scala:150)
        at com.vesoft.nebula.exchange.Exchange$$anonfun$main$2.apply(Exchange.scala:126)
        at scala.collection.immutable.List.foreach(List.scala:392)
        at com.vesoft.nebula.exchange.Exchange$.main(Exchange.scala:126)
        at com.vesoft.nebula.exchange.Exchange.main(Exchange.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52)
        at org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:845)
        at org.apache.spark.deploy.SparkSubmit.doRunMain$1(SparkSubmit.scala:161)
        at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:184)
        at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86)
        at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:920)
        at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:929)
        at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.net.UnknownHostException: metad0
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:607)
        at com.facebook.thrift.transport.TSocket.open(TSocket.java:201)
        ... 24 more

问题 2:

导入数据的所有中文显示为?

运行环境

Docker 环境

λ docker --version
Docker version 20.10.12, build e91ed57

λ docker-compose --version
Docker Compose version v2.2.3

docker-version

docker-compose-version

Clickhouse 环境

部署方式:docker-compose 部署
版本:22.1.3.7
数据:官方basketballplayer,额外添加一个存在中文属性的player顶点

clickhouse-version

Spark 环境

java 版本:OpenJDK 64-Bit Server VM, Java 1.8.0_252
scala 版本:Scala version 2.11.12
spark 版本:version 2.4.6

Nebula 环境

使用 docker-compose 部署:
来源:

$ git clone -b v2.6 https://github.com/vesoft-inc/nebula-docker-compose.git

修改项:

  • --v=0 修改为 --v=3

服务状态


创建Schema

通过 studio 界面连接并通过控制台界面创建 schema

## 创建图空间
CREATE SPACE IF NOT EXISTS basketballplayer (partition_num = 10,  replica_factor = 1, vid_type = FIXED_STRING(30));

## 创建 Tag player
CREATE TAG player(name string, age int);

## 创建 Tag team
CREATE TAG team(name string);

## 创建 Edge type follow
CREATE EDGE follow(degree int);

## 创建 Edge type serve
CREATE EDGE serve(start_year int, end_year int);

配置信息

1 填写所有 metad 地址(address部分)

注: 有些为临时端口, 重启docker-compose 后需要修改。

{
    # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口。
    graph:["192.168.0.4:9669", "192.168.0.4:63264", "192.168.0.4:63271"]
    meta:["192.168.0.4:63237", "192.168.0.4:63241", "192.168.0.4:63244"]
}

2 填写指定 metad 地址(address部分)

注: 有些为临时端口, 重启docker-compose 后需要修改。

{
    # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口。
    # 全填写时报错信息 ERROR MetaClient: Get Space Error: java.net.UnknownHostException: metad0
    # 填写 metad0 地址, 填写其它两个节点会报相同错误
    graph:["192.168.0.4:9669"]
    meta:["192.168.0.4:63237"]
}

3 配置文件(全)

{
  # Spark 相关配置
  spark: {
    app: {
      name: Nebula Exchange 2.6.1
    }
    driver: {
      cores: 1
      maxResultSize: 1G
    }
    cores {
      max: 16
    }
  }

# Nebula Graph 相关配置
  nebula: {
    address:{
      # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口。

      # # test 1
      # graph:["192.168.0.4:9669", "192.168.0.4:63264", "192.168.0.4:63271"]
      # meta:["192.168.0.4:63237", "192.168.0.4:63241", "192.168.0.4:63244"]

      # test 2
      graph:["192.168.0.4:9669"]
      meta:["192.168.0.4:63237"]

    }
    user: root
    pswd: nebula
    space: basketballplayer
    connection {
      timeout: 3000
      retry: 3
    }
    execution {
      retry: 3
    }
    error: {
      max: 32
      output: /tmp/errors
    }
    rate: {
      limit: 1024
      timeout: 1000
    }
  }
  tags: [
    # 设置 Tag player 相关信息。
    {
      name: player
      type: {
        source: clickhouse
        sink: client
      }
      url:"jdbc:clickhouse://192.168.0.4:20044/basketballplayer?characterEncoding=UTF-8"
      user:"default"
      password:""
      numPartition:"5"
      sentence:"select * from player"
      fields: [name,age]
      nebula.fields: [name,age]
      vertex: {
        field:playerid
      }
      batch: 256
      partition: 32
    }
    {
      name: team
      type: {
        source: clickhouse
        sink: client
      }
      url:"jdbc:clickhouse://192.168.0.4:20044/basketballplayer?characterEncoding=UTF-8"
      user:"default"
      password:""
      numPartition:"5"
      sentence:"select * from team"
      fields: [name]
      nebula.fields: [name]
      vertex: {
        field:teamid
      }
      batch: 256
      partition: 32
    }
  ]
  edges: [
    {
      name: follow
      type: {
        source: clickhouse
        sink: client
      }
      url:"jdbc:clickhouse://192.168.0.4:20044/basketballplayer?characterEncoding=UTF-8"
      user:"default"
      password:""
      numPartition:"5"
      sentence:"select * from follow"
      fields: [degree]
      nebula.fields: [degree]
      source: {
        field:src_player
      }
      target: {
        field:dst_player
      }
      batch: 256
      partition: 32
    }
    {
      name: serve
      type: {
        source: clickhouse
        sink: client
      }
      url:"jdbc:clickhouse://192.168.0.4:20044/basketballplayer?characterEncoding=UTF-8"
      user:"default"
      password:""
      numPartition:"5"
      sentence:"select * from serve"
      fields: [start_year,end_year]
      nebula.fields: [start_year,end_year]
      source: {
        field:playerid
      }
      target: {
        field:teamid
      }
      batch: 256
      partition: 32
    }
  ]
}

执行导入

上传配置文件和nebula-exchange-2.6.1.jarbuckets-nebula-spark-master:/tmp

./bin/spark-submit --master spark://master:7077 --class com.vesoft.nebula.exchange.Exchange  /tmp/nebula-exchange-2.6.1.jar  -c /tmp/clickhouse_application.conf
  • 填写所有 metad 地址报错,报错信息见问题描述
  • 填写指定 metad 地址, 成功,但是中文信息为?
    vertex-info-cn

其他信息

nebula-graph-issue-xsh.7z (1.7 MB)

注:使用的压缩软件为 7zip

nebula-graph-issue-xsh
|--- `images`: 截图信息
|--- `logs-0-before-load1`: 完成schema后备份
|--- `logs-1-after-load1`: 全填写导入报错失败后备份
|--- `logs-2-after-load2`: 填写报错信息后描述`metad`节点导入成功后备份
|--- `issue.md`: 问题记录
|--- `load1-info.txt`: 全填写导入控制台信息记录(报错)
|--- `load2-info.txt`: 填写报错信息后描述`metad`节点导入控制台信息记录(成功)
1 个赞
  1. metad0 识别不了,你可以在spark节点中执行telnet metad0 9559 ,肯定访问不了
  2. 中文问题:你看可以用spark shell 去读取一下clickhouse数据看读进来的是否就是正常的中文,其次可以在命令中加入 指定spark worker 文件编码的参数file.encoding 是utf-8。
1 个赞

问题 1 解决方法记录

根据 @nicole 回答 1,spark在执行Exchange导入时,请求连接的是 metad0 9559。显然需要把docker部署的sparknebula-graph放置于同一个网络。

在 spark 容器内,执行telnet metad0 9559

root@e4e8d6e543f4:/opt/bitnami/spark# telnet metad0 9559
telnet: could not resolve metad0/9559: Temporary failure in name resolution

修改nebula-graph 或者 sparkdocker-compose.yml文件,连接至同一个 networks 后, 执行telnet metad0 9559

root@9440bc008152:/opt/bitnami/spark# telnet metad0 9559
Trying 172.22.0.2...
Connected to metad0.
Escape character is '^]'.

修改 clickhouse_application.conf 配置全部地址

{
    # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口。
    graph:["192.168.0.4:9669", "192.168.0.4:63264", "192.168.0.4:63271"]
    meta:["192.168.0.4:63237", "192.168.0.4:63241", "192.168.0.4:63244"]
}

上传并进行导入

./bin/spark-submit --master spark://master:7077 --class com.vesoft.nebula.exchange.Exchange  /tmp/nebula-exchange-2.6.1.jar -c /tmp/clickhouse_application.conf

导入成功,问题1解决。

附录

spark 容器内下载安装 telnet方法

# 进入容器
# 使用 docker exec -it buckets-nebula-spark-worker-1 bash 进入会因为`权限不足`导致
#     E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
λ docker exec -it -u 0 buckets-nebula-spark-worker-1 bash

root@e4e8d6e543f4:/opt/bitnami/spark# apt-get update
Get:1 http://deb.debian.org/debian buster InRelease [122 kB]
Get:2 http://security.debian.org buster/updates InRelease [65.4 kB]
Get:3 http://security.debian.org buster/updates/main amd64 Packages [399 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 Packages [10.7 MB]
Fetched 11.3 MB in 5min 8s (36.8 kB/s)
Reading package lists... Done

root@9440bc008152:/opt/bitnami/spark# apt-get install -y telnet
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  netbase
The following NEW packages will be installed:
  netbase telnet
0 upgraded, 2 newly installed, 0 to remove and 28 not upgraded.
Need to get 89.8 kB of archives.
After this operation, 212 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 netbase all 5.6 [19.4 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 telnet amd64 0.17-41.2 [70.4 kB]
Fetched 89.8 kB in 1s (68.0 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package netbase.
(Reading database ... 6964 files and directories currently installed.)
Preparing to unpack .../archives/netbase_5.6_all.deb ...
Unpacking netbase (5.6) ...
Selecting previously unselected package telnet.
Preparing to unpack .../telnet_0.17-41.2_amd64.deb ...
Unpacking telnet (0.17-41.2) ...
Setting up netbase (5.6) ...
Setting up telnet (0.17-41.2) ...
update-alternatives: using /usr/bin/telnet.netkit to provide /usr/bin/telnet (telnet) in auto mode

问题二解决方法见回复 使用exchange-2.6.1从clickhouse导入数据至nebula报错 UnknownHostException以及中文显示乱码 - #8,来自 MrSaviorBill

1 个赞

感谢回答,问题1已经通过修改docker-compose.yml中的网络配置解决了。想问下spark 在通过 exchange 导入数据时为什么不是通过配置项中的地址发起请求, 而是通过 nebula-graph中配置的信息。我猜测一下:

  1. 按照配置文件记录的host:port列表,通过RPC请求时发现访问的节点不是写节点,然后通过访问类似注册中心职能的节点获取了写节点的host:port再发起请求,所以读取到的是 nebula-graph 中的地址节点信息。
    2.或者一开始就没有读取host:port列表,直接访问类似注册中心职能的节点获取了写节点的host:port再发起请求。
    想请教下是不是这样的。

因为之前没有使用过spark, 问题 2 的解决方法我还需要点时间。

再次感谢!

:thinking: 我尝试解答下哈,因为 Nicole 之前和我科普过,storage 的数据是通过访问 meta 来获得的,所以配置的是 meta 的地址。顺便。。你上面有个错别字,我给你编辑了下。

请问是不是可以这样理解:application.conf 中配置的 graphdmetad 地址只是用于创建与neubula-graph的一个连接,之后exchange内部逻辑使用的地址等参数都来源于metad中记录的信息。

我的理解是这样的,:thinking: 我找个研发来确认下。 @spw

问题 2 解决方法记录

查询编码格式:

# 进入 spark shell
I have no name!@30c585604392:/opt/bitnami/spark/bin$ spark-shell
# 获取 file.encoding
scala> System.getProperty("file.encoding")

原因:spark 编码格式不匹配

执行语句时添加参数:

./bin/spark-submit \
	--master spark://master:7077 \
	--conf spark.driver.extraJavaOptions=" -Dfile.encoding=utf-8 " \
	--conf spark.executor.extraJavaOptions=" -Dfile.encoding=utf-8 " \
	--class com.vesoft.nebula.exchange.Exchange  /tmp/nebula-exchange-2.6.1.jar \
	-c /tmp/clickhouse_application.conf

vertex-info-cn2

问题 2 解决!

感谢各位大佬解答。

1 个赞

不愧是模范生,优秀 !

快勾选自己的回复为解决方案,我刚编辑了下你问题一的解决方法

分两块:

  1. connector 访问 graph 和 meta ,是通过 application.conf 的配置信息来访问的。
  2. connector 访问 storaged,是通过 meta 获取的 space 具体的机器,然后访问的。这里 meta 起到了一个 storaged 的配置中心的作用。
1 个赞

理解了,感谢。
我还想咨询下 application.conf 文件格式是什么类型。
json不太一样,key 值没有双引号"",属性值之间没有分隔符,,也不是 yaml, ini, properties.

可能会用到需要自动生成导入配置文件的情况, 所以想了解一下,看看 pypi 上有没有现成的工具。

@steam 因为有大佬的解答,通过这些关键词可以一下子把问题的范围缩小,答案就容易得到了。


应该是这个,:thinking: 就是 .conf 文件格式

了解了,那我就用字符串拼接好了。

1 个赞

大赞,@MrSaviorBill 同学:+1:t2:,教科书式的提问和追问。补充一个,配置的格式是 hocon 不是 json 也不是 toml 哈哈哈,有了格式应该就可以找到相关库啦。

Ref: https://github.com/chimpler/pyhocon

1 个赞

多谢大佬,还给了库的链接,贴心 :+1: