Flume简介与使用(二)——Thrift Source采集数据
Flume简介与使用(二)——Thrift Source采集数据
继上一篇安装Flume后,本篇将介绍如何使用Thrift Source采集数据。
Thrift是Google开发的用于跨语言RPC通信,它拥有功能强大的软件堆栈和代码生成引擎,允许定义一个简单的IDL文件来生成不同语言的代码,服务器端和客户端通过共享这个IDL文件来构建来完成通信。
Flume的Thrift Source是其实现的众多Source中的一个,Flume已经实现了服务器端,因此我们可以用任意自己熟悉的语言编写自己的Thrift Source客户端来采集数据,然后发送给Thrift Source服务器端。
[一]、生成C++代码
下载源码版的Flume,在apache-flume-1.6.0-src\flume-ng-sdk\src\main\thrift目录下有Flume定义好的flume.thrift文件,现在只要用这个文件来生成我们需要的代码就行了。
flume.thrift文件内容如下:
namespace java org.apache.flume.thrift
struct ThriftFlumeEvent {
1: required map <string, string> headers,
2: required binary body,
}
enum Status {
OK,
FAILED,
ERROR,
UNKNOWN
}
service ThriftSourceProtocol {
Status append(1: ThriftFlumeEvent event),
Status appendBatch(1: list<ThriftFlumeEvent> events),
}
1、定义了一个ThriftFlumeEvent结构体,用来封装发送的数据;
2、定义了一个service类ThriftSourceProtocol,服务器端具体实现ThriftSourceProtocol里面的两个方法,再由客户端调用这些方法把数据传给Thrift Source服务器端。
3、运行下面的命令:thrift --gen cpp flume.thrift,会在当前目录生成gen-cpp目录,里面是Thrift自动生成c++头文件和代码。(在这之前要先安装Thrift)

[二]、下面是编写自己的客户端代码,我这里是接收远程传过来的数据,然后发送给Flume的Thrift Source服务器。
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include "include/MESA_prof_load.h"
#include "include/MESA_handle_logger.h" #include <string>
#include <iostream>
#include "gen-cpp/flume_constants.h"
#include "gen-cpp/flume_types.h"
#include "gen-cpp/ThriftSourceProtocol.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TCompactProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport; #define LOG_PATH "/home/zjf/DFcode/trafficlog/traffic_source.log"
#define DATA_BUFFER 2048 //send buffer data length
#define BUFLEN 2048 //received buffer data length
#define BATCH_SIZE 1000 //send event num to flume once //defined my C++ object
class ThriftClient{
public:
// Thrift protocol needings...
boost::shared_ptr<TTransport> socket;
boost::shared_ptr<TTransport> transport;
boost::shared_ptr<TProtocol> protocol;
ThriftSourceProtocolClient* pClient; public:
ThriftClient();
};
//cconstruction function, init the thrift source server ip and port
ThriftClient::ThriftClient():
socket(new TSocket("10.208.129.12",)),
transport(new TFramedTransport(socket)),
protocol(new TCompactProtocol(transport))
{
pClient = new ThriftSourceProtocolClient(protocol);
} //log
struct log_info_t{
char *path;
int log_level;
void * handle;
};
struct log_info_t log_info;
const char *module = "zjf_traffic_data_collector"; //类的对象
ThriftClient *client = new ThriftClient();
std::map<std::string, std::string> headers;
std::vector<ThriftFlumeEvent> eventbatch;
unsigned long long pkt_num_tgl = ; int RecvAndSendUDP(){
MESA_handle_runtime_log(log_info.handle, RLOG_LV_INFO, module, "RecvUDP be called");
int listen_socket; //socket id
struct sockaddr_in local; //client IP, where to recevied data
struct sockaddr_in from; //server IP(local host)
char server_addr[] = "10.208.129.12"; //received traffic IP
int server_port = ; //received traffic port
char send_buf[DATA_BUFFER] = {}; //data send to flume
char Buf[BUFLEN] = {};
int fromlen;
int len; //init socket
reconnect:
memset(&local, , sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr(server_addr);
local.sin_port = htons(server_port);
listen_socket = socket(AF_INET, SOCK_DGRAM, ); // UDP socket
if(listen_socket < ) {
printf("error udp socket\n");
}else{
printf("listen_socket create OK\n");
}
if(bind(listen_socket, (struct sockaddr *)&local, sizeof(local)) < ) {
printf("error udp bind\n");
return -;
}else{
printf("socket bind OK\n");
} while(){
char sip[] = {};
char dip[] = {};
char srcport[] = {};
char destport[] = {};
char url[BUFLEN] = {};
memset(Buf,,BUFLEN);
fromlen = sizeof(from);
len = recvfrom(listen_socket, (void *)Buf, (size_t)BUFLEN, , (struct sockaddr *)&from,(socklen_t *)&fromlen);
if(len == -) {
printf("error udp recvfrom\n");
close(listen_socket);
goto reconnect;
}
//parse received buf, transform to key-value
int i;
int sip_loc = ;
int sport_loc = ;
int dip_loc = ;
int dport_loc = ;
int dotcount = ;
for(i=;Buf[i] != '\0';i++){
if(Buf[i] == '.'){
dotcount++;
if(dotcount == ){
sip_loc = i;
memcpy(sip,Buf,i);
}
else if(dotcount == ){
dip_loc = i;
memcpy(dip,Buf+sport_loc+,dip_loc-sport_loc-);
}
else if(dotcount == ){
dport_loc = i;
memcpy(destport,Buf+dip_loc+,dport_loc-dip_loc-);
break;
}
else{}
}
if(Buf[i] == '>'){
sport_loc = i;
memcpy(srcport,Buf+sip_loc+,sport_loc-sip_loc-);
}
}
memcpy(url,Buf+dport_loc+,strlen(Buf)-dport_loc);
unsigned long src_ip = inet_addr(sip);
unsigned long dst_ip = inet_addr(dip);
sprintf(send_buf,"SrcIP=%u SrcPort=%s DestIP=%u DestPort=%s",ntohl(src_ip),srcport,ntohl(dst_ip),destport);
//construct an event and append to send
if( != strlen(send_buf) ){
pkt_num_tgl++;
string sBody(send_buf);
ThriftFlumeEvent tfEvent;
tfEvent.__set_headers(headers);
tfEvent.__set_body(sBody);
eventbatch.push_back(tfEvent);
if(eventbatch.size() >= BATCH_SIZE){
if(!client->transport->isOpen())
client->transport->open();
Status::type res = client->pClient->appendBatch(eventbatch);
if(res != Status::OK){
MESA_handle_runtime_log(log_info.handle, RLOG_LV_FATAL, module, "WARNING: send event via thrift failed, return code:%d",res);
}else{
//printf("sended %lld event data to flume successful\n", pkt_num_tgl);
}
eventbatch.clear();
}
}
bzero(send_buf,DATA_BUFFER);
}
} int main()
{
//create――logger
log_info.path = (char *)LOG_PATH;
log_info.log_level = ;
log_info.handle = MESA_create_runtime_log_handle(log_info.path, log_info.log_level);
//open thrift connection
if(!client->transport->isOpen()){
client->transport->open();
}
eventbatch.clear();
RecvAndSendUDP();
return ;
}
[三]、编译并运行
g++ -g -DHAVE_NETINET_IN_H -I. -I/usr/local/include/thrift -L/usr/local/lib rec_send_traffic_thrift.cpp gen-cpp/flume_constants.cpp gen-cpp/flume_types.cpp gen-cpp/ThriftSourceProtocol.cpp -o rec_send_traffic_thrift -lthrift -lpcap -L/usr/lib64 -lMESA_htable -lpthread -lMESA_handle_logger
用守护进程启动程序:
#!/bin/sh while [ ]; do
ulimit -c unlimited
#./jz
#cgexec -g cpu,memory:/MESA/jz ./jz >> jz.log
./rec_send_traffic_thrift
#./jz
echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log
sleep
done
推荐博文:【1】http://www.micmiu.com/soa/rpc/thrift-sample/
【2】http://www.mamicode.com/info-detail-869223.html
【3】http://blog.csdn.net/yuzx2008/article/details/50179033
【4】http://shiyanjun.cn/archives/456.html
【5】http://flume.apache.org/FlumeDeveloperGuide.html#rpc-clients-avro-and-thrift
转载请注明原文出处,谢谢
Flume简介与使用(二)——Thrift Source采集数据的更多相关文章
- 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考
本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...
- Flume简介与使用(一)——Flume安装与配置
Flume简介与使用(一)——Flume安装与配置 Flume简介 Flume是一个分布式的.可靠的.实用的服务——从不同的数据源高效的采集.整合.移动海量数据. 分布式:可以多台机器同时运行采集数据 ...
- 01_日志采集框架Flume简介及其运行机制
离线辅助系统概览: 1.概述: 在一个完整的大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集.结果数据导出. 任务调度等不可或缺的辅助系统,而这些辅助 ...
- [ETL] Flume 理论与demo(Taildir Source & Hdfs Sink)
一.Flume简介 1. Flume概述 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据: ...
- Flume 简介及基本使用
一.Flume简介 Apache Flume是一个分布式,高可用的数据收集系统.它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集.Flume 分为 NG 和 OG (1 ...
- 入门大数据---Flume 简介及基本使用
一.Flume简介 Apache Flume 是一个分布式,高可用的数据收集系统.它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集.Flume 分为 NG 和 OG ( ...
- Flume简介及安装
Hadoop业务的大致开发流程以及Flume在业务中的地位: 从Hadoop的业务开发流程图中可以看出,在大数据的业务处理过程中,对于数据的采集是十分重要的一步,也是不可避免的一步,从而引出我们本文的 ...
- Flume简介与使用(三)——Kafka Sink消费数据之Kafka安装
前面已经介绍了如何利用Thrift Source生产数据,今天介绍如何用Kafka Sink消费数据. 其实之前已经在Flume配置文件里设置了用Kafka Sink消费数据 agent1.sinks ...
- Flume 1.7 源代码分析(四)从Source写数据到Channel
Flume 1.7 源代码分析(一)源代码编译 Flume 1.7 源代码分析(二)总体架构 Flume 1.7 源代码分析(三)程序入口 Flume 1.7 源代码分析(四)从Source写数据到C ...
随机推荐
- 2014 多校联合训练赛6 Fighting the Landlords
本场比赛的三个水题之一,题意是两个玩家每人都持有一手牌,问第一个玩家是否有一种出牌方法使得在第一回和对方无牌可出.直接模拟即可,注意一次出完的情况,一开始没主意,wa了一发. #include< ...
- python 遇到 syntaxerror: non-ascii character '/xd6' in file 我 教你解决 (python问题)(转)
遇到标题上的问题,按照我的解决广方案来吧 ===================================== (一) 用记事本创建一个文件ChineseTest.py,默认ANSI: s = ...
- Zabbix探索:LDAP的认证方式
这两天部署了Zabbix测试环境,终于用Puppet部署完成了.总是存在一些小问题,如服务不起动啦之类的. LDAP验证方式配置 刚刚配置Zabbix的用户管理,使用LDAP方式认证. 比较惊喜的是L ...
- java创建对象的四种方式
1.最常见的 new 一个 2使用反射机制创建对象,直接调用非构造函数 Class obj=Class.forName("A"); A a=obj.newInstance(); C ...
- 决策树学习(ID3)
参考:<机器学习实战> 优点:计算复杂度不高, 输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特 征数据. 缺点:可能会产生过度匹配问题. 适用数据类型:数值型和标称型. 创建分支 ...
- 微软CEO私享会——广东天使会专场圆满落幕
http://www.cnblogs.com/sennly/p/4140976.html 10月17日,微软中国联合广东天使会首期“微软CEO 私享会”在中国微软广东分公司广州太古汇办公室举 ...
- Android实例-程序界面内截取屏幕(XE8+小米2)
结果: 1.只能截取程序界面内的图片. 2.图片有点不清楚,自己设置清楚度. 实例代码: unit Unit1; interface uses System.SysUtils, System.Type ...
- A Tour of Go Interfaces are satisfied implicitly
A type implements an interface by implementing the methods. There is no explicit declaration of inte ...
- [C语言 - 12] Union联合
union Student { int age; char *name; } stu; union只按照最长的数据成员分配控件,适用于有N个数据不会同时出现的情况,用以压缩空间.
- RxJava的使用
前言 RxJava及RxAndroid比较详细的介绍可以参考该文档<给 Android 开发者的 RxJava 详解> 基本介绍 ReactiveX 及 RxJava使用大部分来自和参考& ...