linux 中kafka发送数据,C++ 向kafka中发送数据

kafka是一个分布式流处理的平台,通过kafka我们可以发布和订阅流式记录。有关kafka的介绍可以参考官网或者这篇文章https://juejin.im/post/6844903495670169607,介绍的非常的详细。

我个人喜欢把kafka当做数据库去理解,因为它也有存放数据的功能,但是还是与数据库是不一样的。

kafka中多个broker称为一个集群,一个broker(独立的kafka服务器)中可以创建不同的topic(主题),topic下可以建立多个partition(分区),数据则存放在分区中的一个单元里面(partition可以近似理解为一个数组,存入kafka的一条记录就存放在partition1[0]、partition1[1]...)。

生产者向kafka中生产数据,即把数据推入kafka中,消费者消费kafka中的数据,一个主题可以被多个消费者消费,这个是不同于数据库的地方。

c2ffddba9c0a

kafka结构图.jpg

下面介绍kafka在Linux下的简单使用

1 使用流程

2 问题及解决办法

3 代码示例

1 使用流程

首先服务器上必须已经安装好kafka!

1、在GitHub上下载librdkafka-master.zip安装文件,解压到文件夹https://github.com/edenhill/librdkafka

2、编译文件

cd librdkafka-master //cd到刚刚解压到的文件目录下

chmod 777 configure lds-gen.py

./confgure

make

make install

3、新建文件夹用于存放代码

4、在搭建好的kafka服务器上新建主题"test1"

./kafka-topics.sh --create --zookeeper localhost:2198--replication-factor1 --partitions1 --topic test1

2193是kafka所在的端口,根据自己的实际情况设置 。

5、将/usr/local/lib路径下的librdkafka++.a、librdkafka++.so、librdkafka.so.1放入自己创建的代码的文件夹下;

6、rdkafkacpp.h头文件加入创建的代码文件夹下,并在代码中引入头文件#include "rdkafkacpp.h"

7、在代码中设置broker和topic

std::string brokers="127.0.0.1:9092"; //地址为kafka服务器地址,这里是随便写的

std::string topic="test1" //主题为kafka中存在的主题

8、编译代码时加入 -lstdc++ -lrdkafka -lrdkafka++ -lrt -lpthread -L.

2 问题及解决办法

1、Connection refused

thrd:localhost:9092/bootstrap: Connection to ipv6#[::1]: 9092 failed : Connection refused

此类问题是由于地址设置不正确,没有将brokers地址设置为kafka所在的服务器地址,且服务器地址不能使用localhost代替。

2、搭建的kafka上查看不到创建的主题

可以查看rdkafkacpp.h头文件,调用的函数是哪一个,有的函数里的参数里面的topic主题必须是kafka上已经存在的主题。

3、Disconnected While requesting ApiVersion

Disconnected While requesting ApiVersion: might be caused by incorrect security. protocol configuration (connecting to a SSL listener?) or broker version is < 0.10

这个问题是由于代码中brokers的服务端口设置错误导致,应该设置为9092(配置文件中的默认端口):

std::string brokers = "ip::9092";

4、代码存放的位置不一定与kafka在同一位置上,只要代码中的brokers的地址设置为kafka所在的服务器地址即可。

代码示例

这个是参考github上面的代码改的producer.cpp

想要把代码运行起来,需要参考上面的 1 使用流程 进行设置

···

#include

#include

#include

#include

#include

#include

#if _AIX

#include

#endif

#include "rdkafkacpp.h"

static volatile sig_atomic_t run = 1;

static void sigterm (int sig) {

run = 0;

}

//成功发送一次信息调用一次回调函数

class ExampleDeliveryReportCb : public RdKafka::DeliveryReportCb {

public:

void dr_cb (RdKafka::Message &message) {

/* If message.err() is non-zero the message delivery failed permanently for the message. */

if (message.err())

std::cerr << "% Message delivery failed: " << message.errstr() << std::endl;

else

std::cerr << "% Message delivered to topic " << message.topic_name() <<

" [" << message.partition() << "] at offset " <<

message.offset() << std::endl;

}

};

int main () {

std::string brokers = "127.0.0.1:9092"; //这里的IP地址应该设置为kafka所在服务器地址

std::string topic = "test"; //设置主题

std::string errstr;

//设置配置

RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);

if (conf->set("bootstrap.servers", brokers, errstr) !=

RdKafka::Conf::CONF_OK) {

std::cerr << errstr << std::endl;

exit(1);

}

signal(SIGINT, sigterm);

signal(SIGTERM, sigterm);

ExampleDeliveryReportCb ex_dr_cb;

if (conf->set("dr_cb", &ex_dr_cb, errstr) != RdKafka::Conf::CONF_OK) {

std::cerr << errstr << std::endl;

exit(1);

}

//创建 producer

RdKafka::Producer *producer = RdKafka::Producer::create(conf, errstr);

if (!producer) {

std::cerr << "Failed to create producer: " << errstr << std::endl;

exit(1);

}

delete conf;

/*

* Read messages from stdin and produce to broker.

*/

std::cout << "% Type message value and hit enter " <<

"to produce message." << std::endl;

for (std::string line; run && std::getline(std::cin, line);) {

if (line.empty()) {

producer->poll(0);

continue;

}

//将message传入队列中

retry:

RdKafka::ErrorCode err =

producer->produce(topic,

RdKafka::Topic::PARTITION_UA, //随机分区

/* Make a copy of the value */

RdKafka::Producer::RK_MSG_COPY /* Copy payload */,

/* Value */

const_cast(line.c_str()), line.size(), //需要写入的数据

/* Key */

NULL, 0,

/* Timestamp (defaults to current time) */

0,

/* Message headers, if any */

NULL,

/* Per-message opaque value passed to

* delivery report */

NULL);

if (err != RdKafka::ERR_NO_ERROR) {

std::cerr << "% Failed to produce to topic " << topic << ": " <<

RdKafka::err2str(err) << std::endl;

if (err == RdKafka::ERR__QUEUE_FULL) { //存放数据的队列已满,将执行等待

producer->poll(1000);

goto retry;

}

} else {

std::cerr << "% Enqueued message (" << line.size() << " bytes) " <<

"for topic " << topic << std::endl;

}

producer->poll(0); //保持常态

}

std::cerr << "% Flushing final messages..." << std::endl;

producer->flush(10*1000 /* wait for max 10 seconds */);

run = true ; //之前因为没有加这个就报错了

if (producer->outq_len() > 0) //发送数据

std::cerr << "% " << producer->outq_len() <<

" message(s) were not delivered" << std::endl;

delete producer;

return 0;

}

...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值