在微服务调试与教学演示中,开发团队经常需要把Kafka中的消息内容直观呈现出来。Node.js凭借丰富的生态,可以用较少代码完成从Kafka读取模拟消息再到生成图片的闭环。下面介绍一种名为Mock2Image的思路:它并不依赖真实业务流量,而是用mock数据驱动,把每条消息渲染成带样式的图像,便于分享与归档。

Kafka连接与Mock消息注入
实现Mock2Image的第一步是让Node.js程序能连上Kafka并取得可预测的消息体。生产环境一般用真实topic,但mock场景更推荐自建一个本地Kafka或用Docker启动单节点,通过kafkajs管理admin与producer。这样既能避免污染业务数据,也能自由控制消息结构与频率。注意在配置中显式声明clientId与brokers,否则在容器网络下容易连不上。
下面代码演示如何用kafkajs创建客户端,并向mock-topic发送十条模拟订单消息。消息体采用普通JSON,包含id、user、amount三个字段,后续图像渲染会直接读取这些键。使用admin创建topic时,副本因子在本地设为1即可,不需要高可靠配置。
const { Kafka } = require('kafkajs');
const kafka = new Kafka({
clientId: 'mock2image-client',
brokers: ['127.0.0.1:9092']
});
async function sendMockMessages() {
const admin = kafka.admin();
await admin.connect();
await admin.createTopics({
topics: [{ topic: 'mock-topic', numPartitions: 1, replicationFactor: 1 }]
});
await admin.disconnect();
const producer = kafka.producer();
await producer.connect();
for (let i = 1; i <= 10; i++) {
await producer.send({
topic: 'mock-topic',
messages: [{
value: JSON.stringify({
id: i,
user: 'user_' + i,
amount: 100 * i
})
}]
});
}
await producer.disconnect();
console.log('mock messages sent');
}
sendMockMessages().catch(console.error);
这种注入方式的优势是消息格式完全可控,图像模板只需适配一种结构。若后期要支持多类型,可在value里增加type字段,渲染层按type分流。相比直接连生产环境,mock注入把不确定性降到最低,也更符合测试隔离原则。
消息消费与图像渲染设计
消费端同样使用kafkajs的consumer组,从mock-topic拉取消息后,不直接打印,而是交给canvas模块画图。Node.js里常用canvas包(基于node-canvas),它提供与浏览器接近的2D上下文。每张消息生成一张400x200的卡片,左侧写id,右侧写用户与金额,背景用浅色块区分。这样即使非技术人员也能一眼看懂消息内容。
渲染函数要把JSON安全解析,防止mock数据里出现非法字符导致崩溃。我们约定所有value都是JSON字符串,用try-catch包裹JSON.parse。如果解析失败,就画一张红色错误卡,避免进程退出。以下代码展示消费并渲染单条消息为PNG缓冲区的逻辑:
const { Kafka } = require('kafkajs');
const { createCanvas } = require('canvas');
const kafka = new Kafka({
clientId: 'mock2image-consumer',
brokers: ['127.0.0.1:9092']
});
function renderMessageToPng(value) {
let data;
try {
data = JSON.parse(value);
} catch (e) {
data = { id: 'err', user: 'parse_fail', amount: 0 };
}
const canvas = createCanvas(400, 200);
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#f5f5f5';
ctx.fillRect(0, 0, 400, 200);
ctx.fillStyle = '#333';
ctx.font = '20px sans-serif';
ctx.fillText('ID: ' + data.id, 20, 40);
ctx.fillText('User: ' + data.user, 20, 90);
ctx.fillText('Amount: ' + data.amount, 20, 140);
return canvas.toBuffer('image/png');
}
async function consumeAndRender() {
const consumer = kafka.consumer({ groupId: 'img-group' });
await consumer.connect();
await consumer.subscribe({ topic: 'mock-topic', fromBeginning: true });
await consumer.run({
eachMessage: async ({ message }) => {
const buf = renderMessageToPng(message.value.toString());
// 此处可把buf写入文件或上传
console.log('rendered png size:', buf.length);
}
});
}
consumeAndRender().catch(console.error);
从工程角度看,渲染与消费解耦更稳妥。可把renderMessageToPng单独抽成模块,消费端只负责取数据并调用。若消息量较大,建议加一个队列,让渲染在独立线程做,防止consumer阻塞造成rebalance。Mock2Image的轻量特性正好适合用这种简单管道。
批量导出与CLI封装
当mock消息积累到几十条,逐个看图效率低,需要批量导出成zip或直接存本地目录。Node.js里用fs写文件,配合archiver打压缩包都很方便。我们可以把前面消费逻辑改成:每收到一张图,按id命名存到./output,等消费完打印汇总。这样一次运行就能拿到整套可视化mock数据。
为了让工具好用,可以封装成命令行:接收broker地址、topic、输出目录三个参数。用commander库解析,内部复用同一套消费渲染代码。下面示例展示如何把渲染结果写入磁盘,并支持通过环境变量切换目标Kafka地址:
const fs = require('fs');
const path = require('path');
const { Kafka } = require('kafkajs');
const { createCanvas } = require('canvas');
function render(value) {
const d = JSON.parse(value);
const c = createCanvas(400, 200);
const x = c.getContext('2d');
x.fillStyle = '#eef';
x.fillRect(0, 0, 400, 200);
x.fillStyle = '#222';
x.font = '18px monospace';
x.fillText('id=' + d.id, 10, 30);
x.fillText('u=' + d.user, 10, 70);
x.fillText('a=' + d.amount, 10, 110);
return c.toBuffer('image/png');
}
async function run(broker, topic, outDir) {
const kafka = new Kafka({ clientId: 'cli', brokers: [broker] });
const con = kafka.consumer({ groupId: 'cli-g' });
await con.connect();
await con.subscribe({ topic, fromBeginning: true });
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir);
await con.run({
eachMessage: async ({ message }) => {
const name = 'msg_' + message.offset + '.png';
fs.writeFileSync(path.join(outDir, name), render(message.value.toString()));
}
});
}
const broker = process.env.BROKER || '127.0.0.1:9092';
run(broker, 'mock-topic', './output').catch(console.error);
这种CLI封装让Mock2Image脱离了写死代码的使用方式,测试同学也能在笔记本上一条命令生成图片包。后续还可加入浏览器预览服务,用http模块把output目录挂成静态资源,实现边发mock边看图的体验。整体方案在Node.js下不到两百行即可落地,是性价比很高的内部小工具。
Node.jsKafkaMock2Image修改时间:2026-08-13 15:15:35