安装和部署flume
水槽建筑
Flume是一种分布式,可靠且可用的服务,用于收集,聚集大量流事件数据并将其从许多源移动到集中式数据存储中。
图1. Flume体系结构
![该图显示了Flume架构](https://i-blog.csdnimg.cn/blog_migrate/cded0fd7599ffe6f281b767c1276d7c8.png)
Flume事件可以定义为具有有效负载(字节)和可选的字符串属性集的数据流单位。 Flume代理是一个JVM进程,承载了组件,事件通过这些组件从外部源流到下一个目标(跃点)。
InfoSphere®BigInsights™能够以低延迟对流数据进行连续分析和存储。 InfoSphere Streams可用于配置上述代理程序和收集器流程(请参阅参考资料 )。 另外,Flume可以用于在远程位置上收集数据,并且可以在InfoSphere BigInsights服务器上配置收集器以在分布式文件系统(DFS)上存储数据。 但是,在本文中,我们将Flume用作代理和收集器流程,并将Hadoop分布式文件系统(HDFS)群集用作存储。
数据流模型
Flume代理具有三个主要组件:源,通道和接收器。 源使用由外部源(如Web服务)传递给它的事件。 外部源以可识别的格式将事件发送到Flume。 当Flume源收到事件时,它将事件存储到一个或多个通道中 。 该通道是一个被动存储,用于保留事件,直到被Flume Sink消耗为止。 例如,文件通道使用本地文件系统。 接收器从通道中提取事件,并将其放入HDFS之类的外部存储库中,或将其转发到流中下一个Flume代理(下一跳)的Flume源。 给定代理中的源和接收器与通道中上演的事件异步运行。
源可以出于不同目的使用不同的格式。 例如,可以使用Avro Flume源接收来自Avro客户端的Avro事件。 Avro源占Flume分层收集支持的一半。 在内部,此源使用Avro的NettyTransceiver侦听和处理事件。 可以将其与内置的AvroSink配对以创建分层的集合拓扑。 Flume使用的其他流行网络流是Thrift,Syslog和Netcat。
阿夫罗
Apache的Avro是一种数据序列化格式。 它是一个基于RPC的框架,被Apache项目(例如Flume和Hadoop)广泛使用,用于数据存储和通信(请参阅参考资料 )。 Avro框架的目的是提供丰富的数据结构,紧凑而快速的二进制数据格式,以及与动态语言(例如C ++,Java™,Perl和Python)的简单集成。 Avro将JSON用于其接口描述语言(IDL),以指定数据类型和协议。
Avro依赖于存储有数据的架构。 由于没有每个值的开销,因此可以快速轻松地进行序列化。 在远程过程调用(RPC)期间,在客户端-服务器握手期间交换架构。 使用Avro,可以轻松解决字段之间的对应关系,因为它使用JSON。
可靠性,可恢复性和多跳流
Flume使用事务性设计来确保事件交付的可靠性。 事务性设计对应于将每个事件视为事务,并且这些事件在每个代理程序的通道中上演。 每个事件都会传递到流中的下一个代理(例如源栏)或终端存储库(例如HDFS)。 仅在将事件存储在下一个代理程序的信道或终端存储库中之后,才将它们从信道中删除,从而将当前事件保留在队列中,直到收到存储确认为止。 这是通过源和接收器发生的,它们将存储或检索信息封装在通道提供的事务中。 这确保了Flume中单跳消息传递语义的流的端到端可靠性。
通过通道中的登台事件来维护可恢复性,该事件管理从故障中恢复。 Flume支持由本地文件系统支持的持久文件通道(本质上是在永久存储器上保持状态)。 如果使用持久文件通道,则丢失的任何事件(在崩溃或系统故障的情况下)都可以恢复。 还有一个内存通道将事件存储在内存队列中,速度更快,但是当代理进程死亡时,仍保留在内存通道中的所有事件都无法恢复。
Flume还允许用户构建多跳流程,其中事件在到达最终目的地之前会通过多个代理传播。 在多跳流的情况下,来自上一跳的接收器和来自下一跳的源都运行其事务处理,以确保数据安全地存储在下一跳的通道中。
图2.多跳流
系统架构
在本节中,我们将讨论如何使用Flume设置可伸缩的Web服务。 为此,我们将需要代码来阅读RSS提要。 我们还需要配置Flume代理和收集器以接收RSS数据并将其存储在HDFS中。
Flume代理配置存储在本地配置文件中。 这类似于Java属性文件,并存储为文本文件。 可以在同一配置文件中指定一个或多个代理的配置。 配置文件包括代理中每个源,接收器和通道的属性,以及它们如何连接在一起以形成数据流。
Avro源需要一个主机名(IP地址)和一个端口号才能接收数据。 内存通道可以具有最大队列大小(容量),并且HDFS接收器需要知道文件系统URI和创建文件的路径。 Avro接收器可以是前向接收器( avro-forward-sink
),可以转发到下一个Flume代理。
这个想法是创建一个微型Flume分布式提要(日志事件)收集系统。 我们将使用代理作为节点,这些代理从RSS提要阅读器获取数据(在这种情况下为RSS提要)。 这些代理将这些提要传递到收集器节点,该收集器节点负责将这些提要存储到HDFS群集中。 在此示例中,我们将使用两个Flume代理节点,一个Flume收集器节点和一个三节点HDFS群集。 表1描述了代理程序和收集器节点的源和接收器。
表1.代理和收集器节点的源和接收器
节点数 | 资源 | 水槽 |
---|---|---|
代理节点 | RSS订阅 | 集电极 |
收集器节点 | 代理商 | HDFS |
图3显示了我们的多跳系统的体系结构概述,该系统具有两个代理程序节点,一个收集器节点和一个HDFS集群。 RSS Web提要(请参见下面的代码)是两个代理的Avro源,并将提要存储在内存通道中。 随着提要在两个代理的内存通道中堆积,Avro接收器开始将这些事件发送到收集器节点的Avro源。 收集器还使用内存通道和HDFS接收器将提要转储到HDFS群集中。 请参阅下面的代理和收集器配置。
图3.多跳系统的体系结构概述
![该图显示了多跳系统的体系结构概述](https://i-blog.csdnimg.cn/blog_migrate/bce27eb8a7c048a5423befecda176714.png)
让我们看看如何使用Flume启动简单的新闻阅读器服务。 以下Java代码描述了一个RSS阅读器,该阅读器从BBC读取RSS Web源。 您可能已经知道,RSS是一系列Web提要格式,用于以标准格式发布经常更新的作品,例如博客条目,新闻标题,音频和视频。 RSS使用发布-订阅模型来定期检查订阅的提要以获取更新。
Java代码使用Java的Net和Javax XML API读取W3C文档中URL源的内容,并在将信息写入Flume通道之前处理该信息。
清单1. Java代码(RSSReader.java)
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class RSSReader {
private static RSSReader instance = null;
private RSSReader() {
}
public static RSSReader getInstance() {
if(instance == null) {
instance = new RSSReader();
}
return instance;
}
public void writeNews() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().
newDocumentBuilder();
URL u = new URL("http://feeds.bbci.co.uk/news/world/rss.xml
?edition=uk#");
Document doc = builder.parse(u.openStream());
NodeList nodes = doc.getElementsByTagName("item");
for(int i=0;i<nodes.getLength();i++) {
Element element = (Element)nodes.item(i);
System.out.println("Title: " + getElementValue(element,"title"));
System.out.println("Link: " + getElementValue(element,"link"));
System.out.println("Publish Date: " + getElementValue(element,"pubDate"));
System.out.println("author: " + getElementValue(element,"dc:creator"));
System.out.println("comments: " + getElementValue(element,"wfw:comment"));
System.out.println("description: " + getElementValue(element,"description"));
System.out.println();
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
private String getCharacterDataFromElement(Element e) {
try {
Node child = e.getFirstChild();
if(child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
} catch(Exception ex) {
}
return "";
}
protected float getFloat(String value) {
if(value != null && !value.equals("")) {
return Float.parseFloat(value);
}
return 0;
}
protected String getElementValue(Element parent,String label) {
return getCharacterDataFromElement((Element)parent.getElements
ByTagName(label).item(0));
}
public static void main(String[] args) {
RSSReader reader = RSSReader.getInstance();
reader.writeNews();
}
}
以下代码清单显示了代理(10.0.0.1和10.0.0.2)和收集器(10.0.0.3)的示例配置文件。 配置文件定义了源,通道和接收器的语义。 对于每种源类型,我们还需要定义类型,命令,标准错误行为和故障选项。 对于每个通道,我们需要定义通道类型。 还必须定义通道类型,容量(存储在通道中的最大事件数)和事务处理容量(通道将从每个事务源或接收器接收的最大事件数)。 同样,对于每种接收器类型,我们需要定义类型,主机名(事件接收者的IP)和端口。 如果是HDFS接收器,则提供HDFS头名称节点的目录路径。
清单2显示了示例配置文件10.0.0.1。
清单2.代理1的配置(10.0.0.1上的flume-conf.properties)
# The configuration file needs to define the sources,
# the channels and the sinks.
# Sources, channels and sinks are defined per agent,
# in this case called 'agent'
agent.sources = reader
agent.channels = memoryChannel
agent.sinks = avro-forward-sink
# For each one of the sources, the type is defined
agent.sources.reader.type = exec
agent.sources.reader.command = tail -f /var/log/flume-ng/source.txt
# stderr is simply discarded, unless logStdErr=true
# If the process exits for any reason, the source also exits and will produce no
# further data.
agent.sources.reader.logStdErr = true
agent.sources.reader.restart = true
# The channel can be defined as follows.
agent.sources.reader.channels = memoryChannel
# Each sink's type must be defined
agent.sinks.avro-forward-sink.type = avro
agent.sinks.avro-forward-sink.hostname = 10.0.0.3
agent.sinks.avro-forward-sink.port = 60000
#Specify the channel the sink should use
agent.sinks.avro-forward-sink.channel = memoryChannel
# Each channel's type is defined.
agent.channels.memoryChannel.type = memory
# Other config values specific to each type of channel(sink or source)
# can be defined as well
# In this case, it specifies the capacity of the memory channel
agent.channels.memoryChannel.capacity = 10000
agent.channels.memoryChannel.transactionCapacity = 100
清单3显示了示例配置文件10.0.0.2。
清单3. Agent 2配置(10.0.0.2上的flume-conf.properties)
agent.sources = reader
agent.channels = memoryChannel
agent.sinks = avro-forward-sink
# For each one of the sources, the type is defined
agent.sources.reader.type = exec
agent.sources.reader.command = tail -f /var/log/flume-ng/source.txt
# stderr is simply discarded, unless logStdErr=true
# If the process exits for any reason, the source also exits and will produce
# no further data.
agent.sources.reader.logStdErr = true
agent.sources.reader.restart = true
# The channel can be defined as follows.
agent.sources.reader.channels = memoryChannel
# Each sink's type must be defined
agent.sinks.avro-forward-sink.type = avro
agent.sinks.avro-forward-sink.hostname = 10.0.0.3
agent.sinks.avro-forward-sink.port = 60000
#Specify the channel the sink should use
agent.sinks.avro-forward-sink.channel = memoryChannel
# Each channel's type is defined.
agent.channels.memoryChannel.type = memory
# Other config values specific to each type of channel(sink or source)
# can be defined as well
# In this case, it specifies the capacity of the memory channel
agent.channels.memoryChannel.capacity = 10000
agent.channels.memoryChannel.transactionCapacity = 100
清单4显示了收集器配置文件10.0.0.3。
清单4.收集器配置(10.0.0.3上的flume-conf.properties)
Collector configuration (flume-conf.properties on 10.0.0.3):
# The configuration file needs to define the sources,
# the channels and the sinks.
# Sources, channels and sinks are defined per agent,
# in this case called 'agent'
agent.sources = avro-collection-source
agent.channels = memoryChannel
agent.sinks = hdfs-sink
# For each one of the sources, the type is defined
agent.sources.avro-collection-source.type = avro
agent.sources.avro-collection-source.bind = 10.0.0.3
agent.sources.avro-collection-source.port = 60000
# The channel can be defined as follows.
agent.sources.avro-collection-source.channels = memoryChannel
# Each sink's type must be defined
agent.sinks.hdfs-sink.type = hdfs
agent.sinks.hdfs-sink.hdfs.path = hdfs://10.0.10.1:8020/flume
#Specify the channel the sink should use
agent.sinks.hdfs-sink.channel = memoryChannel
# Each channel's type is defined.
agent.channels.memoryChannel.type = memory
# Other config values specific to each type of channel(sink or source)
# can be defined as well
# In this case, it specifies the capacity of the memory channel
agent.channels.memoryChannel.capacity = 10000
下一步
现在我们有了读取RSS提要的代码,并且知道了如何配置Flume代理和收集器,我们可以通过三个步骤来设置整个系统。
第1步
应该将已编译的Java代码作为后台进程执行,以使其保持运行状态。
清单5.编译后的Java代码
$ javac RSSReader.java
$ java -cp /root/RSSReader RSSReader > /var/log/flume-ng/source.txt &
第2步
在启动代理之前,您需要使用$ FLUME_HOME / conf /目录下提供的模板来修改配置文件。 修改配置文件后,可以使用以下命令启动代理。
清单6显示了在节点1上启动代理。
清单6.在节点1上启动代理
Agent node 1 (on 10.0.0.1):
$ $FLUME_HOME/bin/flume-ng agent -n agent1 -c conf -f
$FLUME_HOME/conf/flume-conf.properties
清单7显示了在节点2上启动代理。
清单7.在节点2上启动代理
Agent node 2 (on 10.0.0.2):
$ $FLUME_HOME/bin/flume-ng agent -n agent2 -c conf -f
$FLUME_HOME/conf/flume-conf.properties
在这里, $FLUME_HOME
被定义为环境变量(bash或.bashrc),它指向Flume的主目录(例如,/ home / $FLUME_HOME
)。
第三步
清单8启动了收集器。 值得注意的是,配置文件负责节点的行为,例如它是代理还是收集器。
清单8. Collector节点(在10.0.0.3上)
$ $FLUME_HOME/bin/flume-ng agent -n collector -c conf -f
$FLUME_HOME/conf/flume-conf.properties
结论
在本文中,我们介绍了Flume,Flume是一种分布式且可靠的服务,用于有效地收集大量日志数据。 我们描述了如何根据需要将其用于部署单跳和多跳流。 我们还描述了一个详细的示例,在该示例中,我们部署了多跳新闻聚合器Web服务。 在示例中,我们使用Avro代理读取RSS提要,并使用HDFS收集器存储新闻提要。 Flume可用于构建可伸缩的分布式系统以收集大量数据。
翻译自: https://www.ibm.com/developerworks/analytics/library/bd-flumews/index.html
安装和部署flume