首页 > 解决方案 > Cassandra / Scylla 编组错误:read_simple_bytes - 字节数不足(请求 841888305,得到 10)

问题描述

我有一个名为 domain 的表,它有 2 列,一列是一个名为 domain 的字符串,它是主键,第二列名为 ip_addresses 并且是一组 inet 地址。

编码:

const cassandra = require('cassandra-driver');
const readline = require('readline');
const fs = require('fs');

const client = new cassandra.Client({
    localDataCenter: 'us-east',
    contactPoints: ['REDACTED'],
    keyspace: 'default_keyspace'
});

const readInterface = readline.createInterface({
    input: fs.createReadStream('./domains'),
    output: null,
    console: false
});

readInterface.on('line', async (line) => {
    const splitLine = line.split(',')

    const domain = splitLine[0]
    splitLine.shift()

    const query = `INSERT INTO domains (domain, ip_addresses) VALUES(?, ?);`;
    const parsed = splitLine.map(e => `'${e}'`)
    const ips = `{${parsed.join(',')}}`
    console.log("IPS ", ips)
    console.log('DOMAIN', domain)
    client.execute(query, [ domain, ips ]).then((result) => console.log('User with email %s', result.rows[0])).catch(e => console.error(e))
});

console.log("DONE")

值: IPS:{'172.217.15.110'} 域:google.com

错误是这样说的:

ResponseError: marshaling error: read_simple_bytes - not enough bytes (requested 841888305, got 10) Backtrace:   0x326f94d
  0xea40d6
  0xea42a6
  0xea44f1
  0x17cba2e
  0x17d1644
  0x17d1a18
  0x14ea92e
  0x14ec4b6
  0x15cd85e
  0x15d2801
  0x15aa827
  0x15b1634
  0x15b30fc
  0x15b3f9f
  0x15b5d8b
  0x15b5dad
  0x15baa48
  0x2d7d4bc
  0x2dda680
  0x2dda88f
  0x2e0f705
  0x2d79e69
  0x2d7af1e
  0xd2ff96
  /opt/scylladb/libreloc/libc.so.6+0x271a2
  0xc5502d

我能做些什么来解决这个问题?

谢谢

标签: node.jscassandrascylla

解决方案


看起来驱动程序无法正确序列化一组 IP 地址。我不是 node.js 专家,但我认为驱动程序根本无法从"{'172.217.15.110'}"字符串中推断出正确的类型,而只是将其序列化为字符串。

这就是为什么我认为驱动程序发送的东西实际上不是一组 IP 地址:Scylla 返回一个错误,通知缓冲区的大小似乎是841888305. 这个数字以十六进制表示为322E3231,它又看起来像是 ASCII 字符串的一部分……它实际上"2.21"以 ASCII 表示,这是您尝试发送的 IP 地址的字符串表示形式的子字符串。

在 CQL 中,大多数类型以[4 bytes of length][data]. Scylla 肯定会将您的 IP 字符串的一部分解析为长度,这意味着它需要不同的数据布局。

您应该浏览文档并查看如何让驱动程序知道您实际尝试发送的是一组 IP 地址,这是一个 CQL 类型set<inet>。以下是我根据您的代码设法将来自 node.js 的正确数据放入 Scylla 的方法(为简单起见,我对地址进行了硬编码,但您应该明白这一点):

readInterface.on('line', async (line) => {
    const splitLine = line.split(',')

    const domain = splitLine[0]
    splitLine.shift()

    const query = `INSERT INTO domains (domain, ip_addresses) VALUES(?, ?);`;
    const ips = [cassandra.types.InetAddress.fromString('127.0.0.1')]
    console.log("IPS ", ips)
    console.log('DOMAIN', domain)
    client.execute(query, [ domain, ips ]).then((result) => console.log('User with email %s', result.rows[0])).catch(e => console.error(e))
});


推荐阅读