在使用kafka库组件时,突然出现 state=67, errorno= 5003 的错误
zxyAcmen opened this issue · comments
#include "CKafkaConsumer.h"
#include
#include "workflow/KafkaDataTypes.h"
#include "workflow/KafkaMessage.h"
#include "workflow/KafkaResult.h"
#include "workflow/WFTaskFactory.h"
#include "workflow/WFFacilities.h"
#include "workflow/WFGlobal.h"
#include "sys_context/instancetemplate.hpp"
#include "CConvert.h"
#include "log/log.h"
#include "CHttpClient.h"
#include <boost/format.hpp>
#undef LOG_MOD_ID
#define LOG_MOD_ID ("tiis-consumer")
using namespace protocol;
static WFFacilities::WaitGroup wait_consumer_group(1);
CKafkaConsumer::CKafkaConsumer(/* args */) {
}
CKafkaConsumer::~CKafkaConsumer() {
}
void CKafkaConsumer::CommitCb(WFKafkaTask *task) {
int state = task->get_state();
int error = task->get_error();
if (state != WFT_STATE_SUCCESS) {
LOG_ESYS("CommitCb", "kafka consumer commit failed state= %d error= %d msg= %s",
state, error, WFGlobal::get_error_string(state, error)
);
}
return;
}
void CKafkaConsumer::KafkaFetchCb(WFKafkaTask *task) {
SeriesWork *series = series_of(task);
int state = task->get_state();
int error = task->get_error();
bool wait = false;
if (state != WFT_STATE_SUCCESS) {
wait = true;
// 错误出现在这行,之前一直都是正常使用,实在不清楚是什么问题了。
LOG_ESYS("CommitCb", "kafka consumer commit failed state= %d error= %d msg= %s",
state, error, WFGlobal::get_error_string(state, error)
);
} else {
WFKafkaTask *commit = m_KafkaCli_.create_kafka_task("api=commit", m_Retry_,std::bind(&CKafkaConsumer::CommitCb,this, std::placeholders::_1));
int api_type = task->get_api_type();
assert(api_type == Kafka_Fetch);
std::vector<std::vector<protocol::KafkaRecord *>> records_vec;
std::vector<protocol::KafkaToppar *> toppars;
protocol::KafkaResult *result = task->get_result();
result->fetch_records(records_vec);
bool isCommit = false;
for (auto &records : records_vec) {
for (auto &record : records) {
const void *value;
size_t value_len;
const char *topic = record->get_topic();
int partition = record->get_partition();
long long offset = record->get_offset();
record->get_value(&value, &value_len);
// 这里消费到的数据是pcs服务写到kafka的,需要放到convert中转换一次,写通知到http客户端
std::string tmpVal((char *)value, value_len);
LOG_INFO("topic= %s partition= %d offset= %lld value_len= %zu value= %s strVal= %s",
topic, partition, offset, value_len, value, tmpVal.c_str()
);
std::string httpData;
// 消息转换
InstanceTemplate<CConvert>::Instance()->UpMsgConvert(tmpVal, httpData);
// 创建http客户端任务
InstanceTemplate2<CHttpClient>::Instance()->Post(httpData);
commit->add_commit_record(*record);
isCommit = true;
}
}
if (isCommit) {
series->push_back(commit);
}
}
if (m_Running_) {
if (wait) {
series->push_back(WFTaskFactory::create_timer_task(1000 * 1000, nullptr));
}
series->push_back(CreateFetchTask());
} else {
series->push_back(m_KafkaCli_.create_leavegroup_task(0, nullptr));
}
return;
}
bool CKafkaConsumer::Init(const std::string &brokerAddr, const std::string &topic,
const std::string group, const std::string cliID, int startAt) {
if (brokerAddr.empty() || topic.empty()) {
LOG_ESYS(" ","broker or topic is empty pls check the param");
return false;
}
m_BrokerAddr_.assign(brokerAddr);
m_Topic_.assign(topic);
m_CliID_.assign("tiis_consumer_cli");
if (group.empty()) {
m_Group_ = "tiis-consumer";
} else {
m_Group_.assign(group);
}
if (!cliID.empty()) {
m_CliID_.assign(cliID);
}
m_OffsetTimestamp_ = KAFKA_TIMESTAMP_UNINIT;
if (startAt == 0) {
m_OffsetTimestamp_ = KAFKA_TIMESTAMP_EARLIEST;
} else {
m_OffsetTimestamp_ = KAFKA_TIMESTAMP_LATEST;
}
m_Retry_ = 2;
if (m_KafkaCli_.init(m_BrokerAddr_, m_Group_) != 0) {
LOG_ESYS("CKafkaConsumer::Init","failed broker= %s group= %s", m_BrokerAddr_.c_str(), m_Group_.c_str());
return false;
}
LOG_ISYS("CKafkaConsumer", "init success broker= %s group= %s", m_BrokerAddr_.c_str(), m_Group_.c_str());
return true;
}
bool CKafkaConsumer::Start() {
m_Running_ = true;
WFKafkaTask *task = CreateFetchTask(true);
SeriesWork *series = Workflow::create_series_work(task, [this](const SeriesWork *w) {
wait_consumer_group.done();
});
series->start();
return true;
}
bool CKafkaConsumer::Stop() {
m_Running_ = false;
wait_consumer_group.wait();
m_KafkaCli_.deinit();
LOG_INFO("---------------------------------CKafkaConsumer exit ---------------------------------");
return true;
}
WFKafkaTask *CKafkaConsumer::CreateFetchTask(bool first) {
std::string query;
WFKafkaTask *task;
protocol::KafkaConfig config;
query.append("api=fetch&topic=").append(m_Topic_);
config.set_client_id(m_CliID_.c_str());
config.set_fetch_max_bytes(512 * 1000);
config.set_fetch_timeout(100);
if (first && m_OffsetTimestamp_ != KAFKA_TIMESTAMP_UNINIT) {
config.set_offset_timestamp(m_OffsetTimestamp_);
config.set_offset_store(KAFKA_OFFSET_ASSIGN);
}
task = m_KafkaCli_.create_kafka_task(query, m_Retry_, [this](WFKafkaTask *task){
this->KafkaFetchCb(task);
});
task->set_config(std::move(config));
return task;
}
67是任务错误,通过WFGlobal::get_error_string可以打出错误原因。
Kafka fetch api failed 这个就是错误原因输出
我们看一下。是持续出现,还是可恢复呢?
我刚刚看了下机器内存,没什么内存了,然后加了内存,现在又正常了,没加内存前,一直失败,不知道是不是这个情况,任务里是不是要使用到内存,如果可以的话错误信息可以加详细些,这样方便查,刚出来的时候一脸懵逼。
你是加了什么机器的内存?kafka broker吗?
workflow所在机器,和内存没有关系。只要程序没有崩溃,行为不应该有什么区别。
嗯嗯,现在大多数服务器没有打开虚拟内存,所以,如果出现内存耗尽的情况,一般直接OOM退出,不会提示内存用完。
我们的程序里没有直接挂,主要是因为我们检查了malloc的返回值,所以你可以得到一个错误。因为内存耗尽的情况程序用于提示错误的资源都没有了,所以这种情况下行为无法确定的。大多数应用程序都是直接崩溃。
如果内存小,可以通过减少handlers_threads和poller_threads,降低内存使用。
handlers_threads
这个在哪里设置呢,找了一下没有找到设置入口。
@zxyAcmen 可以看看这个文档哈:https://github.com/sogou/workflow/blob/master/docs/about-config.md
其他的基本用法也可以通过github搜索项目,很快就可以找到了
这个程序里总共会有三个组件的任务,http(c、s端), kafka(p/c端)和redis的任务,我单独运行redis相关的任务,观察的时候内存不会有变化,但是加上kafka的任务,内存就一直在涨。