Apache Druid 本地 debug 环境搭建

说在前面

最近在研究 Apache Druid 的原理,在不 debug 的情况下已经无法再进一步深入了,因此想在本地搭一套调试环境,但网上可用的资料很少,只能自己摸索,在这期间走过不少弯路,这里做个记录,希望也能给后来的人一些提示与帮助。


安装部署

1.端口列表

以下是 Druid 默认的端口列表,注意是否和本地其他服务是否有端口冲突,如果有端口被占用会显示启动失败

Role Port Description
Coordinator 8081 管理集群上的数据可用性
Historical 8083 存储/查询 历史数据
Broker 8082 处理来自外部 client 的请求
Overload 8090 处理数据 ingestion 的负载
MiddleManager 8091 负责数据的 ingestion
Router 8888 将请求路由到 Brokers/Coordinators/Overloads

2.源代码下载

Apache Druid 主要是方便我们按照自己的需求按模块进行代码 debug,了解其 query 和 ingest 原理。


3.安装包下载

官网安装包下载:download 。我这里下载的是 0.22.1 版本,由于 Druid 运行依赖的组件很多,一个一个启动繁琐不说,还要安装不少依赖项。这个安装包中有封装好的 bin 文件,无需 docker 也可以一键启动所有组件。基于此,我们可以通过该安装包以及源代码来 debug 我们想要了解的组件。

\color{#ea4335}{举个例子} 我想要 debug broker 组件,于是:

安装包 - broker + 源代码启动 broker = 完整的 druid 环境

安装包下载完成后解压:

tar -zxvf apache-druid-0.22.1-bin.tar.gz


4.single-server 配置参考

Scale Required resources
nano-quickstart 1 CPU,4GB RAM
micro-quickstart 4 CPU,16GB RAM
small 8 CPU,64GB RAM
medium 16 CPU,128GB RAM
large 32 CPU,256GB RAM
xlarge 64CPU,512GB RAM
  • 启动命令: ./apache-druid-0.22.1/bin/start-nano-quickstart
  • 启动配置:./apache-druid-0.22.1/conf/supervise/single-server/nano-quickstart.conf
:verify bin/verify-java
:verify bin/verify-default-ports
:kill-timeout 10

!p10 zk bin/run-zk conf
coordinator-overlord bin/run-druid coordinator-overlord conf/druid/single-server/nano-quickstart
# 这里我们注释掉 broker,改为使用源代码启动
#broker bin/run-druid broker conf/druid/single-server/nano-quickstart
router bin/run-druid router conf/druid/single-server/nano-quickstart
historical bin/run-druid historical conf/druid/single-server/nano-quickstart
!p90 middleManager bin/run-druid middleManager conf/druid/single-server/nano-quickstart

由于我本地机器资源有限,这里以 nano-quickstart 为例,其他的同理,都在上述目录下,不再赘述


5.使用安装包其他其他服务

直接执行上述的 bin 文件,能够得到下图输出,可以看到其中是缺少 broker 的,接下来我们来编译源代码


nano-quickstart.png

6. 源代码编译

第一个坑,将 代码 clone 到本地后是 \color{red}{无法直接启动} 的,要进行一些编译与配置:

error.png

如上图所示,Parser 类依赖的 ExprLexer 和 ExprParser 类在整个项目中都找不到,实际的代码需要通过 ANTLR 编译 Expr.g4 文件生成。

g4.png

ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。 它被广泛用于构建语言、工具和框架。ANTLR 根据语法定义生成解析器,解析器可以构建和遍历解析树。

所有编程语言的语法,都可以用ANTLR来定义。ANTLR提供了大量的官方 grammar 示例,包含了各种常见语言,比如Java、SQL、Javascript、PHP等等。

Twitter 使用 ANTLR 进行语法分析,每天处理超过20亿次查询;Hadoop 生态系统中的 Hive、Pig、数据仓库和分析系统所使用的语言都用到了 ANTLR;Lex Machina 将 ANTLR 用于分析法律文本;Oracle 在 SQL 开发者 IDE 和迁移工具中使用了 ANTLR;NetBeans 的 IDE 使用 ANTLR 来解析 C++;Hibernate 对象-关系映射框架(ORM)使用 ANTLR 来处理 HQL 语言。

6.1 IDEA 安装 ANTLR v4 grammar plugin 插件

ANTLR.png

安装完成后我们直接来编译 Expr.g4 文件,右键 -> Generate ANTLR Recognizer


compile.png

接下来不出意外的话马上就要出意外了,果然编译开始报错了hhhhh,如下所示:


compile_error.png

这是因为文件中有一些转义字符报错,需要对 Expr.g4 文件进行修改,以下是我修改过的文件:
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

grammar Expr;

start : expr EOF;

expr : NULL                                                         # null
     | ('-'|'!') expr                                               # unaryOpExpr
     |<assoc=right> expr '^' expr                                   # powOpExpr
     | expr ('*'|'/'|'%') expr                                      # mulDivModuloExpr
     | expr ('+'|'-') expr                                          # addSubExpr
     | expr ('<'|'<='|'>'|'>='|'=='|'!=') expr                      # logicalOpExpr
     | expr ('&&'|'||') expr                                        # logicalAndOrExpr
     | '(' expr ')'                                                 # nestedExpr
     | IDENTIFIER '(' lambda ',' fnArgs ')'                         # applyFunctionExpr
     | IDENTIFIER '(' fnArgs? ')'                                   # functionExpr
     | IDENTIFIER                                                   # identifierExpr
     | DOUBLE                                                       # doubleExpr
     | LONG                                                         # longExpr
     | STRING                                                       # string
     | '[' (stringElement (',' stringElement)*)? ']'                # stringArray
     | '[' longElement (',' longElement)*']'                        # longArray
     | '<LONG>' '[' (numericElement (',' numericElement)*)? ']'     # explicitLongArray
     | '<DOUBLE>'? '[' (numericElement (',' numericElement)*)? ']'  # doubleArray
     | '<STRING>' '[' (literalElement (',' literalElement)*)? ']'   # explicitStringArray
     ;

lambda : (IDENTIFIER | '(' ')' | '(' IDENTIFIER (',' IDENTIFIER)* ')') '->' expr
       ;

fnArgs : expr (',' expr)*                                           # functionArgs
       ;

stringElement : (STRING | NULL);

longElement : (LONG | NULL);

numericElement : (LONG | DOUBLE | NULL);

literalElement : (STRING | LONG | DOUBLE | NULL);

NULL : 'null';
LONG : [0-9]+;
EXP: [eE] [-]? LONG;
// DOUBLE provides partial support for java double format
// see: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-
DOUBLE : 'NaN' | 'Infinity' | (LONG '.' LONG?) | (LONG EXP) | (LONG '.' LONG? EXP);
IDENTIFIER : [_$a-zA-Z][_$a-zA-Z0-9]* | '"' (ESC | ~ ["])* '"';
WS : [ \t\r\n]+ -> skip ;

STRING : '\'' (ESC | ~ ['])* '\'';
fragment ESC : '\\' (['"\\/bfnrt] | UNICODE) ;
fragment UNICODE : 'u' HEX HEX HEX HEX ;
fragment HEX : [0-9a-fA-F] ;

MINUS : '-' ;
NOT : '!' ;
POW : '^' ;
MUL : '*' ;
DIV : '/' ;
MODULO : '%' ;
PLUS : '+' ;
LT : '<' ;
LEQ : '<=' ;
GT : '>' ;
GEQ : '>=' ;
EQ : '==' ;
NEQ : '!=' ;
AND : '&&' ;
OR : '||' ;

接着再次 右键 -> Generate ANTLR Recognizer,发现在 core/gen 目录下生成了一些类:


generation.png

把这些类全部 copy 到 math.expr.antlr 目录下,项目报错就消失了


directory.png

7.debug 配置

可以先看下官方提供的 idea 配置,懒得看也没关系,看下面的配置就行。
首先一定要在 configuration 中打开这个 Add VM options 配置,在 debug 时组件的配置都通过这个来进行

idebug_config.png

以下是我的 broker 配置:

  • vm options
 -server -Ddruid.service=druid/broker -Xms512m -Xmx512m -XX:MaxDirectMemorySize=400m -XX:+ExitOnOutOfMemoryError -XX:+UseG1GC -Duser.timezone=UTC -Dfile.encoding=UTF-8 -Djava.io.tmpdir=var/tmp -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Ddruid.extensions.loadList="[]" -Ddruid.plaintextPort=8082
#可根据需要变更
  • main class
org.apache.druid.cli.Main
# 固定配置
  • Program arguments
server broker
# 固定写法,否则会报错,可根据当前 debug 的不同组件替换成 server historical/ server coordinator 等,解析的代码在 io.airlift.airline.Parser 类的 parse(GlobalMetadata metadata, Iterable<String> params) 方法,可自行 debug


8. Apache Druid,启动!

  • 首先把其他组件先启动 ./apache-druid-0.22.1/bin/start-nano-quickstart**
  • 接着我们把本地的 broker 启动,目前看起来一切正常
    broker-start.png

    本地浏览器打开locahost:8888,如果能成功出现如下页面,说明你已经成功启动了所有组件
    druid-console.png

    我们在本地代码(SqlResource 类)中打个断点,然后刷新下页面
debug.png
refresh-page.png

证明请求确实打到了我们的源代码中,接下来还差最后一步,填充数据

9. 填充测试数据

我们下载的安装包中有提供测试数据,目录是 /apache-druid-0.22.1/quickstart/tutorial/wikiticker-2015-09-12-sampled.json.gz
直接在控制台中 load 即可(也可以使用 hdfs 或 kafka 等,这里不再赘述):


load data.png

好了这样数据也有了,接下来各位就可以开始自行探索 Apache Druid 的秘密了。


以上就是全部内容,如果这篇文章刚好能帮到你,就给我点个赞吧~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容