kafka客户端类


一个项目中实际用到的跨平台的kafka客户端类,vs2013和sentos7实际测试可用

客户端

封装几个简单的函数,给自己留备份,仅供参考。
是针对kafka集群的客户端,而且根据id,做哈希计算后,写入对应的kafka分区,本例子中kafka分区默认为5,复制粘贴的同学自己修改代码。

头文件"kafka_control.h"


#ifndef KAFKA_CONTROL_H
#define KAFKA_CONTROL_H

#ifdef _WIN32
#include ".\librdkafka\include\rdkafka.h"
#else
#include "/home/xby/librdkafka-master/src/rdkafka.h"
#endif


#include <string.h>


class kafka_control
{
private:
	rd_kafka_t *rk;            /*Producer instance handle*/
	rd_kafka_topic_t *rkt;     /*topic对象*/
	rd_kafka_conf_t *conf;     /*临时配置对象*/
	//向kafka发送数据,参数为:① Hadoopid;②要发送的数据
	int SendData(const char* pcWtgHadoopId, const char *pcData, int nPartition);
	size_t my_Hash(const char* pcPara);
static void dr_msg_cb(rd_kafka_t *rk, const rd_kafka_message_t *rkmessage, void *opaque);
public:
	//初始化kafka,pcBrobers是kafka的ip集群
	int InitBrokers(const char *topic, const char *pcBrokers);
	//发送风机scada数据
	int SendWtgScadaData(const char* pcWtgHadoopId, const char *pcData);
	//发送原始数据(或叫波形数据),参数为:① Hadoopid;②要发送的数据
	int SendWaveFormData(const char* pcWtgHadoopId, const char *pcData);
	//发送预警报警数据
	int SendAlarmData( const char *pcData);
	//发送指标数据(或叫特征数据)
	int SendCharacterData(const char *pcData);

};

#endif

源文件"kafka_control.cpp"

// An highlighted block
#ifdef _WIN64 
#pragma comment(lib, ".\\librdkafka\\dll\\x64\\librdkafka.lib")
#else
#pragma comment(lib, ".\\librdkafka\\dll\\x86\\librdkafka.lib")
#endif

#pragma comment(lib,"wsock32.lib")


#include "kafka_control.h"



void kafka_control::dr_msg_cb(rd_kafka_t *rk, const rd_kafka_message_t *rkmessage, void *opaque)
{
	if (rkmessage->err)
		fprintf(stderr, "%% Message delivery failed: %s\n",
		rd_kafka_err2str(rkmessage->err));
	else
	{
/*fprintf(stderr,
		"%% Message delivered (%zd bytes, "
		"partition %"PRId32")\n",
		rkmessage->len, rkmessage->partition);*/
		
	/* rkmessage被librdkafka自动销毁*/

	//printf("send kafka successed ,partition is %d,data len is %d. \r\n", rkmessage->partition, rkmessage->len);
	}
		
}


int kafka_control::InitBrokers(const char *topic, const char *pcBrokers)
{
	if (topic == NULL || pcBrokers == NULL){
		printf("config info have an error :topic name is '%s' ,brokers is '%s'", topic, pcBrokers);
		return -1;
	}
#ifdef _WIN32

	WORD wVerisonRequested;
	WSADATA wsaData;
	int err;
	wVerisonRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVerisonRequested, &wsaData);
	if (err != 0){
		return -1;
	}
#endif
	//rd_kafka_t *rk;            /*Producer instance handle*/
	//rd_kafka_topic_t *rkt;     /*topic对象*/
	//rd_kafka_conf_t *conf;     /*临时配置对象*/
	char errstr[512];
	char brokers[512];
	//const char *topic;
	//CMS数据接入测试环境 TOPIC
	//原始数据:  --partitions 5 --topic cmsdata_test
	//	指标数据:  --partitions 1 --topic cmsmetrics_test
	//	预警数据:  --partitions 1 --topic cmsalarm_test


	//	CMS数据接入生产环境 TOPIC
	//	原始数据:  --partitions 5 --topic cmsdata
	//	指标数据:  --partitions 1 --topic cmsmetrics
	//	预警数据:  --partitions 1 --topic cmsalarm

	//192.168.190.152:9092,192.168.190.152 : 9092,192.168.190.152 : 9092
	"192.168.190.152:9092,192.168.190.153:9092,192.168.190.154:9092";
	//brokers = "192.168.190.152:9092,192.168.190.153:9092,192.168.190.154:9092";
	strcpy(brokers,pcBrokers);
	//brokers = "hadoop2:9092,hadoop3:9092,hadoop4:9092";
	//	topic = "scada_test";
	//const char *topic = "cmsalarm_test";//cmsdata_test //cmsmetrics_test

	/* 创建一个kafka配置占位 */
	conf = rd_kafka_conf_new();

	/*创建broker集群*/
	if (rd_kafka_conf_set(conf, "bootstrap.servers", brokers, errstr,
		sizeof(errstr)) != RD_KAFKA_CONF_OK){
		fprintf(stderr, "%s\n", errstr);
		return 1;
	}

	/*设置发送报告回调函数,rd_kafka_produce()接收的每条消息都会调用一次该回调函数
	*应用程序需要定期调用rd_kafka_poll()来服务排队的发送报告回调函数*/
	rd_kafka_conf_set_dr_msg_cb(conf, this->dr_msg_cb);

	/*创建producer实例
	rd_kafka_new()获取conf对象的所有权,应用程序在此调用之后不得再次引用它*/
	rk = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
	if (!rk){
		fprintf(stderr, " Failed to create new producer:%s\r\n", errstr);
		return 1;
	}

	/*实例化一个或多个topics(`rd_kafka_topic_t`)来提供生产或消费,topic
	对象保存topic特定的配置,并在内部填充所有可用分区和leader brokers,*/
	rkt = rd_kafka_topic_new(rk, topic, NULL);
	if (!rkt)
	{
		fprintf(stderr, "%% Failed to create topic object: %s\n",
			rd_kafka_err2str(rd_kafka_last_error()));
		rd_kafka_destroy(rk);
		return 1;
	}

	return 0;
}

int kafka_control::SendAlarmData(const char *pcData)
{
	this->SendData(NULL, pcData, 0);
	return 0;
}
int kafka_control::SendCharacterData(const char *pcData)
{
	this->SendData(NULL, pcData, 0);
	return 0;
}
int kafka_control::SendWaveFormData(const char* pcWtgHadoopId, const char *pcData)
{
	this->SendData(pcWtgHadoopId, pcData, 5);
	return 0;
}
int kafka_control::SendWtgScadaData(const char* pcWtgHadoopId, const char *pcData)
{
	this->SendData(pcWtgHadoopId, pcData, 5);
	return 0;
}
int kafka_control::SendData(const char* pcWtgHadoopId, const char *pcData, int nPartition)
{
	const char* pcTopic = rd_kafka_topic_name(this->rkt);
	int nPartition1 = 0;
	if (pcWtgHadoopId == NULL){
		nPartition1 = 0;
	}
	else{
		if (nPartition <= 0){
			printf("kafka nPartition have error\r\n");
		}
		 size_t nHashValue = this->my_Hash(pcWtgHadoopId);
		 nPartition1 = nHashValue % nPartition;
	}

	int len = (int)strlen(pcData);
	if (-1 == rd_kafka_produce(
		/* Topic object */
		rkt,
		/*使用内置的分区来选择分区*/
		nPartition1,
		//1,
		/*生成payload的副本*/
		RD_KAFKA_MSG_F_COPY,
		/*消息体和长度*/
		(void*)pcData, len,
		/*可选键及其长度*/
		NULL, 0,
		NULL))
	{
		fprintf(stderr,
			"%% Failed to produce to topic %s: %s\n",
			rd_kafka_topic_name(rkt),
			rd_kafka_err2str(rd_kafka_last_error()));

		if (rd_kafka_last_error() == RD_KAFKA_RESP_ERR__QUEUE_FULL){
			/*如果内部队列满,等待消息传输完成并retry,
			内部队列表示要发送的消息和已发送或失败的消息,
			内部队列受限于queue.buffering.max.messages配置项*/
			rd_kafka_poll(rk, 1000);

		}
	}
	else{
		//fprintf(stderr, "%% Enqueued message (%zd bytes) for topic %s\n",
		//len, rd_kafka_topic_name(rkt));

	}

	/*producer应用程序应不断地通过以频繁的间隔调用rd_kafka_poll()来为
	传送报告队列提供服务。在没有生成消息以确定先前生成的消息已发送了其
	发送报告回调函数(和其他注册过的回调函数)期间,要确保rd_kafka_poll()
	仍然被调用*/
	rd_kafka_poll(rk, 0);

	return 0;
}

size_t kafka_control::my_Hash(const char* pcPara)
{
	/*std::hash<const char*> h1;
	size_t nR = h1(pcPara);
	return nR;*/
	int i, l;
	unsigned long ret = 0;
	unsigned short *s;
	if (pcPara == NULL) return(0);
	l = (strlen(pcPara) + 1) / 2;
	s = (unsigned short *)pcPara;
	for (i = 0; i<l; i++)
		ret ^= (s[i] << (i & 0x0f));
	return(ret);
}

例子:

// An highlighted block
	//kafka
	kafka_control* pkafka_class = new kafka_control();
	printf("");
#ifdef CONVERTER
	pkafka_class->InitBrokers("cvtdata","192.168.190.152:9092,192.168.190.153:9092,192.168.190.154:9092");
	pkafka_class->SendWtgScadaData("HadoopId", "data");

部分内容参考了下面文章:
他的更简练,我的符合自己的需求
https://blog.csdn.net/lijinqi1987/article/details/76582067

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kafka 客户端工具是一种用于与 Kafka 消息队列进行通信和交互的工具。它提供了一系列命令行接口 (CLI) 和 API,可用于在 Kafka 集群中发布、订阅和使用消息。 Kafka 客户端工具具有以下主要功能: 1. 发布消息:可以使用 Kafka 客户端工具将消息发布到 Kafka 集群中的指定主题。可以通过命令行或程序化方式指定消息的内容、主题和其他属性。 2. 订阅消息:可以使用 Kafka 客户端工具从 Kafka 集群中的指定主题订阅消息。可以通过指定消费者组、分区和其他属性来灵活控制订阅行为。 3. 检查主题和分区:可以使用 Kafka 客户端工具查看 Kafka 集群中的所有主题和相应的分区信息。可以检查每个分区的偏移量、副本分布和其他有关分区的元数据。 4. 控制消费者组:可以使用 Kafka 客户端工具管理消费者组。可以列出当前活动的消费者组、查看组内消费者的偏移量以及重置偏移量等操作。 5. 监控和性能测试:Kafka 客户端工具还提供了一些监控工具和性能测试工具,用于监测和调优 Kafka 集群的性能。可以使用这些工具检查消息的产生和消费速率、分区偏移量的变化等。 总之,Kafka 客户端工具是一种便捷的工具,可以帮助开发人员和管理员与 Kafka 集群进行交互,并用于操作和管理消息的发布和订阅。无论是通过命令行还是API,它们都为处理 Kafka 数据流提供了强大的功能和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值