美文网首页
Apache Druid 本地 debug 环境搭建

Apache Druid 本地 debug 环境搭建

作者: YancyPeng | 来源:发表于2023-12-04 18:21 被阅读0次

说在前面

最近在研究 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 的秘密了。


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

相关文章

网友评论

      本文标题:Apache Druid 本地 debug 环境搭建

      本文链接:https://www.haomeiwen.com/subject/maalgdtx.html