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采集数据的更多相关文章

  1. 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考

    本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...

  2. Flume简介与使用(一)——Flume安装与配置

    Flume简介与使用(一)——Flume安装与配置 Flume简介 Flume是一个分布式的.可靠的.实用的服务——从不同的数据源高效的采集.整合.移动海量数据. 分布式:可以多台机器同时运行采集数据 ...

  3. 01_日志采集框架Flume简介及其运行机制

    离线辅助系统概览: 1.概述: 在一个完整的大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集.结果数据导出. 任务调度等不可或缺的辅助系统,而这些辅助 ...

  4. [ETL] Flume 理论与demo(Taildir Source & Hdfs Sink)

    一.Flume简介 1. Flume概述 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据: ...

  5. Flume 简介及基本使用

    一.Flume简介 Apache Flume是一个分布式,高可用的数据收集系统.它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集.Flume 分为 NG 和 OG (1 ...

  6. 入门大数据---Flume 简介及基本使用

    一.Flume简介 Apache Flume 是一个分布式,高可用的数据收集系统.它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集.Flume 分为 NG 和 OG ( ...

  7. Flume简介及安装

    Hadoop业务的大致开发流程以及Flume在业务中的地位: 从Hadoop的业务开发流程图中可以看出,在大数据的业务处理过程中,对于数据的采集是十分重要的一步,也是不可避免的一步,从而引出我们本文的 ...

  8. Flume简介与使用(三)——Kafka Sink消费数据之Kafka安装

    前面已经介绍了如何利用Thrift Source生产数据,今天介绍如何用Kafka Sink消费数据. 其实之前已经在Flume配置文件里设置了用Kafka Sink消费数据 agent1.sinks ...

  9. Flume 1.7 源代码分析(四)从Source写数据到Channel

    Flume 1.7 源代码分析(一)源代码编译 Flume 1.7 源代码分析(二)总体架构 Flume 1.7 源代码分析(三)程序入口 Flume 1.7 源代码分析(四)从Source写数据到C ...

随机推荐

  1. HNU OJ10320 穿越火线 简单模拟

    穿越火线 Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB Total submit users: 12, A ...

  2. vs2015无法解析外部符号__imp__fprintf

    使用vs2015编译ffmpeg的一个小项时,出现了__imp__fprintf和__imp____iob_func 的错误,google了一下,有的人 建议下载SDL源码重新编译一下,当然这个方案非 ...

  3. tomcat Connector 连接器

    连接器的核心功能,本文去除非核心功能,留下整个程序的框架,便于理解. 1.接受连接请求 2.创建request,和response. 3.调用容器对应的Invoke方法, 首先看类的依赖结构. 1.C ...

  4. Redhat常见问题

    1.现象:hadoop用户启动startx时失败,报如下提示 Fatal server error: PAM authentication failed, cannot start X server. ...

  5. Docker系列(六)路由打通网络示例

    运行环境 两台虚拟机IP分别为:192.168.0.103(简称:A主机).192.168.0.104(简称:B主机) 操作系统:Centos 7 Docker版本:1.8 Mysql镜像配置 1.在 ...

  6. HW5.27

    public class Solution { public static void main(String[] args) { int totalCount = 0; int lineCount = ...

  7. Linq to Sql 总生成 where ID is null 的解决办法

    using (Entities com = new Entities()){     com.Configuration.UseDatabaseNullSemantics = true; } EF+M ...

  8. hdu 1491 Octorber 21st

    Octorber 21st Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. iOS CAShapeLayer精讲

    前言 CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性.但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义. 关于UIBezierPath,请阅读文章:i ...

  10. iOS几个效果动画-------------------(实例详讲)qq粘性效果

    这几天做了一些简单iOS的效果图,感觉苹果官方已经帮我们做了很多了,我们只是站在巨人的肩膀上编程,这些也没什么难的,最难的也就是用到了初中的三角函数,先让大家看看这几个动画吧.先列这几个把,由上而下分 ...