级联flume报错 输出方无法连接接收方

今天犯了一个低级的错误,在排查过程中学到一些知识,特此记录,加深印象。

需求

模拟后台业务日志采集程序,多个服务器不停地生成多种日志内容,我需要在每台机器上启动输出方flume,然后把输出方flume的数据统一起来,由一台服务器启动接收方flume,把数据传给hdfs。总之,我需要搭建一套级联flume,部分日志采集架构图如下

报错

结果我启动的时候,接收方没有报错,但是输出方报错说接收方拒绝连接 org.apache.flume.FlumeException: NettyAvroRpcClient { host:xxxxx, port: xxxxx }: RPC connection error

21/02/03 22:59:27 INFO sink.AbstractRpcSink: Rpc sink k1 started.
21/02/03 22:59:27 INFO sink.AbstractRpcSink: Rpc sink k1: Building RpcClient with hostname: nn1.hadoop, port: 44444
21/02/03 22:59:27 INFO sink.AvroSink: Attempting to create Avro Rpc client.
21/02/03 22:59:27 WARN api.NettyAvroRpcClient: Using default maxIOWorkers
21/02/03 22:59:27 ERROR flume.SinkRunner: Unable to deliver event. Exception follows.
org.apache.flume.EventDeliveryException: Failed to send events
        at org.apache.flume.sink.AbstractRpcSink.process(AbstractRpcSink.java:389)
        at org.apache.flume.sink.DefaultSinkProcessor.process(DefaultSinkProcessor.java:67)
        at org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:145)
        at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.flume.FlumeException: NettyAvroRpcClient { host: nn1.hadoop, port: 44444 }: RPC connection error
        at org.apache.flume.api.NettyAvroRpcClient.connect(NettyAvroRpcClient.java:181)
        at org.apache.flume.api.NettyAvroRpcClient.connect(NettyAvroRpcClient.java:120)
        at org.apache.flume.api.NettyAvroRpcClient.configure(NettyAvroRpcClient.java:638)
        at org.apache.flume.api.RpcClientFactory.getInstance(RpcClientFactory.java:90)
        at org.apache.flume.sink.AvroSink.initializeRpcClient(AvroSink.java:127)
        at org.apache.flume.sink.AbstractRpcSink.createConnection(AbstractRpcSink.java:210)
        at org.apache.flume.sink.AbstractRpcSink.verifyConnection(AbstractRpcSink.java:270)
        at org.apache.flume.sink.AbstractRpcSink.process(AbstractRpcSink.java:346)
        ... 3 more
Caused by: java.io.IOException: Error connecting to nn1.hadoop/192.168.0.128:44444
        at org.apache.avro.ipc.NettyTransceiver.getChannel(NettyTransceiver.java:261)
        at org.apache.avro.ipc.NettyTransceiver.<init>(NettyTransceiver.java:203)
        at org.apache.avro.ipc.NettyTransceiver.<init>(NettyTransceiver.java:152)
        at org.apache.flume.api.NettyAvroRpcClient.connect(NettyAvroRpcClient.java:169)
        ... 10 more
Caused by: java.net.ConnectException: 拒绝连接: nn1.hadoop/192.168.0.128:44444
        at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
        at org.jboss.netty.channel.socket.nio.NioClientBoss.connect(NioClientBoss.java:152)
        at org.jboss.netty.channel.socket.nio.NioClientBoss.processSelectedKeys(NioClientBoss.java:105)
        at org.jboss.netty.channel.socket.nio.NioClientBoss.process(NioClientBoss.java:79)
        at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318)
        at org.jboss.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42)
        at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
        at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        ... 1 more

解决答案

最直接的原因就是输出方的flume启动命令写错了

# 进入flume的conf目录后,输入启动命令

# 正确的命令
flume-ng agent -n a1 -f ./flume-access.conf -c ./

# 错误的命令
flume-ng agent -n a1 -f ./flume-access.conf -c conf

启动flume的命令参数说明:

-n:指定agent名称(与配置文件中代理的名字相同)

-c:指定flume中配置文件的目录

-f:指定配置文件

按说这种错误应该报找不到×××/conf/conf呀,但是它偏偏报无法连接的错误,害我一直找不到原因。我至今不知道为什么会这样,哪位大佬给我讲讲是怎么回事呢?

排查过程

好了,接下来聊聊排查过程。其实我到现在也没搞明白这些现象的深层原因,只知道它们并不是报错的原因,希望走过路过的大佬指点一二。

扫描二维码关注公众号,回复: 12898808 查看本文章

1 检查网络

多个agent所在的服务器能互相ping通。

2 所有的 涉及到ip的不要用0.0.0.0或者 127.0.0.1这种表示

在接收方的配置文件中有这么一段内容

#对于source的配置描述 监听目录中的新增文件
a1.sources.r1.type = avro
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 44444

实际上,0.0.0.0对级联flume的连接并没有影响。而且,接收方的配置文件只需要配置这一个sources,就可以让多个agent向这一个sources推送数据。这段配置内容的意思是:0.0.0.0代表本机 表示使用lo网卡和ens33网卡都可以,范围会大点
,接收方flume绑定了本机44444端口,别的agent可以通过接收方的这个端口推送内容。

3 flume启动先后顺序

有人说是启动先后顺序的问题,像这种级联flume,一定要先启动接收方(Flume04),再启动输出方(Flume01、Flume02、Flume03),这样才可以保证sink的avro输出有接收方。

亲测无效!

实际上,在启动命令无误的情况下,flume的启动顺序对系统是没有影响的。我尝试在接收方的端口未打开的情况下启动输出方的flume,并没有报错。

4 检查44444端口

检查端口:netstat -an | grep 44
开启端口:nc -lp 44444 &

netstat -an | grep 44

  • 发现没有44444

nc -lp 44444 &

  • 手动开启接收方和输出方的44444端口

netstat -an | grep 44

  • 发现有44444了

启动flume,输出方仍然报错

  • 接收方的控制台出现乱码,依稀可见部分采集数据,然后自动退出程序。

netstat -an | grep 44

  • 接收方44444消失,输出方的44444还在
  • 说明接收方在强制开启端口的情况下,接收了部分采集数据,然后挂掉端口

检查输出方的channel文件,发现已经成功创建

通过对端口的排查,意外发现接收方的flume启动命令写错了,配置文件写成输出方的了。虽然该配置文件并不存在,但是整个过程接收方都没有报错,真是莫名其妙!

5 输出方本地测试

修改输出方的flume配置文件

Logger Sink 将数据写到flume的log中,通常用于测试或调试

# 配置Sink
a1.sinks.k1.type = logger

输出方的flume启动命令明明写错了,竟然能采集到数据,什么鬼???

-c conf 能采集到数据;-c ./ 反而采集不到数据,但是不会报错。

配置文件

最后贴出这次搭建级联flume集群的配置文件吧!

输出方的配置文件

#########################################################
##
##主要作用是监听文件中的新增数据,采集到数据之后,打印在控制台
##    注意:Flume agent的运行,主要就是配置source channel sink
##  下面的a1就是agent的代号,source叫r1 channel叫c1 sink叫k1
#########################################################
a1.sources = r1 r2 r3
a1.sinks = k1
a1.channels = c1

#对于source的配置描述 监听文件中的新增数据 exec
a1.sources.r1.type = exec
a1.sources.r1.command  = tail -F /home/hadoop/jars/data-clean/logs/data-clean/data-access.log
a1.sources.r1.interceptors = i1 i2
a1.sources.r1.interceptors.i1.type = static
##静态的在header中添加一个key value
a1.sources.r1.interceptors.i1.key = type
a1.sources.r1.interceptors.i1.value = access
a1.sources.r1.interceptors.i2.type = timestamp



a1.sources.r2.type = exec
a1.sources.r2.command  = tail -F /home/hadoop/jars/data-clean/logs/data-clean/data-ugchead.log
a1.sources.r2.interceptors = i1 i2
a1.sources.r2.interceptors.i1.type = static
##静态的在header中添加一个key value
a1.sources.r2.interceptors.i1.key = type
a1.sources.r2.interceptors.i1.value = ugchead
a1.sources.r2.interceptors.i2.type = timestamp

a1.sources.r3.type = exec
a1.sources.r3.command  = tail -F /home/hadoop/jars/data-clean/logs/data-clean/data-ugctail.log
a1.sources.r3.interceptors = i1 i2
a1.sources.r3.interceptors.i1.type = static
##静态的在header中添加一个key value
a1.sources.r3.interceptors.i1.key = type
a1.sources.r3.interceptors.i1.value = ugctail
a1.sources.r3.interceptors.i2.type = timestamp

#对于sink的配置描述 使用avro日志做数据的消费
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = nn1.hadoop
a1.sinks.k1.port = 44444

#对于channel的配置描述 使用文件做数据的临时缓存 这种的安全性要高
a1.channels.c1.type = file
a1.channels.c1.checkpointDir = /home/hadoop/jars/data-clean/logs/data-clean/checkpoint
a1.channels.c1.dataDirs = /home/hadoop/jars/data-clean/logs/data-clean/channel

#通过channel c1将source r1和sink k1关联起来
a1.sources.r1.channels = c1
a1.sources.r2.channels = c1
a1.sources.r3.channels = c1
a1.sinks.k1.channel = c1

接收方的配置文件

#########################################################
##
##主要作用是监听目录中的新增文件,采集到数据之后,输出到hdfs
##    注意:Flume agent的运行,主要就是配置source channel sink
##  下面的a1就是agent的代号,source叫r1 channel叫c1 sink叫k1
#########################################################
a1.sources = r1
a1.sinks = k1
a1.channels = c1

#对于source的配置描述 监听目录中的新增文件
a1.sources.r1.type = avro
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 44444

#对于sink的配置描述 使用log日志做数据的消费
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://ns1/input/data-clean/%{type}/%Y/%m/%d
a1.sinks.k1.hdfs.filePrefix = %{type}
a1.sinks.k1.hdfs.fileSuffix = .log
a1.sinks.k1.hdfs.inUseSuffix = .tmp
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.rollSize = 1048576
a1.sinks.k1.hdfs.rollInterval = 0
a1.sinks.k1.hdfs.rollCount = 0
a1.sinks.k1.hdfs.serializer = TEXT
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.minBlockReplicas = 1

#对于channel的配置描述 使用内存缓冲区域做数据的临时缓存
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 1000

#通过channel c1将source r1和sink k1关联起来
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

小结

归根结底还是flume启动命令写错了,没有理解各个命令参数。

通过这次排查,我进一步掌握了以下知识:

  1. 级联flume
  2. flume启动命令的命令参数含义
  3. 正常的flume启动会自动开启端口
  4. 端口的查看与开启

写到这里觉得挺没意思的,不知道记这些过程有没有意义,好浪费时间的样子。心好累,至今仍然一团浆糊,越弄越糊涂,感觉不会再爱了。。。

猜你喜欢

转载自blog.csdn.net/qq_40995238/article/details/113621003