-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mongo副本集超过3节点连接primary失败 #1145
Comments
我对 mongo 这里的机制不熟悉,不知道官方的策略是怎样的? |
我阅读代码看到有 |
这里可供选择的列表,是由第一台机器 ismater 指令返回值中的 hosts 列表决定的,你看看你的所有机器的列表有没有配置正确。 |
well,我刚才去检查了一下报错,发现是socketchannel在连接第二个节点时报错,line:459
没有等到response,应该是这个节点正好有故障。 外部我们的项目尝试重连,重连有一次重复刚才的流程,因此出现了只连接1、2号两个节点,而没有发现primary的3号节点 |
选择 primary host 的流程见这个 patch #525 我猜测这个实现有这样的问题:
@zxfishhack 你可以看看,我认为可以将 https://github.com/cloudwu/skynet/blob/master/lualib/skynet/db/mongo.lua#L128-L142 -- determine the primary db using hosts
local pickserver = rawget(mongoc, "__pickserver")
if pickserver == nil then
pickserver = {}
rawset(mongoc, "__pickserver", pickserver)
end
for _, v in ipairs(rs_data.hosts) do
if v ~= rs_data.me then
table.insert(pickserver, v)
end
end
if pickserver <= 0 then
error("CAN NOT DETERMINE THE PRIMARY DB")
end
local pick = table.remove(pickserver, 1)
skynet.error("INFO: TRY TO CONNECT " .. pick)
local host, port = __parse_addr(pick) @sabearcher 你不妨试试。 |
不过,这样修改有可能导致在配置错误(没有 primary 时) 变成死循环,因为会不断的添加已经尝试过的节点。如果想避免这种情况,可以在 |
有可能存在一段时间,没有primary节点,一般不超过12秒,参考这个文档( https://docs.mongodb.com/manual/core/replica-set-elections/ )。目前代码确实没考虑选举过程中的问题,会造成尝试一轮后放弃?
新加入的节点,副本集之间会互相发现的;这里描述的bug有点奇怪,一共4个节点,选举新primary至少要3个节点投票的,不可能两个节点都不知道另外两个节点。是手工强行指定的primary节点么?这行代码触发了么? error("CAN NOT DETERMINE THE PRIMARY DB") |
@xjdrew 根据今天出现的新的报错来看,今天阿里云的mongo出现了禁止连接的bug,在重连log里我看到4个节点都尝试过了(副本集是5节点的,一个Arbit,四个数据),反复重试连接不成功,经历了35分钟后,skynet进程退出了, @cloudwu 是否是太长期的socket error,会导致skynet进程退出? 而且之前的bug经过我回头检查所有旧的log,发现起服也有连接到第3节点成功的情况,真实的报错位置还是在 local function wrapper_socket_function(f)
return function(self, ...)
local result = f(self[1], ...)
if not result then
error(socket_error) ----这里报错
else
return result
end
end
end
channel_socket.read = wrapper_socket_function(socket.read) 之后的重连尝试有时不正常,现在推测可能确实如你们所说中途一个故障节点的 rs_data.hosts本身就可能数量不对,能否改成无论 channelsocket.lua 如何表现,mongo.lua 至少一定要把配置的 conf.rs 里全部节点都遍历到? |
我上个回复中的改法也有问题? |
我明白了。socketchannel 的 backup 列表只在连接不上时才会轮流试。对于 auth 阶段的错误则不会。我要想想怎么改。 |
我写了个 patch 改进这里的处理方式。因为我这里很难搭建对应的环境,所以麻烦你 review 一下 patch 的代码,并做一定的测试。如发现 patch 中的问题,可以继续在那个 pr 下讨论。 |
经线上项目,发现mongo副本集配置有4个可以用节点(1主3从),通过mongo配置 rs属性,在连接报错
然后发现主节点已切换到第3个,但是skynet.mongo重连只发生在第一第二节点
该方法在尝试时,只切换到第二节点,连接成功则 socket_channel 返回,在mongo_auth内校验rs_data.primary失败后,重新取的节点信息又重回第一节点,在5节点模型里,无法找到主节点,永久失败。
The text was updated successfully, but these errors were encountered: