lua和kafka整合后遇到的问题

按照时间线,记录一次lua写数据到kafka中碰到的事故

Q1:所有的数据写到kafka的同一个分区里面
A1:每次写入时,都重新创建了连接,这样数据就只保存到一个分区里面了

function connectKafka(kafkaConfig)
	local bp, err = producer:new(kafkaConfig.broker_list)
	if not bp then
	    ngx.log(ngx.INFO, "failed to connect: ", err)
	    return nil,err
	end
	return bp
end
-----
	local bp = connectKafka(kafkaConfig)
	local ok, err = bp:send(topic,nil,content)
-----

查过资料后,可以事先进行分区的计算,在发送数据时指定分区,因此nginx.conf中要加个配置,保存用于运算的数据

lua_shared_dict shared_data 1m;
作用:设置一个共享全局变量表,在所有worker进程间共享

然后加入计算分区的方法:

function getPartitionId() 
	// kafka分区的个数
	local partition_num = 2
	local shared_data = ngx.shared.shared_data
	local sharedKey = "shared_Key"
	local key_val = shared_data:get(sharedKey)
	if not key_val or key_val > 100000 then
    	key_val = 1
    	shared_data:set(sharedKey,key_val)
	end
	local partition_id = ""..tonumber(key_val%partition_num)
	shared_data:incr(sharedKey,1)
	return partition_id
end

-----
	local bp = connectKafka(kafkaConfig)
	local pId = getPartitionId()
	local ok, err = bp:send(topic,pId,content)
-----

Q2:按理说数据就应该在五个分区中轮流写入,但是结果是0号分区一潭死水,数据量根本没有发生变化,但是也没有报错,说明指定0号分区的数据没有丢,只是没往0分区写
A2:lua指定分区的算法可能有问题,后台java程序不指定分区也能在不同的分区间写入数据,干脆不再每次去创建连接,试试看

local bp = nil
function connectKafka(kafkaConfig)
	if not bp then
		bp, err = producer:new(kafkaConfig.broker_list)
		if not bp then
	    	ngx.log(ngx.INFO, "failed to connect: ", err)
		end
	end
end
-----
	connectKafka(kafkaConfig)
	local ok, err = bp:send(topic,nil,content)
	if not ok then
           bp = nil
	end
-----

这种办法,重启nginx之后,果然数据被基本均匀的保存到了不同的分区中去了

Q3:很快啊,又出现了新的问题,连接丢失写入失败,尽管做了一旦发生错误就将连接重置的逻辑,但是存三条丢一条的情况在环境中是绝不能接受的!
A3:怀疑是主机的性能不行,每来一条数据就写一次不太好,就把发送改成了异步的

bp, err = producer:new(kafkaConfig.broker_list,{ producer_type = "async" })

默认一次200条或50K
发现数据依然能均匀的写入到不同的分区中,并且sendKafka方法没有再提示写入失败的错误

Q4:又很快啊,丢数据的事情还是发生了,200条中能有几条数据因为写入失败被丢,甚至导致了更严重的事情发生------一条数据都没写入,重启nginx进程又恢复了正常(建议写一个15分钟重启一次nginx的crontab
A4:看了下kafka插件的producer.lua,发现指定key其实并不是partition_id,而是又进行了计算:

local function default_partitioner(key, num, correlation_id)
    local id = key and crc32(key) or correlation_id
	ngx.log(ngx.INFO,"id:",id," key:",key," crc32(key):",crc32(key)," cId:",correlation_id," pId:", id%num)
    -- partition_id is continuous and start from 0
    return id % num
end

根据添加的打印语句,发现一旦指定key,就会取crc32算法改写之后的key作为id,再取id和分区总数的余数作为分区号

producer.lua:48: choose_partition(): id:2212294583 key:1 crc32(key):2212294583 cId:1 pId:1,
producer.lua:48: choose_partition(): id:4108050209 key:0 crc32(key):4108050209 cId:1 pId:1,
producer.lua:48: choose_partition(): id:2212294583 key:1 crc32(key):2212294583 cId:1 pId:1,

这个算法我是看不懂,但是A1中前面传入的key就已经是分区号的啊,还要它算什么哦,直接将上面的方法改掉:

local function default_partitioner(key, num, correlation_id)
    -- local id = key and crc32(key) or correlation_id
    -- ngx.log(ngx.INFO,"id:",id," key:",key," crc32(key):",crc32(key)," cId:",correlation_id," pId:", id%num)
    -- partition_id is continuous and start from 0
    -- return id % num
    return tonumber(key)
end

重启nginx,环境内目前总算是没有出现新问题了…
其实这里出现了两个问题,一个是指定分区,但是0号分区不写的问题,一个是使用持久的连接,分区能被均匀的写入但是连接不稳,导致数据丢失的问题。
前者改写了插件的代码解决,如果不指定分区号又要改回,否则就直接报错了。后者就无法从代码部分理解了,估计是环境的问题,broker找不到、连接超时、连接关闭等,需要安装最新版本的kafka、申请更大的宽带等办法解决了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值