mongoose / mongodb DoS -ing一个nodeJS实例

在AWS VPC中有一个nodeJS实例,向另一个可用区域中运行的mongodb实例发出请求。

节点实例被一个特定的请求打了很多 。 该请求用于从mongodb实例中获取大量信息。 在第一个查询条目被caching了一段时间之后。

昨天发生了一些数据,它回来了。 有了这样的代码:

console.log('before retrieve'); Model.find({}).exec(function() { console.log('after retrieve'); }); 

如果在“检索”之前碰到10次,然后就停止,自己动手。 我删除了一些数据,这是暂时的修复。

在mongoDB方面,我有时会看到:

  SocketException handling request, closing client connection: 9001 socket exception [SEND_ERROR] 

我怎样才能避免这种情况发生?

你所描述的问题与mongoose,蒙古和节点有很大关系,更多的是通常被称为“caching踩踏”或“狗桩”的问题的performance。

顾名思义,当一堆东西试图立刻刷新caching时,会发生caching踩踏事件。 在你的情况下,这发生在caching过期时,或者在数据初始加载到caching期间。 突然之间,大量的请求进来,并应用大量的读取负载到您的数据库,1)导致caching刷新缓慢,2)导致更多的请求堆叠等待caching。 这基本上导致你看到的行为,只是事情崩溃

这个维基百科页面相当清楚地描述了问题,以及如何使用单独的进程或locking来解决问题。 由于节点没有锁或线程,这可能不是一个解决scheme。 另外,虽然单独的过程将起作用,但它有更复杂的一面。

过去我使用的一种技术是使用两个到期的caching键,一个键只用于指示何时应该刷新caching,而另一个键是否保存实际数据。

为了说明,我们假设我有一个对象foo ,我想要caching,并且每小时过期。 我可以创build另一个关键foo_refresh ,我在foo键前1分钟过期。

foo_refresh键过期时,一个worker / request会立即replacefoo_refresh键并忽略caching,而是从数据库中提取数据,并在完成时刷新foo键(也会重置到期时间)。 使用这样的机制,我们获得了一种刷新caching的“locking”,意味着不超过一名工作人员将进行昂贵的读取。

假设高速caching刷新不到1分钟, foo对象永不过期,而是通过foo_refresh键的刷新刷新。

希望有帮助!