问题 : Avro Source提供了怎么样RPC服务,是怎么提供的?

问题 1.1 Flume Source是如何启动一个Netty Server来提供RPC服务。

由GitHub上avro-rpc-quickstart知道可以通过下面这种方式启动一个NettyServer,来提供特定的RPC。那么Flume Source 是通过这种方法来提供的RPC服务吗?

  server = new NettyServer(new SpecificResponder(Mail.class, new MailImpl()), new InetSocketAddress(65111));

AvroSource中创建NettyServer的源码为:

  

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

    NioServerSocketChannelFactory socketChannelFactory = initSocketChannelFactory();

    ChannelPipelineFactory pipelineFactory = initChannelPipelineFactory();

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

  看来AvroSource也是直接用Avro提供的NettyServer类来建立了一个NettyServe,不过它使用了另一个构造函数,指定了ChannelFactory和ChannelPipelineFactory.

  那么AvroSource使用的是怎么样的一个ChannelFactory呢?

  initSocketChannelFactory()方法的实现为:

  private NioServerSocketChannelFactory initSocketChannelFactory() {
NioServerSocketChannelFactory socketChannelFactory;
if (maxThreads <= 0) {
socketChannelFactory = new NioServerSocketChannelFactory
(Executors .newCachedThreadPool(), Executors.newCachedThreadPool());
} else {
socketChannelFactory = new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newFixedThreadPool(maxThreads));
}
return socketChannelFactory;
}

  看来之所以要指定ChannelFactory,是为了根据AvroSource的"threads”这个参数,来决定可以使用worker thread的最大个数。这个数字决定了最多有多少个线程来处理RPC请求。

  参见NioServerChannelFactory的说明

  

A ServerSocketChannelFactory which creates a server-side NIO-based ServerSocketChannel. It utilizes the non-blocking I/O mode which was introduced with NIO to serve many number of concurrent connections efficiently.

How threads work

There are two types of threads in a NioServerSocketChannelFactory; one is boss thread and the other is worker thread.

Boss threads

Each bound ServerSocketChannel has its own boss thread. For example, if you opened two server ports such as 80 and 443, you will have two boss threads. A boss thread accepts incoming connections until the port is unbound. Once a connection is accepted successfully, the boss thread passes the accepted Channel to one of the worker threads that the NioServerSocketChannelFactory manages.

Worker threads

One NioServerSocketChannelFactory can have one or more worker threads. A worker thread performs non-blocking read and write for one or more Channels in a non-blocking mode.

  ChannelPipelineFactory是干嘛的呢?为什么也要特化一个?

  ChannelPipleline类的说明为:

  A list of ChannelHandlers which handles or intercepts ChannelEvents of a ChannelChannelPipeline implements an advanced form of the Intercepting Filter pattern to give a user full control over how an event is handled and how the ChannelHandlers in the pipeline interact with each other.

  看来这东西提供了一种更高级的拦截器组合。那就来看看AvroSource是用了怎么样的ChannelPiplelineFactory

  

  private ChannelPipelineFactory initChannelPipelineFactory() {
ChannelPipelineFactory pipelineFactory;
boolean enableCompression = compressionType.equalsIgnoreCase("deflate");
if (enableCompression || enableSsl) {
pipelineFactory = new SSLCompressionChannelPipelineFactory(
enableCompression, enableSsl, keystore,
keystorePassword, keystoreType);
} else {
pipelineFactory = new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline();
}
};
}
return pipelineFactory;
}

  看来如果开启了压缩或者使用了ssl,就使用SSLCompressionChannelPiplelineFactory,这类是AvroSource一个私有的静态内部类。否则就使用Channels.pipleline()新建一个,这个pipleline貌似啥都不做?

  

问题 1.2这样Server是起来了,可是Server提供了什么样的RPC服务呢?

  关键在这一句。

  

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

  查下Avro的API,得知道SpecificResponder的两个参数是protocol和protocol的实现。看起来AvroSource这个类实现了AvroSourceProtocol。Yes, AvroSource的声明为

  

public class AvroSource extends AbstractSource implements EventDrivenSource,Configurable, AvroSourceProtocol

  那就看看AvroSourceProtocol是怎么样定义的吧。它定义在flume-ng-sdk工程的src/main/avro目录下,由flume.avdl定义。avdl是使用Avro IDL定义的协议。放在那个特定的目录下,是avro-maven-plugin的约定。

  这个avdl是这样的

  

@namespace("org.apache.flume.source.avro")

protocol AvroSourceProtocol {

enum Status {
  OK, FAILED, UNKNOWN
}

record AvroFlumeEvent {
  map<string> headers;
  bytes body;
}

Status append( AvroFlumeEvent event );

Status appendBatch( array<AvroFlumeEvent> events );

}

  

  它定义了一个枚举,用作append和appendBatch的返回值。表示Source端对传输来的消息处理的结果,有OK FAILED UNKNOWN三种状态。

  定义了 AvroFlumeEvent这样一个record类型,符合Flume对Event的定义,header是一系列K-V对,即一个Map, body是byte数组。

  定义了两个方法,append单条AvroFlumeEvent,以及append一批AvroFlumeEvent.

  由此avdl,Avro生成了三个java文件,包括:一个枚举Status,一个类AvroFlumeEvent,一个接口AvroSourceProtocol。其中AvroSource类实现了AvroSourceProtocol接口,对外提供了append和appendBatch这两个远程方法调用。

  append方法实现为:

  

  @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;
}

  这个方法就是用获取的AvroFlumeEvent对象,经过转换构建一个Event对象。这个转换只是将不对等的数据类型进行了转换,arvoEvent.getBody()返回的是ByteBuffer,而avroEvent.getHeaders()返回的是Map<CharSequence,CharSequence>。

构建完Event后,把这个消息传递给这个Source对应的ChannelProcessor来处理。

  appendBatch方法和append方法的实现很相似。

Flume的Avro Sink和Avro Source研究之一: Avro Source的更多相关文章

  1. 将线上服务器生成的日志信息实时导入kafka,采用agent和collector分层传输,app的数据通过thrift传给agent,agent通过avro sink将数据发给collector,collector将数据汇集后,发送给kafka

    记flume部署过程中遇到的问题以及解决方法(持续更新) - CSDN博客 https://blog.csdn.net/lijinqi1987/article/details/77449889 现将调 ...

  2. IDEA 编译错误:java: try-with-resources is not supported in -source 1.6 (use -source 7 or higher to enable try-with-resources)

    错误描述 在用IDEA编译别人的项目的时候遇到下面的错误: java: try-with-resources is not supported in -source 1.6 (use -source ...

  3. Maven错误 diamond operator is not supported in -source 1.5 (use -source 7 or higher to enable diamond operator)问题解决

    如果在Maven构建时出现: diamond operator is not supported in -source 1.5 (use -source 7 or higher to enable d ...

  4. Source roots (or source folders) Test source roots (or test source folders; shown as rootTest)Resource rootsTest resource roots

    idea中Mark Directory As里的Sources Root.ReSources Root等的区别 1.Source roots (or source folders) 通过这个类指定一个 ...

  5. Flume的Avro Sink和Avro Source研究之二 : Avro Sink

    啊,AvroSink要复杂好多:< 好吧,先确定主要问题: AvroSink为啥这么多代码?有必要吗?它都有哪些逻辑需要实现? 你看,avro-rpc-quickstart里是这么建client ...

  6. Flume配置Failover Sink Processor

    1 官网内容 2 看一张图一目了然 3 详细配置 source配置文件 #配置文件: a1.sources= r1 a1.sinks= k1 k2 a1.channels= c1 #负载平衡 a1.s ...

  7. Hadoop实战-Flume之Hdfs Sink(十)

    a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = ...

  8. flume 测试 hive sink

    测试flume,将数据送到hive表中,首先建表. create table order_flume( order_id string, user_id string, eval_set string ...

  9. 自定义flume的hbase sink 的序列化程序

    package com.hello.hbase; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import ...

随机推荐

  1. 最新app源码下载:200款优秀Android项目源码

    200款优秀Android项目源码!菜鸟必备!Android开发又将带来新一轮热潮,很多开发者都投入到这个浪潮中去了,创造了许许多多相当优秀的应用.其中也有许许多多的开发者提供了应用开源项目,贡献出他 ...

  2. CSS之边框属性

    border-style 属性用于设置元素所有边框的样式,或者单独地为各边设置边框样式. border-style:dotted solid double dashed; border-style的属 ...

  3. Entity Framework 6.1-Code First

    原文:Entity Framework 6.1-Code First Code First-代码优先,先创建好领域模型.新建MyDbContext继承DbContext.根据代码自动生成数据库 Cod ...

  4. 基于Tengine的反向代理详细配置

    系统环境: SUSE Linux Enterprise Server 10 SP1 (x86_64) 注:所有软件包都放置在/data/software目录下 nginx_tcp_proxy_modu ...

  5. Java开源 开源工作流

    OpenEbXML   点击次数7801 Werkflow   点击次数11181 OSWorkflow   点击次数14988 wfmOpen   点击次数7997 OFBiz   点击次数1234 ...

  6. Cocos移植到Android-Android.mk编译文件

    我们在上一篇博客中年使用的cocos工具对于C和C++源代码进行编译.事实上cocos工具读取<游戏工程目录>\proj.android\jni\目录中的Android.mk文件,进行交叉 ...

  7. iOS学习——iOS视频和推荐网站

    最近有人问有没有iOS学习的相关资料,就简单的把自己的知道的和资源共享一下: 个人感觉iOS开发人才饱和,培训泛滥,个人推荐后台升职空间大和web前端竞争小. [链接][Ronda收集整理]2014年 ...

  8. java 内部类定义在局部时需要注意的情况

    /*内部类定义在局部时,1,不可以被成员修饰符修饰2,可以直接访问外部类中的成员,因为还持有外部类中的引用.    但是不可以访问它所在的局部中的变量.只能访问被final修饰的局部变量.*/clas ...

  9. 关于Fragment的使用与Androikd sdk版本之间的东东

    第一个问题如何使用Fragment? 第二个问题哪些场景适合用Fragment? 第三个问题android.app.fragment与android.support.v4.app.Fragment 为 ...

  10. Nginx日志按天分割

    核心思想:使用crontab在每日23:59执行日志分割. 1.配置nginx日志信息,vim /etc/logrotate.d/nginx /var/log/nginx/*.log { nocomp ...