一、Wormhole概述

 1、Wormhole是什么

8、Wormhole流处理平台_xml

 

 

 

8、Wormhole流处理平台_xml_02

 

 

 

 

2、为什么会有Wormhole

8、Wormhole流处理平台_数据_03

 

 

 

3、设计理念

8、Wormhole流处理平台_xml_04

 

 

 

8、Wormhole流处理平台_xml_05

 

 

 

4、主要特性

8、Wormhole流处理平台_xml_06

 

 

 

5、核心概念

参考:https://edp963.github.io/wormhole/concept.html

Namespace(命名空间)

Namespace是Wormhole定义的唯一定位数据系统上数据表的规范,由七部分组成。

[Datastore].[Datastore Instance].[Database].[Table].[Table Version].[Database Partition].[Table Partition]

  • Datastore 代表数据存储系统类型,如 Oracle,Mysql,Hbase,Elasticsearch,Kafka 等
  • Datastore Instance 代表数据存储系统物理地址别名
  • Database 代表 RDBS 中的数据库,Hbase 中的命名空间,Elasticsearch 中的索引,Kafka 中的主题
  • Table 代表 RDBS 中的数据表,Hbase 中的数据表,Elasticsearch 中的文档,Kafka 中的某主题下的数据
  • Table Version 代表Table 的表结构版本,一般情况下 Table Version 的值应随表结构的变化递增(目前Wormhole 中处理时用“*”匹配所有版本的数据)
  • Database Partition 代表 Database 的分区名称(目前 Wormhole 中处理时用“*”匹配所有分区的数据)
  • Table Partition 代表 Table 的分表名称(目前 Wormhole 中处理时用“*”匹配所有分表的数据)

例如:​​mysql.test.social.user.*.*.* kafka.test.social.user.*.*.*​

UMS(统一消息规范)

UMS 是 Wormhole 定义的消息规范(JSON 格式),UMS 试图抽象统一所有结构化消息,通过自身携带的结构化数据 Schema 信息,来实现一个物理 DAG 同时处理多个逻辑 DAG 的能力,也避免了和外部数据系统同步元数据的操作。

{
"protocol": {
"type": "data_increment_data"
},
"schema": {
"namespace": "kafka.kafka01.datatopic.user.*.*.*",
"fields": [
{
"name": "ums_id_",
"type": "long",
"nullable": false
},
{
"name": "ums_ts_",
"type": "datetime",
"nullable": false
},
{
"name": "ums_op_",
"type": "string",
"nullable": false
},
{
"name": "key",
"type": "int",
"nullable": false
},
{
"name": "value1",
"type": "string",
"nullable": true
},
{
"name": "value2",
"type": "long",
"nullable": false
}
]
},
"payload": [
{
"tuple": [ "1", "2016-04-11 12:23:34.345123", "i", "23", "aa", "45888" ]
},
{
"tuple": [ "2", "2016-04-11 15:23:34.345123", "u", "33", null, "43222" ]
},
{
"tuple": [ "3", "2016-04-11 16:23:34.345123", "d", "53", "cc", "73897" ]
}
]
}

 

protocol 代表消息协议

  • data_increment_data 代表增量数据
  • data_initial_data 代表全量数据
  • data_increment_heartbeat 代表增量心跳数据
  • data_increment_termination 代表增量数据结束

schema 代表消息来源及表结构信息

namespace 指定消息的来源,fields 指定表结构信息,其中 ​​ums_id_,ums_ts_,ums_op_​​ 三个字段是必需的三个系统字段,Wormhole 使用这三个字段实现幂等写数据的逻辑。

  • ums_id_: long 类型,用来唯一标识消息,须根据消息生成的顺序递增
  • ums_ts_: datetime 类型,每一条消息产生的时间
  • ums_op_: string 类型,指定每条消息生成的方式,值为 “i” 或 “u” 或 “d” ,分别代表新增,更新,删除操作

payload 代表数据本身

  • tuple:一个tuple对应一条消息

UMS_Extension (UMS 扩展格式)

除 UMS 格式外,Wormhole 支持 UMS_Extension(UMS扩展格式),用户可自定义数据格式,且支持嵌套结构。使用时须将 Kafka 消息的 key 设置为 data_increment_data.sourceNamespace,然后在 Wormhole 页面上粘贴数据样式简单配置即可。如 sourceNamespace 为 ​​kafka.kafka01.datatopic.user.*.*.*​​​,则 Kafka 消息的 key 须为 ​​data_increment_data.kafka.kafka01.datatopic.user.*.*.*​​。

若一个 sourceNamespace 的消息需要随机分配到多个 partition,消息的 key 可设置为data_increment_data.kafka.kafka01.datatopic.user.*.*.*...abc 或 data_increment_data.kafka.kafka01.datatopic.user.*.*.*...bcd,即在 sourceNamespace 后面添加“…”,之后可添加随机数或任意字符。

若 UMS_Extension 类型数据有增删改操作且需要幂等写入,也须配置 ums_id_,ums_ts_,ums_op_ 三个字段。具体配置方式请参考 Admin-Guide Namespace章节。

Stream

Stream 是在 Spark Streaming 上封装的一层计算框架,消费的数据源是 Kafka。Stream 作为 Wormhole 的流式计算引擎,匹配消息的 key,sourceNamespace 和其对应处理逻辑,可将数据以幂等的方式写入多种数据系统中。处理过程中 Stream 会反馈错误信息、心跳信息、处理数据量及延时等信息。

一个 Stream 可以处理多个 Namespace 及其处理逻辑,共享计算资源。

Flow

Flow 关注的是数据从哪来(sourceNamespace),到哪去(sinkNamespace),及中间的处理逻辑。

Flow 支持 SQL 配置,自定义UDF,自定义 Class,且可以关联其他 RDBS/Hbase/Phoenix/Redis/Es 等系统中的数据。

Flow 配置好后可以注册到 Stream,Stream 接收 Flow 指令后,根据指令中的 sourceNamespace,sinkNamespace 及业务逻辑处理数据。

Job

Job 相当于 Spark Job,其数据源是 HdfsLog Stream 备份在 Hdfs 上的数据。Stream/Flow/Job 组合可实现 Lambda 架构和 Kappa 架构。

Kafka 中数据有一定的生命周期,可通过 Stream 将 Kafka 中数据备份到 Hdfs 上。后续需要从某个时间节点重新计算或者补充某个时间段的数据,可通过 Job 读取 Hdfs上 的备份数据,配置与 Flow 相同的处理逻辑,将数据写入目标表。

注意:目前 UMS_Extension 类型数据只支持通过 Stream 将 Kafak 中数据备份到 Hdfs 上,Job 还不支持读取 UMS_Extension 类型数据。

 

 

二、wormhole编译

1、克隆源代码

 

git clone https://github.com/edp963/wormhole.git
cd wormhole

 

2、切换tag

 

git checkout 0.6.2

 

 

 

 

我个人是直接下载0.6.2版本的代码下来

8、Wormhole流处理平台_kafka_07

 

 

3、导入idea,修改pom.xml

修改以下部分:

<!--    <distributionManagement>-->
<!-- <repository>-->
<!-- <id>dist-nexus</id>-->
<!-- <url>${release.url}</url>-->
<!-- </repository>-->
<!-- </distributionManagement>-->

<!-- common repositories -->
<!-- <repositories>-->
<!-- <repository>-->
<!-- <id>alimaven</id>-->
<!-- <url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
<!-- </repository>-->
<!-- <!–<repository>–>-->
<!-- <!–<id>hortonworks</id>–>-->
<!-- <!–<url>http://repo.hortonworks.com/content/repositories/releases/</url>–>-->
<!-- <!–</repository>–>-->
<!-- <repository>-->
<!-- <id>conjars</id>-->
<!-- <url>http://conjars.org/repo/</url>-->
<!-- </repository>-->
<!-- <repository>-->
<!-- <id>creditease</id>-->
<!-- <url>${public.url}</url>-->
<!-- </repository>-->
<!-- </repositories>-->

 

4、新增kafka2.0.0支持

8、Wormhole流处理平台_kafka_08

 

 

8、Wormhole流处理平台_kafka_09

 

 

8、Wormhole流处理平台_数据_10

 

 

8、Wormhole流处理平台_数据_11

 

 

8、Wormhole流处理平台_数据_12

 

 

8、Wormhole流处理平台_数据_13

 

 

 注册新加模块
修改最外层的pom.xml

<modules>
<module>ums</module>
<module>kafkatool/kafka08</module>
<module>kafkatool/kafka010</module>
<module>kafkatool/kafka010-2</module>
<module>kafkatool/kafka200</module>
<module>util</module>
<module>externalclient/zookeeper</module>
<module>externalclient/hadoop</module>
<module>dbdriver/dbpool</module>
<module>dbdriver/sql4es5</module>
<module>dbdriver/sql4es2</module>
<module>dbdriver/redispool</module>
<module>dbdriver/kuduconnection</module>
<module>dbdriver/hbaseconnection</module>
<!--<module>dbdriver/phoenix-jdbc</module>-->
<module>interface/sparkxinterface</module>
<module>interface/flinkxinterface</module>
<module>interface/publicinterface</module>
<module>sinks</module>
<module>common</module>
<module>swifts</module>
<module>reporter</module>
<module>flinkx</module>
<module>sparkextension/spark_extension_2_2</module>
<module>sparkextension/spark_extension_2_3</module>
<module>sparkextension/spark_extension_2_4</module>
<module>sparkx</module>
<!--<module>rider/common/haservice</module>-->
<module>rider/rider-server</module>
<!--<module>rider/mad-server</module>-->
<module>rider/rider-assembly</module>
</modules>

 

 

修改新模块pom文件
修改本模块的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>wormhole-parent</artifactId>
<groupId>edp.wormhole</groupId>
<version>0.6.2</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>wormhole-kafka-200</artifactId>
<packaging>jar</packaging>
<properties>
<main.basedir>${project.parent.basedir}</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>edp.wormhole</groupId>
<artifactId>wormhole-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.11</artifactId>
<version>2.0.0</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.0.0</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

 

 

复制代码

把kafka010-2的源代码目录全部拷贝过来,并设置为source root目录:

8、Wormhole流处理平台_kafka_14

 

 

修改源代码
修改edp.wormhole.kafka.WormholeGetOffsetUtils:

#删掉如下三行
import kafka.api.{OffsetFetchRequest, OffsetFetchResponse}
import kafka.common.TopicAndPartition
import kafka.network.BlockingChannel

 

5、适配HDP3.1
修改最外层pom.xml以适配HDP3.1:

<!--        <kafka.version>0.10.2.2</kafka.version>-->
<!-- <hadoop.version>2.7.1</hadoop.version>-->
<!-- <hbase.version>1.1.3</hbase.version>-->
<!-- <hive.version>1.2.1</hive.version>-->
<kafka.version>2.0.0</kafka.version>
<hadoop.version>3.1.1</hadoop.version>
<hbase.version>2.0.2</hbase.version>
<hive.version>3.1.0</hive.version>
<flink.version>1.7.2</flink.version>
<zookeeper.version>3.4.6</zookeeper.version>
<jackson.version>2.6.5</jackson.version>
<kudu.version>1.8.0</kudu.version>
<clickhouse.version>0.1.54</clickhouse.version>
<fastjson.version>1.2.58</fastjson.version>
<!-- <spark.extension.version>2.2</spark.extension.version>-->
<spark.extension.version>2.3</spark.extension.version>


wormhole 0.6.2及之后版本增加spark不同版本兼容,已适配spark2.2/2.3/2.4,默认支持的是spark2.2,其他版本需要用户修改代码中的spark版本号进行适配。
修改启动stream时调用的sparkx jar包名称,即edp.rider.common.RiderConfig.scala中wormholeJarPath 和wormholeKafka08JarPath变量:

 

8、Wormhole流处理平台_kafka_15

lazy val wormholeJarPath = getStringConfig("spark.wormhole.jar.path", s"${RiderConfig.riderRootPath}/app/wormhole-ums_1.3-sparkx_2.3-0.6.2-jar-with-dependencies.jar")
lazy val wormholeKafka08JarPath = getStringConfig("spark.wormhole.kafka08.jar.path", s"${RiderConfig.riderRootPath}/app/wormhole-ums_1.3-sparkx_2.3-0.6.2-jar-with-dependencies-kafka08.jar")

 

6、其他bug修复

fix wh feedback mysql bug
rider/conf/wormhole.sql:

#483行新增
alter table `feedback_flow_stats` modify column `batch_id` varchar(100);
alter table `feedback_flow_stats` modify column `topics` varchar(2000) NOT NULL;

 

8、Wormhole流处理平台_数据_16

 

 

 

rider/rider-server/src/main/scala/edp/rider/rest/persistence/entities/MonitorInfo.scala:

//val intervalSwiftsToSink: Rep[Long] = column[Long]("interval_swifts_sink")
//val intervalSinkToDone: Rep[Long] = column[Long]("interval_sink_done")
val intervalSwiftsToSink: Rep[Long] = column[Long]("interval_swifts_to_sink")
val intervalSinkToDone: Rep[Long] = column[Long]("interval_sink_to_done")

 

 

8、Wormhole流处理平台_kafka_17

 

 

 

 

修复Phoenix sink⽆无法建⽴立连接的bug:

8、Wormhole流处理平台_kafka_18

 

 

 修复方法 edp.rider.rest.util.NamespaceUtils

8、Wormhole流处理平台_kafka_19

//      case "mysql" | "postgresql" | "phoenix" | "vertica" | "clickhouse"=>
// db.config match {
// case Some(conf) =>
// if (conf != "") {
// val confStr =
// (keyEqualValuePattern.toString.r findAllIn conf.split(",").mkString("&")).toList.mkString("&")
// s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}?$confStr"
// } else s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}"
// case None => s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}"
// }
case "mysql" | "postgresql" | "vertica" | "clickhouse"=>
db.config match {
case Some(conf) =>
if (conf != "") {
val confStr =
(keyEqualValuePattern.toString.r findAllIn conf.split(",").mkString("&")).toList.mkString("&")
s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}?$confStr"
} else s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}"
case None =>s"jdbc:${instance.nsSys}://${instance.connUrl}/${db.nsDatabase}"
}

 

 

 

修复Phoenix sink⽆无法正确找到table的bug
现象:明明对应的表存在,仍然报如下错误:

org.apache.phoenix.schema.TableNotFoundException: ERROR 1012 (42M03): Table
undefined. tableName=sca.USER_INFO

 

修复方法: edp.wormhole.sinks.phoenixsink.PhoenixProcess 第57、58行:

//    val sql = s"UPSERT INTO "+ "\""+tableName+ "\""+s" ($columnNames,"+ "\""+s"${UmsSysField.ACTIVE.toString.toUpperCase}"+"\""+") VALUES " +
// (1 to baseFieldNames.size + 1).map(_ => "?").mkString("(", ",", ")")
val sql = s"UPSERT INTO "+ ""+tableName+ ""+s" ($columnNames,"+ "\""+s"${UmsSysField.ACTIVE.toString.toUpperCase}"+"\""+") VALUES " +
(1 to baseFieldNames.size + 1).map(_ => "?").mkString("(", ",", ")")

8、Wormhole流处理平台_数据_20

 

 

7、编译源代码

mvn clean package -DskipTests -Pwormhole

 

 

8、Wormhole流处理平台_kafka_21

 

编译完成后,安装包在target目录下:

8、Wormhole流处理平台_kafka_22

 

 三、Wormhole部署

 1、环境准备

 

8、Wormhole流处理平台_数据_23

 

 

 2、启动依赖服务

 

8、Wormhole流处理平台_数据_24

 

 

 3、部署规划

 

8、Wormhole流处理平台_xml_25

 

 

 4、配置

 上传安装包:

将前面编译好的安装包wormhole-0.6.2.tar.gz上传到node01的/home/hadoop/app目录下。

cd /home/hadoop/app
tar -xvf wormhole-0.6.2.tar.gz
ln -s wormhole-0.6.2 wormhole

 

 

配置环境变量:

vim /etc/profile

 

添加以下内容:

export WORMHOLE_HOME=/home/hadoop/app/wormhole
export PATH=$WORMHOLE_HOME/bin:$PATH

 

保存退出,使环境变量生效:

source /etc/profile

 

配置rider-server

vim $WORMHOLE_HOME/conf/application.conf

 

配置内容如下:

akka.http.server.request-timeout = 120s

wormholeServer {
cluster.id = "" #optional global uuid
host = "0.0.0.0"
port = 8989
ui.default.language = "Chinese"
token.timeout = 1
token.secret.key = "iytr174395lclkb?lgj~8u;[=L:ljg"
admin.username = "admin" #default admin user name
admin.password = "admin" #default admin user password
refreshInterval = "5" #refresh yarn to update stream status interval(second)
}

mysql = {
driver = "slick.driver.MySQLDriver$"
db = {
driver = "com.mysql.jdbc.Driver"
user = "wormhole"
password = "wormhole"
url = "jdbc:mysql://node01:3306/wormhole?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
numThreads = 4
minConnections = 4
maxConnections = 10
connectionTimeout = 3000
}
}

ldap = {
enabled = false
user = ""
pwd = ""
url = ""
dc = ""
read.timeout = 3000
read.timeout = 5000
connect = {
timeout = 5000
pool = true
}
}

spark = {
wormholeServer.user = "hadoop"
wormholeServer.ssh.port = 22
spark.home = "/usr/hdp/current/spark2-client"
yarn.queue.name = "default" #WormholeServer submit spark streaming/job queue
wormhole.hdfs.root.path = "hdfs://node01:8082/wormhole" #WormholeServer hdfslog data default hdfs root path
yarn.rm1.http.url = "node01:8088" #Yarn ActiveResourceManager address
yarn.rm2.http.url = "node01:8088" #Yarn StandbyResourceManager address
#yarn.web-proxy.port = 8888 #Yarn web proxy port, just set if yarn service set yarn.web-proxy.address config
}

flink = {
home = "/usr/local/flink"
yarn.queue.name = "default"
checkpoint.enable = false
checkpoint.interval = 60000
stateBackend = "hdfs://nn1/flink-checkpoints"
feedback = {
enabled = false
state.count = 100
interval = 30
}
}

zookeeper = {
connection.url = "node01:2181" #WormholeServer stream and flow interaction channel
wormhole.root.path = "/wormhole" #zookeeper
}

kafka = {
brokers.url = "node02:6667" #WormholeServer feedback data store
zookeeper.url = "node01:2181"
topic.refactor = 3
using.cluster.suffix = false #if true, _${cluster.id} will be concatenated to consumer.feedback.topic
consumer = {
feedback.topic = "wormhole_feedback"
poll-interval = 1m
poll-timeout = 1m
stop-timeout = 30s
close-timeout = 20s
commit-timeout = 70s
wakeup-timeout = 1h
max-wakeups = 10000
session.timeout.ms = 120000
heartbeat.interval.ms = 50000
max.poll.records = 1000
request.timeout.ms = 130000
max.partition.fetch.bytes = 4194304
}
}

#kerberos = {
# kafka.enabled = false
# keytab = ""
# rider.java.security.auth.login.config = ""
# spark.java.security.auth.login.config = ""
# java.security.krb5.conf = ""
#}

# choose monitor method among ES、MYSQL
monitor = {
database.type = "MYSQL"
}

#Wormhole feedback data store, if doesn't want to config, you will not see wormhole processing delay and throughput
#if not set, please comment it
#elasticSearch.http = {
# url = "http://localhost:9200"
# user = ""
# password = ""
#}


#delete feedback history data on time
maintenance = {
mysql.feedback.remain.maxDays = 7
elasticSearch.feedback.remain.maxDays = 7
}


#Dbus integration, support serveral DBus services, if not set, please comment it
#dbus = {
# api = [
# {
# login = {
# url = "http://localhost:8080/keeper/login"
# email = ""
# password = ""
# }
# synchronization.namespace.url = "http://localhost:8080/keeper/tables/riderSearch"
# }
# ]
#}

 

 Feedback State 存储位置配置:

wormhole在0.6版本之前的feedback state默认存储在ES中,在0.6版本之后,将支持用户根据需求在ES与MySQL中间选择合适的存储库进行数据存储。

如果需要将存储位置由ES迁往MySQL,可以参照下面的步骤进行配置。通过配置monitor.database.type选择存储位置

monitor.database.type = "MYSQL" #存储到mysql中
monitor.database.type = "ES" #存储到ES中

 

当选择存储到mysql时,需要在wormhole/riderlconf/wormhole.sql新建feedback_flow_stats 表,并在wormhole配置的数据库中执行该文件,从而在数据库中建立feedback_flow_stats表

注意:我们前面已经配置为MYSQL了,这里不用动,表会自动创建的。


创建数据库:

在node01上连接mysql:

mysql -u root -p

 

然后在Mysql命令行执行如下操作:

mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.01 sec)

mysql> set global validate_password_mixed_case_count=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_number_count=3;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_special_char_count=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=3;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE DATABASE IF NOT EXISTS wormhole DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE USER 'wormhole'@'%' IDENTIFIED BY 'wormhole';
Query OK, 0 rows affected (0.06 sec)

mysql> GRANT ALL ON wormhole.* TO 'wormhole'@'%';
Query OK, 0 rows affected (0.02 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

 

 

5、启停

启动:

cd $WORMHOLE_HOME/bin
chmod u+x ./*
$WORMHOLE_HOME/bin/start.sh

 

8、Wormhole流处理平台_kafka_26

 

 

 检查

第一次启动之后需要检查一下相关的Topic、表是否创建好:

启动时自动创建 table, kafka topic,elasticsearch index, grafana datasource 创建kafka topic时,有时候会因环境原因失败,须手动创建
topic name: wormhole_feedback partitions: 4
topic nameғ wormhole_heartbeat partitions: 1

# 创建或修改topic命令
cd /usr/hdp/current/kafka-broker/bin/
./kafka-topics.sh --zookeeper node01:2181 --create --topic wormhole_feedback --replication-factor 1 --partitions 4
./kafka-topics.sh --zookeeper node01:2181 --create --topic wormhole_heartbeat --replication-factor 1 --partitions 1
./kafka-topics.sh --zookeeper node01:2181 --alter --topic wormhole_feedback --partitions 4
./kafka-topics.sh --zookeeper node01:2181 --alter --topic wormhole_heartbeat--partitions 1

 

 

查看Mysql表

8、Wormhole流处理平台_kafka_27

 

 

 

查看kafka topic列表

8、Wormhole流处理平台_数据_28

 

 

 

我现在手动把wormhole_heartbeat topic创建上

 

8、Wormhole流处理平台_xml_29

 

 

 

停止

因为停止脚本通过lsof命令去查找pid的,所以先安装下lsof(一次性操作):

sudo yum -y install lsof

 

停止命令如下:

$WORMHOLE_HOME/bin/stop.sh

 

重启:

$WORMHOLE_HOME/bin/restart.sh

 

 

6、访问Wormhole

访问http://node01:8989即可试用Wormhole,可使用admin类型用户登录,默认用户名,密码见application.conf中配置,我们设置的是admin/admin。

8、Wormhole流处理平台_xml_30

 

 

8、Wormhole流处理平台_kafka_31

 能看到上述界面wormhole安装基本是没有问题的。

 

 四、快速入门

 管理员操作:

创建普通用户

admin/admin登录Wormhole,并按照下图操作切换到用户管理界面︰

8、Wormhole流处理平台_kafka_32

 

 

 

在用户管理界面,我们能看到有一个用户就是管理员admin,点击"新建"按钮:

8、Wormhole流处理平台_xml_33

 

 

在弹出的窗口中填写相关用户信息,用户类型选择user,点击保存即可,见下图:

8、Wormhole流处理平台_kafka_34

 

 为了方便,我把密码设置成666666

 

1、创建Source Namespace

8、Wormhole流处理平台_数据_35

 

 

创建Instance

8、Wormhole流处理平台_数据_36

 

 

8、Wormhole流处理平台_kafka_37

 

 

8、Wormhole流处理平台_数据_38

 

 保存之后能看到已经添加成功了:

8、Wormhole流处理平台_xml_39

 

 

 创建Database

8、Wormhole流处理平台_xml_40

 

 

 

8、Wormhole流处理平台_数据_41

 

 点击新建Database页面:

8、Wormhole流处理平台_数据_42

 

 

8、Wormhole流处理平台_kafka_43

 

 

8、Wormhole流处理平台_xml_44

 

 保存之后就能看见:

8、Wormhole流处理平台_xml_45

 

 

创建Namespace

有了前面两步创建的Instance和DataBase,接下来就可以轻松创建NameSpace了。进入Namespace列表页:

 

8、Wormhole流处理平台_kafka_46

 

 点击“新建”进入新建Namespace页面:

8、Wormhole流处理平台_xml_47

 

 

8、Wormhole流处理平台_kafka_48

 

8、Wormhole流处理平台_xml_49

 

 保存之后:

8、Wormhole流处理平台_xml_50

 

 

 2、创建source topic与模拟数据

 kafka集群中创建topic: test_source,并生产测试数据。

 创建topic

cd /usr/hdp/current/kafka-broker/bin
./kafka-topics.sh --zookeeper node01:2181 --create --topic test_source --replication-factor 1 --partitions 1

8、Wormhole流处理平台_数据_51

 

生成测试数据:

8、Wormhole流处理平台_kafka_52

data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*

 

 

生成测试数据命令如下:

cd /usr/hdp/current/kafka-broker/bin
./kafka-console-producer.sh --broker-list node02:6667 --topic test_source --property "parse.key=true" --property "key.separator=@@@"

data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*@@@{"id": 1,"name": "test", "phone":"18074546423", "city": "Beijing", "time": "2017-12-2210:00:00"}
data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*@@@{"id": 2,"name": "test1", "phone":"18074546423", "city": "Shanghai", "time": "2017-12-22 10:00:00"}
data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*@@@{"id": 3,"name": "test2", "phone":"18074546423", "city": "Wuhan", "time": "2017-12-22 10:00:00"}
data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*@@@{"id": 4,"name": "test4", "phone":"18074546423", "city": "Wuhan", "time": "2017-12-22 10:00:00"}

 

 

3、配置Source Namespace Schema

 在前面几步我们创建了Source Namespace,接下来需要配置下他们的Schema。

进入Namespace列表

8、Wormhole流处理平台_kafka_53

 

 

 进入souce schema配置页面

8、Wormhole流处理平台_kafka_54

 

 

 配置source schema

 

8、Wormhole流处理平台_kafka_55

{
"id": 4,
"name": "test4",
"phone":"18074546423",
"city": "Wuhan",
"time":"2017-12-22 10:00:00"
}

 

 4、创建Sink Namespace 

 

8、Wormhole流处理平台_xml_56

 

 

 创建Instance

8、Wormhole流处理平台_xml_57

 

 

8、Wormhole流处理平台_数据_58

 

8、Wormhole流处理平台_数据_59

 

 

创建Database

8、Wormhole流处理平台_数据_60

 

 

8、Wormhole流处理平台_xml_61

useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true

 

8、Wormhole流处理平台_kafka_62

 

 

创建Namespace

8、Wormhole流处理平台_kafka_63

 

 

8、Wormhole流处理平台_xml_64

 

8、Wormhole流处理平台_数据_65

 

 

5、创建Lookup Namespace

Look Namespace跟Source Namespace也是一样的套路,只不过按照需求咱们的Loop up的Datasys是MySQL。

 

创建Instance

复用上一步创建的hdp-mysql。

 

创建Database

 

8、Wormhole流处理平台_xml_66

 

 

8、Wormhole流处理平台_数据_67

useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&noAccessToProcedureBodies=true&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false

 

8、Wormhole流处理平台_xml_68

 

 

创建Namespace

8、Wormhole流处理平台_数据_69

 

 

 

8、Wormhole流处理平台_xml_70

 

 

8、Wormhole流处理平台_数据_71

 

 

6、创建UDF
UDF为可选项,可以省略该步骤,只有当我们现有的处理逻辑不够用时,才会创建UDF。

7、创建Project并授权

截止当前,我们已经创建好相关Namespace。接下来的操作就可以交给业务部门的普通用户自己来操作了,为了便于管理Wormhole提出了Project的概念。

 

创建Project

切换到Project列表并点击“新建项目”:

8、Wormhole流处理平台_kafka_72

 

 

 

按照下图操作:

8、Wormhole流处理平台_kafka_73

 

 注意:前端有个小bug,添加王project没有自动跳转,直接刷新页面即可。

8、Wormhole流处理平台_数据_74

 

 

普通用户操作

Wormhole支持Spark和Flink两种流式处理引擎,这里先介绍Spark Stream/Flow的使用流程。

1、Spark Stream/Flow使用流程
进入项目视图

我这里用之前创建的普通用户登录, 用户名: gong@gym.com  密码:666666   登录Wormhole

8、Wormhole流处理平台_xml_75

 

点击项目卡片,进入项目视图:

8、Wormhole流处理平台_kafka_76

 

 

2、创建Stream

进入Stream列表:

8、Wormhole流处理平台_kafka_77

 

 

 添加Stream:

8、Wormhole流处理平台_kafka_78

 

 

 配置Stream资源:

8、Wormhole流处理平台_数据_79

 

 

 添加完之后就能在列表中看见了:

8、Wormhole流处理平台_数据_80

 注意:Stream名字被自动加上了wormhole前缀。

 

3、创建Flow

选择Spark Stream 

 

8、Wormhole流处理平台_kafka_81

 

 

选择数据源(source):

8、Wormhole流处理平台_xml_82

 

 

选择目标(sink)

配置sink的基本信息:

8、Wormhole流处理平台_xml_83

 

 

sink高级配置:

8、Wormhole流处理平台_数据_84

 

注意:这里配置的是Sink类型,因为在前面Source Namespace 中数据只配置了“ums_ts_”系统字段,"mutation_type”只能设置为“i',即"insert only"。

 保存之后点击下一步即可:

8、Wormhole流处理平台_数据_85

 

 

 

配置转换逻辑

8、Wormhole流处理平台_数据_86

 

 

 目前Transformation支持 LookupSQL、Spark SQL等类型:

8、Wormhole流处理平台_数据_87

 

 

 

配置lookup SQL

我们直接采用Lookup SQL,配置如下:

8、Wormhole流处理平台_kafka_88

select id as id1,cardBank from userCard where (id) in (kafka.hdpkafka.test_source.test_table.id);

 

保存之后:

8、Wormhole流处理平台_kafka_89

 按照上图操作,点击加号再添加一个Spark SQL 类型的转换逻辑来过滤字段:

 

8、Wormhole流处理平台_xml_90

select id,name,cardBank,phone,city from test_table;

 保存之后点击下一步:

8、Wormhole流处理平台_xml_91

 

 

 最后提交:

8、Wormhole流处理平台_数据_92

 

 

 最后就能看见了:

8、Wormhole流处理平台_kafka_93

 

 

 

4、创建Lookup Table/Sink Table

在node01节点上登录Mysql:

mysql -u root -p

 

 

Lookup Table:

CREATE DATABASE IF NOT EXISTS lookup DEFAULT CHARSET utf8 COLLATE utf8_unicode_ci;
use lookup;
CREATE TABLE IF NOT EXISTS `userCard` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`cardBank` VARCHAR(200) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE = InnoDB CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO userCard (id, cardBank) VALUES (1, "CMB");
INSERT INTO userCard (id, cardBank) VALUES (2, "CITIC");
INSERT INTO userCard (id, cardBank) VALUES (3, "ABC");
INSERT INTO userCard (id, cardBank) VALUES (4, "BOC");
INSERT INTO userCard (id, cardBank) VALUES (5, "CEB");
INSERT INTO userCard (id, cardBank) VALUES (6, "CCB");
INSERT INTO userCard (id, cardBank) VALUES (7, "ICBC");
INSERT INTO userCard (id, cardBank) VALUES (8, "CMBC");
INSERT INTO userCard (id, cardBank) VALUES (9, "SPDB");
INSERT INTO userCard (id, cardBank) VALUES (10, "GDB");

 

 

sink Table:

CREATE DATABASE IF NOT EXISTS testdb DEFAULT CHARSET utf8 COLLATE utf8_unicode_ci;
use testdb;
CREATE TABLE IF NOT EXISTS `user` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200) NOT NULL,
`cardBank` VARCHAR(200) NOT NULL,
`phone` VARCHAR(200) NOT NULL,
`city` VARCHAR(200) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE = InnoDB CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

 

5、启动Flow

8、Wormhole流处理平台_kafka_94

 

 

 

8、Wormhole流处理平台_kafka_95

注意:Flow suspending状态代表挂起状态,标识Flow信息已注册到Stream中,Stream目前处于非 running状态。Stream状态正常后Flow状态会自动切换到running或failed状态

 

6、启动Stream

8、Wormhole流处理平台_kafka_96

 

 启动时需要设置offset:

 

8、Wormhole流处理平台_xml_97

 

奈何我一直显示资源不足,可能真的因为个人的电脑不给力了,跑不动了。我也尝试个虚拟机加大内存,好像并没有什么用

查看日志

8、Wormhole流处理平台_xml_98

 

 

如果大家不存在这个问题,启动完stream后,就像前面的  创建source topic 与模拟数据   这一步生成一些模拟数据

登录kafka里面插入一些数据,

参考命令:

[root@hadoop002 bin]# ./kafka-console-producer.sh --broker-list hadoop002:6667 --topic test_source --property "parse.key=true" --property "key.separator=@@@"

>data_increment_data.kafka.hdp-kafka.test_source.test_table.*.*.*@@@{"id": 2, "name": "test1", "phone":"18074546423", "city": "Shanghai", "time": "2017-12-22 10:00:00"}

 

最后登录mysql检查数据是否过来:

mysql -u root -p

select * from testdb.user;