除了Flume内置的客户端,我们也可以自定义客户端向Flume发送数据。目前Flume支持自定义客户端通过Avro、Thrift、Log4j、Syslog和HTTP POST(JSON格式)发送的数据。客户端发送的数据必须是Flume能够识别的Event格式。
Flume SDK是一个提供Flume连接和向Flume发送数据(通过RPC)的类库。Flume SDK封装了底层的细节,只提供了统一接口,包括Flume连接、Event封装和Event发送等。Flume SDK可以通过Maven方式引用到项目中。
<dependency>
<groupId>org.apache.flume</groupId>
<artifactId>flume-ng-sdk</artifactId>
<version>1.6.0</version>
</dependency>
Event有两个实现类SimpleEvent和JSONEvent。JSONEvent发送JSON格式数据,主要由HTTP Source接收。SimpleEvent和JSONEvent在使用上并没有区别。可以通过EventBuilder的静态方法创建Event,EventBuilder默认创建SimpleEvent。
Event示例代码
String logBody = "这里是日志内容";
// 日志头文件,头文件是可选的
Map<String, String> logHeaders = new HashMap<String, String>();
// 给日志添加时间戳
logHeaders.put("timestamp", System.currentTimeMillis() + "");
// SimpleEvent
Event simpleEvent = new SimpleEvent();
simpleEvent.setBody(logBody.getBytes());
simpleEvent.setHeaders(logHeaders); // 头文件是可选的
// JSONEvent
Event jsonEvent = new JSONEvent();
jsonEvent.setBody(logBody.getBytes());
jsonEvent.setHeaders(logHeaders); // 头文件是可选的
// EventBuilder
EventBuilder.withBody(logBody.getBytes());
EventBuilder.withBody(logBody.getBytes(), logHeaders);
Flume连接和Event发送由RpcClient接口提供,RpcClient有两个基本实现类NettyAvroRpcClient和ThriftRpcClient,分别使用Avro协议和Thrift协议。RpcClient可以通过静态方法RpcClientFactory.getInstance(),getInstance有多个重载方法,如果不指定协议类型,默认使用Avro协议。
/** * 返回NettyAvroRpcClient实例 * @param IP地址 * @param 端口 */
public static RpcClient getDefaultInstance(String hostname, Integer port) throws FlumeException;
/** * 返回ThriftRpcClient实例 * @param IP地址 * @param 端口 */
public static RpcClient getThriftInstance(String hostname, Integer port) throws FlumeException;
/** * 返回RpcClient实例,实例类型在配置项client.type中指定 * @param properties 配置文件 */
public static RpcClient getInstance(Properties properties) throws FlumeException;
RpcClient配置可选参数
# 可选值为default和thrift,其中default表示使用avro协议
client.type = default
# 主机名称,只能配置一个名称,如果有多个名称,第一个名称有效。
hosts = h1
# h1主机的ip和端口
hosts.h1 = host1.example.org:41414
# 批量发送的数量,该值必须大于0,默认是100。
batch-size = 100
# 连接超时,该值必须大于1000,默认是20000,单位毫秒。
connect-timeout = 20000
# 请求超时,该值必须大于1000,默认是20000,单位毫秒。
request-timeout = 20000
RpcClient示例代码
import java.nio.charset.Charset;
import java.util.Properties;
import org.apache.flume.Event;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.api.RpcClient;
import org.apache.flume.api.RpcClientFactory;
import org.apache.flume.event.EventBuilder;
public class FlumeClient {
private static RpcClient client;
private static Charset charset = Charset.forName("UTF-8");
// type取值default,创建NettyAvroRpcClient实例。取值thrift,创建ThriftRpcClient实例。
private static String type = "default";
private static String hostname = "127.0.0.1";
private static String port = "41414";
public static void main(String[] args) {
init();
for(int i = 0; i < 10; i++){
send("发送第" + i + "条数据");
}
}
public static void init(){
Properties props = new Properties();
props.put("client.type", type);
props.put("hosts", "h1");
props.put("host.h1", hostname + ":" + port);
client = RpcClientFactory.getInstance(props);
}
public static void send(String data){
Event event = EventBuilder.withBody(data, charset);
try {
client.append(event);
} catch (EventDeliveryException e) {
e.printStackTrace();
// 如果连接失败,重置client
client.close();
init();
}
}
}
FailoverRpcClient是RpcClient的实现类,该类包装了NettyAvroRpcClient,实现故障转移功能。故障转移客户端类只能使用Avro协议。
FailoverRpcClient可选配置参数
# client.type必须为default_failover
client.type = default_failover
# 那么hosts至少要配置两台主机。
hosts = h1 h2 h3
# 主机配置
hosts.h1 = host1.example.org:41414
hosts.h2 = host2.example.org:41414
hosts.h3 = host3.example.org:41414
# 如果主机连接失败,是否把主机临时放入黑名单中,过一段时间再启用。
# 默认为false,不放入黑名单。
backoff = false
# 主机连接失败,下次连接该主机的最大时间间隔,单位毫秒。
# 默认值为0,相当于30000毫秒。
maxBackoff = 0
# 批量发送的数量,该值必须大于0,默认是100。
batch-size = 500
# 连接超时,该值必须大于1000,默认是20000,单位毫秒。
connect-timeout = 20000
# 请求超时,该值必须大于1000,默认是20000,单位毫秒。
request-timeout = 20000
FailoverRpcClient示例代码
Properties props = new Properties();
props.put("client.type", "default_failover");
// 主机列表
props.put("hosts", "h1 h2 h3");
// 主机地址和端口
String host1 = "host1.example.org:41414";
String host2 = "host2.example.org:41414";
String host3 = "host3.example.org:41414";
props.put("hosts.h1", host1);
props.put("hosts.h2", host2);
props.put("hosts.h3", host3);
RpcClient client = RpcClientFactory.getInstance(props);
LoadBalancingRpcClient和FailoverRpcClient一样,都包装了NettyAvroRpcClient。负载均衡客户端根据策略向Flume集群发送数据,负载均衡策略包括round_robin和random。
LoadBalancingRpcClient可选配置参数
# client.type必须为default_loadbalance
client.type = default_loadbalance
# 主机配置
hosts.h1 = host1.example.org:41414
hosts.h2 = host2.example.org:41414
hosts.h3 = host3.example.org:41414
# 如果主机连接失败,是否把主机临时放入黑名单中,过一段时间再启用。
# 默认为false,不放入黑名单。
backoff = false
# 负载均衡轮询策略
# 可选策略有round_robin、random或者自定义策略(实现LoadBalancingRpcClient$HostSelector接口)。
# 默认是round_robin
host-selector = round_robin
# 主机连接失败,下次连接该主机的最大时间间隔,单位毫秒。
# 默认值为0,相当于30000毫秒。
maxBackoff = 0
# 批量发送的数量,该值必须大于0,默认是100。
batch-size = 500
# 连接超时,该值必须大于1000,默认是20000,单位毫秒。
connect-timeout = 20000
# 请求超时,该值必须大于1000,默认是20000,单位毫秒。
request-timeout = 20000
LoadBalancingRpcClient示例代码
Properties props = new Properties();
props.put("client.type", "default_loadbalance");
props.put("hosts", "h1 h2 h3");
String host1 = "host1.example.org:41414";
String host2 = "host2.example.org:41414";
String host3 = "host3.example.org:41414";
props.put("hosts.h1", host1);
props.put("hosts.h2", host2);
props.put("hosts.h3", host3);
props.put("host-selector", "random");
//props.put("host-selector", "round_robin");
props.put("backoff", "true");
props.put("maxBackoff", "10000");
RpcClient client = RpcClientFactory.getInstance(props);