MongoCursorNotFoundException,关于mongodb使用过程报游标找不到的问题

如下是我的项目中的相关报错信息:

要解决问题,首先要了解问题。

异常直接了当的告诉你编号为127594874818的游标在服务器端找不到了,那游标是什么?

当我们在使用db.collection.find()命令查询mongodb数据时,直接返回给你的并不是数据本身,而是一个游标,每个游标都有对应的一个游标ID,服务器会记录这个游标ID,真正获取数据时,是通过对游标进行遍历拿到数据,对应的遍历方法主要是hashNext()和next(),跟iterator迭代器一样使用(命令行客户端之所以通过find()命令就得到数据,是因为它自动帮你遍历了游标,且默认展示了20条数据),客户端通过游标从服务端获取数据时并不是一条一条的,而是一批一批的,这样可以提升IO性能,每批数据都缓存在客户端内存中,通过next()遍历完后,继续通过getMore()方法去服务器获取下一批数据,而此时需要携带cursorid的,服务器通过cursorid辨别是取什么数据,当服务器端没有这个cursorid时,就会发生这个游标找不到的错误。

为什么找不到游标了?

1、游标由服务端生成,但是游标本身是会占用系统资源的,所以用完是要及时回收的,一般来说由客户端使用完发送一个close命令,这样服务端就知道这个游标不再使用了;另一种情况是服务端识别到该游标长时间没有再使用,则会自动完成回收,默认过期时间是10min,我们可以在admin库中查到配置,如下所示,其中的cursorTimeoutMills就是游标超时配置:

/

2、游标超时,会导致我们的项目报游标找不到的错误,但是游标找不到的错误,并不一定就是超时导致的,如果服务器本身就没有这个游标ID呢,那自然是会找不到,什么场景会出现这种情况呢?

首先我们看个关于mongodb驱动中getMore()方法,用的是连接池的方式,每次getMore都会重新获取连接。

在mongo集群场景中,有多个mongo服务器,每个服务器都能提供查询,当我们find()时由A服务器生成了一个游标并返回,然后getMore()时又用这个游标访问到了B服务器,这时候B服务器就会返回游标找不到。

正常情况下,当我们使用mongodb集群时,将所有mongodb服务器以 IP1:PORT1,IP2:PORT2,IP3:PORT3的形式传给驱动,驱动能够自动完成负载均衡和保持会话转发到同一个服务器,这时候不会出现问题;

但是当自己给集群搭建了一个负载均衡层,用了一个 product.mongos.com:port 这种通过域来访问,就会有问题,虽然当我们访问product.mongos.com时,最终也会转发到真正的mongos服务器上,但是这时候并不能保证getMore()的后续访问都能到同一个服务器上,当然如果你的负载均衡层完全是以客户端IP来分发的,同一个IP去同一个服务器,应该也没有问题,我们线上用的是Maglev算法,这是google的一个调度算法,用的是源IP,源端口,目标IP,目标端口,IP协议号五个维度的散列值,所以一个客户端的多个端口连接并不保证去往同一个服务器,这也是导致项目中报错的原因。

所以,在做mongos集群时,不要搭建自己的负载均衡层,因为通过驱动本身就已经能实现负载均衡了。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值