Apache/InLong InLong Manager 支持配置 Flink 任务并发度/Adjust sort resources according to data scale心得和随笔
audit已经实现了对于InLong系统的Agent、DataProxy、Sort模块的入流量、出流量进行实时审计对账。 对账的粒度有分钟、小时、天三种粒度。
1. audit的数据缓存在org.apache.inlong.audit.cache
的各个类中,有DayCache HalfHourCache
等等
2. 调用api的方式
请求audit数据的api在org.apache.inlong.audit.config.OpenApiConstants
中,通过org.apache.inlong.audit.service.ApiService
来调用。调用的时候注意参数的合法性,有合法性检查,以免请求不到数据。居然没有用controller,挺神奇的,贴一段代码上来,便于以后研究
private void initHttpServer() {
点击查看代码
private void initHttpServer() {
int bindPort = Configuration.getInstance().get(KEY_HTTP_SERVER_BIND_PORT, DEFAULT_HTTP_SERVER_BIND_PORT);
try {
HttpServer server = HttpServer.create(new InetSocketAddress(bindPort),
Configuration.getInstance().get(KEY_API_BACKLOG_SIZE, DEFAULT_API_BACKLOG_SIZE));
server.setExecutor(Executors.newFixedThreadPool(
Configuration.getInstance().get(KEY_API_THREAD_POOL_SIZE, DEFAULT_API_THREAD_POOL_SIZE)));
server.createContext(Configuration.getInstance().get(KEY_API_DAY_PATH, DEFAULT_API_DAY_PATH),
new AuditHandler(DAY));
server.createContext(Configuration.getInstance().get(KEY_API_HOUR_PATH, DEFAULT_API_HOUR_PATH),
new AuditHandler(HOUR));
server.createContext(Configuration.getInstance().get(KEY_API_MINUTES_PATH, DEFAULT_API_MINUTES_PATH),
........省略类似的方法.........
server.start();
LOGGER.info("Init http server success. Bind port is: {}", bindPort);
} catch (Exception e) {
LOGGER.error("Init http server has exception!", e);
}
}
3. 请求方法样例,查询分钟数据
http://172.28.128.1:10080/audit/query/minutes?startTime=2024-07-01T00:00:00&endTime=2024-07-06T23:59:59&inlongGroupId=test_pulsar_group&inlongStreamId=test_pulsar_stream&auditId=1073741825&auditCycle=1
注意填写ipconfig中的地址,不是wsl中ifconfig的地址
注意!一定要启动inlong/manager和mysql,否则前者导致获取不到配置文件,后者导致获取不到数据
以太网适配器 vEthernet (WSL (Hyper-V firewall)):
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::15f7:1f2:8c88:287b%64
IPv4 地址 . . . . . . . . . . . . : 172.28.128.1
子网掩码 . . . . . . . . . . . . : 255.255.240.0
默认网关. . . . . . . . . . . . . :
返回
点击查看代码
{
"success": true,
"errMsg": "",
"data": [
{
"auditVersion": 0,
"logTs": "2024-07-06 22:16:00",
"inlongGroupId": "test_pulsar_group",
"inlongStreamId": "test_pulsar_stream",
"auditId": "1073741825",
"auditTag": "-1",
"count": 10000,
"size": 157788,
"delay": 0
}
]
}
4. audit如何处理MySQL中的审计数据
audit会把从MQ中查询到的数据放入数据库(默认MySQL),然后进行缓存。在org.apache.inlong.audit.service.EtlService
中,调用
mysqlToHalfHourCache
等方法,
点击查看代码
private void mysqlToHalfHourCache() {
DataQueue dataQueue = new DataQueue(queueSize);
mysqlSourceOfHalfHourCache =
new JdbcSource(dataQueue, buildMysqlSourceConfig(AuditCycle.MINUTE_30, statBackTimes));
mysqlSourceOfHalfHourCache.start();
cacheSinkOfHalfHourCache = new CacheSink(dataQueue, HalfHourCache.getInstance().getCache());
cacheSinkOfHalfHourCache.start();
DataQueue dataQueue = new DataQueue(queueSize);
mysqlSourceOfHalfHourCache =
new JdbcSource(dataQueue, buildMysqlSourceConfig(AuditCycle.MINUTE_30, statBackTimes));
mysqlSourceOfHalfHourCache.start();
cacheSinkOfHalfHourCache = new CacheSink(dataQueue, HalfHourCache.getInstance().getCache());
cacheSinkOfHalfHourCache.start();
}
实现方法的考虑
从manager中进行parallelism的调控,从flinkInfo中的inlongStreamInfoList中获取streamID inlongGroupId
然后通过分钟级接口进行查询,获得size和count,用于data scale 的计算
注意,单独编译子模块的时候,由于是1.13.0-SNAPSHOT开发分支,需要设置
maven生命周期的整理
清理声明周期(Clean Lifecycle):
clean:清理项目构建产生的临时文件和目录。
默认声明周期(Default Lifecycle):
validate:验证项目是否正确且所有必要信息可用。
compile:编译项目的源代码。
test:运行测试代码。
package:将编译后的代码打包成可分发的格式,如 JAR。
verify:对打包的代码进行额外的检验,以确保质量。
install:将打包的代码安装到本地 Maven 仓库,供其他项目使用。
deploy:将打包的代码部署到远程仓库,供其他开发人员和项目使用。
关于编译
docker太强了,可以搭建独立的编译环境,甚至可以通过
cd /mnt/c/Users/zhang/Desktop/ApacheInLong/inlong
docker run -v `pwd`:/inlong -w /inlong maven:3.6-openjdk-8 mvn clean install -DskipTests
使用maven:3.6-openjdk-8镜像启动一个Docker容器,并将当前目录(即项目目录)挂载到容器的/inlong目录中。然后,在容器中执行mvn clean install -DskipTests命令来编译项目。完成上述步骤后,Docker容器将使用Maven编译项目,并根据指定的参数进行构建。编译生成的结果将存储在项目目录中,可以在Windows宿主机上访问和使用。完美地解决了我的maven各种奇怪的依赖/路径/环境问题!成为docker忠实粉丝。
使用docker编译inlong出现了问题,docker命令是
docker run -v pwd:/inlong -w /inlong maven:3.6-openjdk-8 mvn clean install -DskipTests
,问题是
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0:exec (version) on project tubemq-server: Command execution failed.: Cannot run program "/inlong/inlong-tubemq/tubemq-server/src/saveServerVersion.sh" (in directory "/inlong/inlong-tubemq/tubemq-server"): error=13, Permission denied -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <args> -rf :tubemq-server
解决方法:这个问题是由于Docker容器内的权限问题导致的。默认情况下,Docker容器中的文件可能没有执行权限。要解决这个问题,可以在运行Docker容器之前,确保脚本文件具有执行权限。修改Docker命令,使其在执行Maven构建之前,先授予脚本执行权限。
docker run -v `pwd`:/inlong -w /inlong maven:3.6-openjdk-8 bash -c "chmod +x /inlong/inlong-tubemq/tubemq-server/src/saveServerVersion.sh && mvn clean install -DskipTests"
Q:为啥即使我用docker run -v pwd:/inlong -w /inlong maven:3.6-openjdk-8 bash -c "chmod +x /inlong/inlong-tubemq/tubemq-server/src/saveServerVersion.sh && mvn compile -DskipTests",这docker每次启动都会检查和安装依赖?
A:Docker 每次启动都会检查和安装依赖的原因是因为 Docker 容器是无状态的,并且每次运行都会创建一个新的容器实例。为了避免每次启动时都重新安装依赖,可以使用以下方法: 1. 使用 Dockerfile 创建一个自定义镜像 2. 使用 Docker Compose 3. 持久化 Maven 依赖缓存 由于每次都重新下载依赖时间太久了,考虑自己搞个maven:3.6-openjdk-8的镜像,但是带inlong的所有依赖
Q:Docker是无状态的,那为啥MySQL docker可以保存数据? A: Docker 容器本身是无状态的,这意味着当容器停止或删除后,其内部的所有数据都会丢失。然而,通过使用卷(Volumes),Docker 可以实现数据的持久化,从而保存状态。
Docker Volumes
Docker 卷是一种特殊的目录,可以将主机上的目录挂载到 Docker 容器中,使得容器中的数据可以在容器重启、删除或重建后依然保留。这就是为什么 Docker 中的 MySQL 容器可以保存数据的原因。
考虑下列命令:
docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=root -v /my/local/data:/var/lib/mysql -d mysql:5.7
-v /my/local/data:/var/lib/mysql
将主机上的 /my/local/data
目录挂载到容器中的/var/lib/mysql
目录。MySQL 的数据存储在 /var/lib/mysql
目录下,因此这确保了数据在容器重启或删除后仍然保存在主机上的 /my/local/data
目录中。
小事故:本来想挂载docker到windows目录的,但是挂载了之后发现读取不到文件,估计是没有权限(后来发现可能路径没有加/mnt/),而且官方不推荐,就不用了
2024.7.15 更正,别瞎搞,要挂载windows目录很简单,只需要用windows的目录完全
照搬就可以了。发现了一个很有趣的问题,就是/mnt/c格式的指令要在linux wsl terminal中执行,windows格式的目录要在windows powershell中执行,需要注意
也就是说用
docker run -v D:\develop\ApacheInLong\inlong:/inlong -v D:\UserProgram\mavenRepo:/root/.m2/repository -w /inlong maven:3.6-openjdk-8 mvn clean install -DskipTests
编译
启动docker:
docker run --name maven-inlong-official -it \
--privileged \
-v /home/peterzh/osp/inlong-dev/inlong:/inlong \
-v /usr/share/maven-repo:/root/.m2/repository \
-w /inlong \
maven:3.6-openjdk-8 bash
编译的时候有个脚本执行没权限,先赋予执行权限,否则会失败
chmod 700 inlong-tubemq/tubemq-client/src/saveServerVersion.sh
已经启动的没法挂载
已经在运行的容器
docker exec
启动一个已经创建的容器
docker start
考虑到开发的便捷性,感觉还是idea或者vscod连接到wsl,直接操作比较好,写完了可以直接编译,windows环境怎么都配不好xs
2024.7.15
之前一直在研究auditid是什么鬼东西,本来都要问doleyzi了,结果发现auditUtil里面有一大堆自己定义的常量。因为用buildaudit没法生成正确的auditid。比如
AUDIT_ID_AGENT_TASK_HEARTBEAT = 1073741839;
位于inlong-agent/agent-common/src/main/java/org/apache/inlong/agent/metrics/audit/AuditUtils.java
看来连伟大的钒哥也没有记得inlong的所有实现,这说明了维护大型项目的解耦的重要作用。
如果用
docker run -v /home/peterzh/inlong:/inlong -v /usr/share/maven-repo:/root/.m2/repository -w /inlong maven:3.6-openjdk-8 bash
启动docker的话会出现瞬间自动关闭的问题,如果你只是运行 bash,它会启动一个非交互式 shell,然后立即退出。为了保持容器的运行,你需要启动一个交互式 shell。
docker run --name maven -it -v /home/peterzh/inlong:/inlong -v /usr/share/maven-repo:/root/.m2/repository -w /inlong maven:3.6-openjdk-8 bash
同时,如果用
docker run -v /home/peterzh/inlong:/inlong -v /usr/share/maven-repo:/root/.m2/repository -w /inlong maven:3.6-openjdk-8 bash -c "chmod +x inlong-tubemq/tubemq-server/src/saveServerVersion.sh && mvn clean install -DskipTests"
那么docker每次启动都会自动执行
chmod +x inlong-tubemq/tubemq-server/src/saveServerVersion.sh && mvn clean install -DskipTests
,这不好。docker还是要多研究
7.16
学习到了测试自己的代码可以把编译好的jar包放到docker-compose up生成的container的里面,替换原来的lilb就可以测试了,不用自己搭环境,非常好!
使用docker编译的时候,遇到了test,里面需要再启动docker,
Caused by: org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=elasticsearch:7.9.3, imagePullPolicy=DefaultPullPolicy(), imageNameSubstitutor=org.testcontainers.utility.ImageNameSubstitutor$LogWrappedImageNameSubstitutor@fffb4a8)
Caused by: java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration
可能的解决方法:
挂载 Docker 套接字:
在运行构建容器时,通常需要将宿主机的 Docker 套接字挂载到容器中。这允许容器内的进程使用宿主机的 Docker 守护进程来启动新的 Docker 容器。例如:
bash
复制代码
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
使用合适的 Docker 镜像:
构建用于测试的 Docker 容器时,使用已安装 Docker 的镜像,例如 docker:dind 镜像,这样容器内部就自带了 Docker 环境。
2024.7.18
终于跑起来了,发现是我傻掉了home\peterzh\inlong\inlong-distribution\target\apache-inlong-1.13.0-SNAPSHOT-bin\apache-inlong-1.13.0-SNAPSHOT\inlong-manager,居然只把lib拷贝到了docker里面,一直提示flinkservice holder没有定义,我以为真的没有定义,结果一看发现是flinkservice的东西都在plugins里面,怪不得我看见我定义在sort properties的maxpercore也是nullpointerexception。看来即使是大佬说的话也要思考xs。
自用复制文件到docker的命令
docker cp /home/peterzh/inlong/inlong-distribution/target/apache-inlong-1.13.0-SNAPSHOT-bin/apache-inlong-1.13.0-SNAPSHOT/inlong-manager/ manager:/tmp/all
cp -r /tmp/all/. /opt/inlong-manager/
注意到docker中用.表示所有文件(可能)
2024.7.18
发现了一些问题,dataproxy的ip似乎由manager写死在inlong_cluster_node中了,但是docker会动态分配ip,导致没法找到合适的ip,所以agent发送失败。所以我有的时候会发送成功,有的时候不成功,因为agent是通过ip和proxy交互的,而不是域名
2024.7.22
还是基本功不行,悲
又忘记了docker重启之后只要不是volume都会被重置。
发现了用环境变量logging.level.root=DEBUG可以覆盖配置文件中的相关环境变量,终于用上DEBUG版的manager了
试了commit,生成新的dockerimage,似乎不能成功保存配置文件
2024.8.10
dashboard,数据流中点击执行工作流,flink web dashboard会出现新的job
http://localhost:8081/#/overview
使用自定义docker网络定义每个容器的ip可以有效防止重启容器之后容器之间无法通讯的情况
具体问题为telnet 127.0.0.1 46801会显示拒绝访问,不知道为什么
以下是参考的配置文件,pulsar经常会卡死,换用了kafka,配了kafka magic方便监控
clickhouse也配进来了,省的每次都重启,而且配网络也麻烦
点击查看代码
#
# 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.
#
version: '2.4'
networks:
custom_network:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16
services:
mysql:
image: mysql:8.0.28
container_name: mysql
platform: "linux/x86_64"
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=inlong
healthcheck:
test: "/usr/bin/mysql --user=root --password=inlong --execute \"SHOW DATABASES;\""
timeout: 20s
interval: 2s
retries: 10
volumes:
- ./mysql:/var/lib/mysql
- ./sql:/docker-entrypoint-initdb.d
command: --authentication_policy=mysql_native_password
networks:
custom_network:
ipv4_address: 172.18.0.2
zookeeper:
image: wurstmeister/zookeeper
container_name: zookeeper
ports:
- 2181:2181
networks:
custom_network:
ipv4_address: 172.18.0.3
kafka:
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
- KAFKA_BROKER_ID=0
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
- KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092
- KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092
depends_on:
- zookeeper
networks:
custom_network:
ipv4_address: 172.18.0.4
kafkamagic:
image: digitsy/kafka-magic
container_name: kafkamagic
ports:
- "8080:80"
environment:
- KAFKA_HOST=kafka
- KAFKA_PORT=9092
- KMAGIC_ALLOW_TOPIC_DELETE="true"
- KMAGIC_ALLOW_SCHEMA_DELETE="true"
depends_on:
- kafka
volumes:
- .:/config
networks:
custom_network:
ipv4_address: 172.18.0.5
manager:
image: inlong/manager:${VERSION_TAG}
container_name: manager
depends_on:
mysql:
condition: service_healthy
ports:
- "8083:8083"
environment:
- JDBC_URL=mysql:3306
- USERNAME=root
- PASSWORD=inlong
- ZK_URL=tubemq-server:2181
- FLINK_HOST=jobmanager
- FLINK_PORT=8081
- AUDIT_QUERY_URL=http://audit:10080
networks:
custom_network:
ipv4_address: 172.18.0.6
dashboard:
image: inlong/dashboard:${VERSION_TAG}
container_name: dashboard
depends_on:
- manager
ports:
- "80:80"
environment:
- MANAGER_API_ADDRESS=manager:8083
networks:
custom_network:
ipv4_address: 172.18.0.7
dataproxy:
image: inlong/dataproxy:${VERSION_TAG}
container_name: dataproxy
depends_on:
- manager
ports:
- "46801:46801"
- "46802:46802"
environment:
- MANAGER_OPENAPI_IP=manager
- MANAGER_OPENAPI_PORT=8083
# pulsar or kafka
- MQ_TYPE=kafka
- ETH_NAME=eth0
networks:
custom_network:
ipv4_address: 172.18.0.8
agent:
image: inlong/agent:${VERSION_TAG}
container_name: agent
depends_on:
- manager
- dataproxy
environment:
- MANAGER_OPENAPI_IP=manager
- MANAGER_OPENAPI_PORT=8083
- DATAPROXY_IP=dataproxy
- DATAPROXY_PORT=46801
volumes:
- ./collect-data:/data/collect-data
networks:
custom_network:
ipv4_address: 172.18.0.9
audit:
image: inlong/audit:${VERSION_TAG}
container_name: audit
privileged: true
depends_on:
mysql:
condition: service_healthy
environment:
- AUDIT_JDBC_URL=mysql:3306
- AUDIT_JDBC_USERNAME=root
- AUDIT_JDBC_PASSWORD=inlong
- MANAGER_OPENAPI_IP=manager
- MANAGER_OPENAPI_PORT=8083
- AUDIT_PROXY_ADDRESS=audit:10081
# pulsar or kafka
- MQ_TYPE=kafka
ports:
- "10080:10080"
- "10081:10081"
networks:
custom_network:
ipv4_address: 172.18.0.10
jobmanager:
image: apache/flink:1.15-scala_2.12
container_name: jobmanager
environment:
- |
FLINK_PROPERTIES=
jobmanager.rpc.address: jobmanager
ports:
- "8081:8081"
command: jobmanager
networks:
custom_network:
ipv4_address: 172.18.0.11
taskmanager:
image: apache/flink:1.15-scala_2.12
container_name: taskmanager
environment:
- |
FLINK_PROPERTIES=
jobmanager.rpc.address: jobmanager
taskmanager.numberOfTaskSlots: 2
command: taskmanager
networks:
custom_network:
ipv4_address: 172.18.0.12
clickhouse:
image: clickhouse/clickhouse-server:22.8
container_name: clickhouse
environment:
- CLICKHOUSE_USER=admin
- CLICKHOUSE_PASSWORD=inlong
- CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
ports:
- "8123:8123"
networks:
custom_network:
ipv4_address: 172.18.0.13
当使用windows terminal和wsl的terminal启动docker时,对于docker-compose.yml没有linux语法的时候,没有区别,但是如果有的话,比如\(PWD,就会有区别,挂载volume路径包含\)PWD的话一定要用linux terminal
8.11
发现mysql->clickhouse数据同步的官网文档有点问题,
这里用的是test.source_table
,多了个schema,其实只要source_table就行,因为库名已经指定了,否则会出现表名变成test.test.source_table的问题,导致没法找到source
8.23
碰到了audit url的@value注解注入失败的情况,在 FlinkService 中手动使用 new 关键字创建 FlinkParallelismOptimizer 实例,而不是通过 Spring 的依赖注入机制来管理这个对象,确实会导致 @Value 注解无法注入属性。这是因为 @Value 注解依赖于 Spring 的依赖注入容器,如果对象不是由 Spring 管理的,Spring 将无法注入配置值。
使用ApplicationContext手动管理spring context,可以解决问题
package org.apache.inlong.manager.plugin.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Get the ApplicationContext
*/
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
然后在需要使用的地方,使用
FlinkParallelismOptimizer flinkParallelismOptimizer = ApplicationContextProvider.getContext().getBean(FlinkParallelismOptimizer.class);
就可以在不被Spring管理的类中注入spring管理的类了
2024.8.31
经历了32个comment之后,终于合并了,感动
谨此纪念
https://github.com/apache/inlong/pull/10916