Azure上的MongoDB连接问题

我们将一个ASP.NET MVC应用程序部署到Azure网站,该网站连接到MongoDB并执行读写操作。 应用程序迭代地执行此操作。 每分钟几千次。

我们使用Autofac初始化C#驱动程序,并按照https://groups.google.com/forum/#!topic/mongodb-user/_Z8YepNHnbI和其他一些地方的建议将MaxConnectionIdleTime设置为45秒。

我们仍然收到大量以下错误:

无法从传输连接读取数据:连接尝试失败,因为连接方在一段时间后没有正确响应,或者由于连接的主机无法响应而建立的连接失败。 方法消息:“:{”ClassName“:”System.IO.IOException“,”消息“:”无法从传输连接读取数据:连接尝试失败,因为连接方在一段时间后没有正确响应,或已建立的连接失败,因为已连接的主机无法响应。

在连接到Azure上相同数据中心/区域中的VM上部署的MongoDB实例时,以及连接到外部PaaS MongoDB提供程序时,我们会收到此错误。

我在本地计算机上运行相同的代码并连接到同一个数据库,但我没有收到这些错误。 只有当我将代码部署到Azure网站时才会这样。 有什么建议?

每分钟几千个请求是一个很大的负载,唯一正确的方法是控制和限制任何时候可以运行的最大线程数。

由于没有发布关于你如何实现这一点的信息。 我将介绍几种可能的情况。


是时候试验……

常数:

  • 要处理的项目:
    • 每秒 50,或换句话说……
    • 每分钟 3,000,还有一种方式来看待它……
    • 每小时 180,000

变量:

  • 数据传输率:

    • 无论我们做什么,您每秒可以传输多少数据都将发挥作用,这将根据一天中的不同时间而变化。

      我们唯一能做的就是从不同的cpu发出更多的请求来分配我们发回的流量的权重。

  • 处理能力:

    • 我假设你在WebJob有这个,而不是在MVC站点内编码它是自己的。 这是非常低效的,不适合你想要实现的目的。 通过使用WebJob,我们可以对要由其他WebJobs处理的工作项进行WebJobs 。 有问题的队列是Azure队列存储 。

      Azure Queue存储是一种用于存储大量消息的服务,可以使用HTTP或HTTPS通过经过身份validation的调用从世界上任何地方访问这些消息。 单个队列消息的大小最多为64 KB,队列可以包含数百万条消息,最多可达存储帐户的总容量限制。 存储帐户最多可包含200 TB的blob,队列和表数据。 有关存储帐户容量的详细信息,请参阅Azure存储可伸缩性和性能目标。

      队列存储的常见用途包括:

      • 创建积压的工作以异步处理
      • 将消息从Azure Web角色传递到Azure Worker角色

问题:

  • 我们试图每秒完成50个事务,因此如果我们使用50个线程,每个事务应该在1秒内完成。 我们45秒的时间没有任何目的。
  • 我们期望50个线程同时运行,并且所有线程都在一秒钟内完成,每秒钟在一个cpu上完成。 (我在这里夸大了一点,只是为了说明一点……但是想象一下每秒下载50个文本文件。处理它,然后尝试将它拍回给同事,希望他们甚至可以准备好抓住它)
  • 我们需要有一个重试逻辑,如果在3次尝试之后没有处理该项,则需要将它们放回队列中。 理想情况下,我们应该为服务器提供更多的时间来响应而不是每次失败仅一秒钟,让我们说我们在第一次失败时给它2秒rest,然后是4秒,然后是10,这将大大增加我们坚持的几率/检索我们需要的数据。
  • 我们假设我们的MongoDb每秒可以处理这么多的请求。 如果你还没有,开始寻找扩展它的方法,问题不在于它是一个MongoDb,数据层可能是任何东西,这是因为我们从这个数量的请求来自单一来源将是您问题的最可能原因。

解决方案:

  1. 设置WebJob并将其命名为EnqueueJob 。 此WebJob只有一个目的,即在Queue Storage对要处理的工作进行Queue Storage
  2. 创建一个名为WorkItemQueueQueue Storage Container ,此队列将充当下一步的触发器并启动我们的扩展操作。
  3. 创建另一个名为DequeueJob 。 此WebJob还有一个唯一目的,即从WorkItemQueue取出工作项并将请求发送到您的数据存储。
  4. 将项目放置在WorkItemQueue ,将DequeueJob配置为旋转,在每个项目上启动5个单独的线程,并且当队列不为空时,为每个线程取出工作项并尝试执行出列的作业。
    1. 尝试1,如果失败,请等待并重试。
    2. 尝试2,如果失败,请等待并重试。
    3. 尝试3,如果失败,将项目排入WorkItemQueue
  5. 将您的网站配置为自动缩放到x个cpu(请注意您的网站和Web作业共享相同的资源)

这是一段短短的10分钟video ,概述了如何利用队列存储和Web作业。


编辑:

你可能会遇到这些错误的另一个原因可能是因为另外两个因素,再次是因为它在MVC应用程序中…

如果您正在使用DEBUG属性编译应用程序但是推送了RELEASE版本,则由于web.config的设置而导致问题,而没有DEBUG属性,ASP.NET Web应用程序将运行请求如果请求的时间超过此时间,则最多90秒,它将处理该请求。

要将超时增加到90秒以上,您需要更改web.config[httpRuntime][3]属性…

   

您需要注意的另一件事是浏览器> Web应用程序的请求超时设置,我会说,如果您坚持将代码保留在MVC中而不是将其提取并放入WebJob,那么您可以使用以下代码将请求发送到您的Web应用程序并抵消请求的超时。

 string html = string.Empty; string uri = "http://google.com"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Timeout = TimeSpan.FromMinutes(5); using (HttpWebResponse response = (HttpWebResonse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { html = reader.ReadToEnd(); } 

你在VM中使用mongoDB吗? 这似乎是一个网络问题。 应该发生这种瞬态故障,因此您可以做的最好是实现重试模式或使用像Polly这样的库来执行此操作:

 Policy .Handle() .Retry(3, (exception, retryCount) => { // do something }); 

https://github.com/michael-wolfenden/Polly