flume之Avro Source和Avro Sink

【原文】https://my.oschina.net/pengqiang/blog/535365?fromerr=qjKhU9We
一、Avro Souce介绍

Flume主要的RPC Source是Avro Source

Avro Source被设计为高扩展的RPC服务器端,能从其他的Flume Agent的Avro Sink或者使用Flume的SDK发送数据的客户端应用,接受数据到一个Flume Agent中。

Avro Source的可扩展性结合Channel担当了缓冲器的角色,使得Flume Agent能够处理重要的负载峰值。

Flume的Avro Source使用Netty-Avro inter-process的值通信(IPC)协议来通信,因此可以用Java或JVM语言发送数据到Avro Source。

如果想从应用使用Avro Source发送事件给一个Agent,你可以利用Flume SDK,或者嵌入式Agent来完成。

Avro Source可以配置用来从配置好输出压缩事件的Avro Sink中接收压缩的事件。也可以配置来确保接收任何客户端或Sink发送的使用SSL加密的数据。
二、Avro Source参数说明
配置参数
默认值 描述
type

Avro Source的别名是avro,也可以使用完整类别名称org.apache.flume.source.AvroSource

bind

绑定的ip地址或主机名。使用0.0.0.0表示绑定机器所有的接口

port
绑定的端口
threads
infinity
接收从客户端或Avro Sink传入的数据的最大工作线程的数量,默认无穷大

ssl false
设置为true时表示,所有连接到Source的客户端都需要使用SSL,如果使用了SSL,则keystore和keystore-password参数是必须的。

keystore
使用SSL的keystore的路径

keystore-password

打开keystore使用的密码
keystore-type
JKS 正在使用的keystore的类型
compression-type
用于解压缩传入数据的压缩格式。唯一支持的压缩格式是zlib。如果要接收zlib压缩的数据,设置该参数为deflate。

ipFilter
false 设置为true启用ip过滤
ipFilter.rules

通过此配置,定义ip过滤的表达式规则

Avro Source使用Netty服务器来处理传入的请求。Netty服务器使用Java的非阻塞I/O(NIO),这保证了当Netty服务器使用了相对较少的线程来处理请求的高性能。
Avro Source允许用户配置线程的最大数量,但实际线程受JVM、操作系统、硬件等的限制。

Keystore是用Java标准定义的加密密钥和证书的集合,每隔keystore受可以用来加载keystore的密码保护。 在Flume实例中,密码以纯文本存储在Flume配置文件中,配置文件必须以恰当的权限来保护,以避免密码落入他人手中。

使用的加密算法通过Java安全属性文件里的ssl.KeyManagerFactory.algorithm定义,如果Java文件中这个参数没有设置,就会使用SunX509算法。【Java安全指南】

Avro Sink和Flume RPC客户端可以配置用于发送数据给Avro Source之前压缩数据,如果数据在广域网或数据中心之间的传输时,这个非常有用的,能够减少使用的宽带。
目前Avro Source仅对RPC支持zlib压缩,为了使Avro Source能以压缩的形式接收数据,需要将compression-type参数设置为deflate。
如果这个参数没有设置或者设置为none,Flume将不会解压数据,这可能导致事件积压在前一阶段(因为Source讲不能解析压缩数据,会给前一段返回错误,将导致该阶段一直重试)

如果compression-type参数设置为deflate,那么传入的数据必须被压缩,否则Source不能解析传入的数据。所以,Sink或Flume客户端必须配置为压缩将要发送的数据。

因此,如果压缩和为压缩的数据被传输到相同的Flume Agent时,agent应该能运行两种Avro Source:一种用来接收压缩的数据,另一种用来接收未压缩的数据。

当Avro Sink或Flume RPC客户端发送数据到Avro Source时,数据是分批被压缩的,而不是按照每个事件,因此这可能会提供更好的压缩率,减少压缩内存的使用情况。

ipFilter.rules定义格式如下 :
::

allow/deny:ip/name:pattern

例如:
a1.sources.r1.ipFilter = true
a1.sources.r1.ipFilter.rules = allow:ip:127.,allow:name:localhost,deny:ip:
三、Avro 配置实例
1.一个单点avro例子
配置文件 testAvro.conf
#test avro sources
a1.sources=r1
a1.channels=c1
a1.sinks=k1

a1.sources.r1.type = avro
a1.sources.r1.channels=c1
a1.sources.r1.bind=192.168.1.102
a1.sources.r1.port=55555

#Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity=1000
a1.channels.c1.transactionCapacity = 100

#sink配置
a1.sinks.k1.type=logger
a1.sinks.k1.channel=c1

启动flume服务
$ bin/flume-ng agent -c conf -f conf/testAvro.conf -n a1 -Dflume.root.logger=INFO,console

测试
$ bin/flume-ng avro-client -c conf -H 192.168.1.102 -p 55555 -F /app/logs/test.log

  1. avro source ssl例子
    使用keytool工具创建keystore.jks和truststore.jks文件

在conf下新建serverSSL.conf文件
#server
a2.sources=avroSrc
a2.channels=memChannel
a2.sinks=loggerSink
a2.sources.avroSrc.type=avro
a2.sources.avroSrc.channels=memChannel
#Bind to all Interface
a2.sources.avroSrc.bind=192.168.1.102
a2.sources.avroSrc.port=4353
#开启SSL
a2.sources.avroSrc.ssl=true
a2.sources.avroSrc.keystore=/Users/pengqiang/Program/keystore.jks
a2.sources.avroSrc.keystore-password=*******
a2.sources.avroSrc.keystore-type=JKS
#开启压缩
a2.sources.avroSrc.compression-type=deflate
a2.channels.memChannel.type=memory
a2.channels.memChannel.capacity=1000
a2.channels.memChannel.transactionCapacity = 100

#Describe the sink
a2.sinks.loggerSink.type = logger
a2.sinks.loggerSink.channel=memChannel
启动命令:$ bin/flume-ng agent -c conf -f conf/serverSSL.conf -n a2 -Dflume.root.logger=INFO,console

在conf下新建clientSSL.conf文件
a1.sinks=avroSink
a1.channels=c1
a1.sources.r1.type = exec
a1.sources.r1.command=tail -F /app/logs/test.log
a1.sources.r1.channels=c1
#Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity=1000
a1.channels.c1.transactionCapacity = 100
#sink配置
a1.sinks.avroSink.type=avro
a1.sinks.avroSink.channel=c1
a1.sinks.avroSink.hostname=192.168.1.102
a1.sinks.avroSink.port=4353
a1.sinks.avroSink.ssl=true
a1.sinks.avroSink.trust-all-certs=true
a1.sinks.avroSink.truststore=/Users/pengqiang/Program/truststore.jks
a1.sinks.avroSink.truststore-type=JKS
a1.sinks.avroSink.truststore-password=*****
a1.sinks.avroSink.compression-type=deflate
启动命令: $ bin/flume-ng agent -c conf -f conf/clientSSL.conf -n a1 -Dflume.root.logger=INFO,console

测试验证

$ vim /app/logs/test.log

四、Avro Sink介绍
Avro Sink使用Avro的Netty-based RPC协议发送数据到Avro Source。它被实现为一个感知事务的Flume NettyAvroRpcClient的包装器。

Avro Sink可以批量发送事件到Avro Source.
五、Avro Sink参数

表格说明
参数 默认值 描述
type
Avro Sink别名为avro,也可以使用FQCN(org.apache.flume.sink.AvroSink)
hostname
托管Agent机器的主机名,Sink应该连接的Source在该Agent上

port
Sink连接的Source的监听端口
batch-size 100 每个RPC调用发送的事件数量。也是在单次事务中Sink从Channel中读取的事件数量
compression-type
用来压缩传入数据的压缩格式。Flume1.5只支持zlib的压缩格式,如果要接收zlib压缩的
数据,需要叫compression-type设置为deflate

compression-level 6 压缩级别,有效值1~9,数值越高,压缩的越好
connect-timeout 20000 最初的连接和握手协议完成的超时,单位:毫秒
request-timeout 20000 整个RPC调用成功完成超时
ssl false 加密套接字协议层(一种加密的通讯协定,用在使用者与网服器之间)
trust-all-certs false 如果设置为true,则Sink接受所有的SSL
truststore

使用的truststore文件的路径
truststore-password

用来打开trust store的密码
truststore-type JKS java trust store类型
reset-connection-interval

Sink从Source断开连接并重新连接之后的间隔

Avro Sink在通过线路发送数据之前可以压缩数据。压缩级别1~9,虽然9代表最好的压缩,但是在Sink压缩和Source解压缩所花费的时间也越多。

Avro Sink支持使用SSL进行加密通信。Source接收数据也必须配置为从Avro Sink接收加密数据。除非指定,Flume将使用Java默认的JSSE证书授权文件,jssecacerts/cacerts,来判断Avro Source的SSL证书是否可信。

trust-all-certs为true时,表示Sink发送数据时不需要检查Source的SSL证书

大多数情况下,Agent之间在中间利用负载均衡器相互通信。
六、Avro Source源码
1.configure

@Override
public void configure(Context context) {
Configurables.ensureRequiredNonNull(context, PORT_KEY, BIND_KEY);

port = context.getInteger(PORT_KEY);
bindAddress = context.getString(BIND_KEY);
compressionType = context.getString(COMPRESSION_TYPE, "none");

try {
  maxThreads = context.getInteger(THREADS, 0);
} catch (NumberFormatException e) {
  logger.warn("AVRO source\'s \"threads\" property must specify an integer value.",
          context.getString(THREADS));
}

enableSsl = context.getBoolean(SSL_KEY, false);
keystore = context.getString(KEYSTORE_KEY);
keystorePassword = context.getString(KEYSTORE_PASSWORD_KEY);
keystoreType = context.getString(KEYSTORE_TYPE_KEY, "JKS");
String excludeProtocolsStr = context.getString(EXCLUDE_PROTOCOLS);
if (excludeProtocolsStr == null) {
  excludeProtocols.add("SSLv3");
} else {
  excludeProtocols.addAll(Arrays.asList(excludeProtocolsStr.split(" ")));
  if (!excludeProtocols.contains("SSLv3")) {
    excludeProtocols.add("SSLv3");
  }
}

if (enableSsl) {
  Preconditions.checkNotNull(keystore,
      KEYSTORE_KEY + " must be specified when SSL is enabled");
  Preconditions.checkNotNull(keystorePassword,
      KEYSTORE_PASSWORD_KEY + " must be specified when SSL is enabled");
  try {
    KeyStore ks = KeyStore.getInstance(keystoreType);
    ks.load(new FileInputStream(keystore), keystorePassword.toCharArray());
  } catch (Exception ex) {
    throw new FlumeException(
        "Avro source configured with invalid keystore: " + keystore, ex);
  }
}

enableIpFilter = context.getBoolean(IP_FILTER_KEY, false);
if (enableIpFilter) {
  patternRuleConfigDefinition = context.getString(IP_FILTER_RULES_KEY);
  if (patternRuleConfigDefinition == null ||
    patternRuleConfigDefinition.trim().isEmpty()) {
    throw new FlumeException(
      "ipFilter is configured with true but ipFilterRules is not defined:" +
        " ");
  }
  String[] patternRuleDefinitions = patternRuleConfigDefinition.split(
    ",");
  rules = new ArrayList<IpFilterRule>(patternRuleDefinitions.length);
  for (String patternRuleDefinition : patternRuleDefinitions) {
    rules.add(generateRule(patternRuleDefinition));
  }
}

if (sourceCounter == null) {
  sourceCounter = new SourceCounter(getName());
}

}

2.start

lifecycleAware 会调用start方法启动avroSource。avroSource主要启动了一个NettyServer用于接收数据,然后交由avroSource处理。

@Override
public void start() {
logger.info(“Starting {}…”, this);

Responder responder = new SpecificResponder(AvroSourceProtocol.class, this);

NioServerSocketChannelFactory socketChannelFactory = initSocketChannelFactory();

ChannelPipelineFactory pipelineFactory = initChannelPipelineFactory();

server = new NettyServer(responder, new InetSocketAddress(bindAddress, port),
      socketChannelFactory, pipelineFactory, null);

connectionCountUpdater = Executors.newSingleThreadScheduledExecutor();
server.start();
sourceCounter.start();
super.start();
final NettyServer srv = (NettyServer)server;
connectionCountUpdater.scheduleWithFixedDelay(new Runnable(){

  @Override
  public void run() {
    sourceCounter.setOpenConnectionCount(
            Long.valueOf(srv.getNumActiveConnections()));
  }
}, 0, 60, TimeUnit.SECONDS);

logger.info("Avro source {} started.", getName());

}

3.当AvroSource接收到数据时,会调用append函数,append函数会调用getChannelProcessor().processEvent处理接收的event

@Override
public Status append(AvroFlumeEvent avroEvent) {
logger.debug(“Avro source {}: Received avro event: {}”, getName(),
avroEvent);
sourceCounter.incrementAppendReceivedCount();
sourceCounter.incrementEventReceivedCount();

Event event = EventBuilder.withBody(avroEvent.getBody().array(),
    toStringMap(avroEvent.getHeaders()));

try {
  getChannelProcessor().processEvent(event);
} catch (ChannelException ex) {
  logger.warn("Avro source " + getName() + ": Unable to process event. " +
      "Exception follows.", ex);
  return Status.FAILED;
}

sourceCounter.incrementAppendAcceptedCount();
sourceCounter.incrementEventAcceptedCount();

return Status.OK;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值