我正在使用融合的REST API代理致电Kafka。我正在读取一个CSV文件,从那里的所有记录(大约400万条记录)中创建一个对象,并将请求发送到REST代理。我不断遇到OutOfMemory
异常。
确切的异常消息是:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "kafka-producer-network-thread | producer-81"
我只有一个REST代理服务器实例,作为Docker容器托管。环境变量设置为:
JAVA_OPTIONS=-Xmx1g
其他配置:
CPU - 1
Memory - 1024
它在崩溃之前处理大约1,00,000。 我尝试将其扩展到4个实例,同时将CPU增加到3个,并将内存增加到2046 mb。然后,它将处理约500万条记录。
在读取csv之后,我以5k记录的批次调用Kafka端点。那是用Node写的。这是节点代码
fs.createReadStream(inputFile)
.pipe(parser({skip_lines_with_error: true}))
.on('data', (records) => {
country.push({ 'value' : {
country: records[0],
capital: records[1]
}
});
if (country.length > 5000) {
batch++;
callKafkaProxy(country).then((rec) => {
console.log(`'Batch done!'`);
}).catch((reason) => {
console.log(reason);
});
country = [];
}
})
.on('end', () => {
console.log('All done!');
});
function callKafkaProxy(records) {
const urlAndRequestOptions = {
url: 'http://kafka-rest-proxy.com/topics/test-topic',
headers: {
'content-type' : 'application/vnd.kafka.json.v2+json',
'Accept' : 'application/vnd.kafka.v2+json'
}
};
let recordsObject = {records: records};
//request here is a wrapper on the http package.
return request.post(urlAndRequestOptions, recordsObject);
我觉得我缺少一些配置,这些配置可以帮助解决此问题而又不增加实例数> 1。
任何帮助将不胜感激。
答案 0 :(得分:1)
.on('data', () => {}); ...
1。它不处理背压。创建可写流,它将处理您的批处理过程。然后只需使用管道即可。
inputStream
.pipe(parser)
.pipe(kafka)
然后分析这些行:
if (country.length > 5000) {
batch++;
callKafkaProxy(country).then((rec) => {
console.log(`'Batch done!'`);
).catch((reason) => {
console.log(reason);
});
country = [];
}
解决方案:
答案 1 :(得分:0)
借助Zilvinas的答案,我了解了如何利用流来批量发送数据。这是一个解决方案:
var stream = fs.createReadStream(file)
.pipe(es.split())
.pipe(es.mapSync(function (line) {
if (line.length) {
//read your line and create a record message
}
//put 5000 in a config constant
if (records.length === 5000) {
stream.pause();
logger.debug(`Got ${records.length} messages. Pushing to Kafka...`);
postChunkToKafka(records).then((response) => {
records = [];
stream.resume();
});
}