Azure上的MongoDB连接问题

时间:2015-02-24 12:31:53

标签: c# mongodb azure

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

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

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

  

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

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

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

2 个答案:

答案 0 :(得分:3)

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

由于没有发布关于您如何实施此信息的信息。我将介绍几种可能的情况。


实验时间......

常数:

  • 要处理的项目:
    • 每秒50 ,换句话说......
    • 每分钟3,000 ,以及另一种查看它的方法......
    • 每小时180,000

变量:

  • 数据传输率:

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

      我们唯一可以做的就是从不同的cpu发出更多请求,以分配我们重新发送的流量。

  • 处理能力

    • 我假设您在WebJob中拥有此内容,而不是将其编码在MVC网站内。它非常低效,不适合您尝试实现的目的。通过使用WebJob,我们可以排队工作项以供其他WebJobs处理。有问题的队列Azure Queue Storage

        

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

           

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

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

问题:

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

解决方案:

  1. 设置WebJob并将其命名为EnqueueJob。此WebJob只有一个目的,即在Queue Storage中对要处理的工作项进行排队。
  2. 创建一个名为Queue Storage Container的{​​{1}},此队列将作为下一步的触发器,启动我们的扩展操作。
  3. 创建另一个名为WorkItemQueue的{​​{1}}。此WebJob也只有一个目的,即将DequeueJob的工作项出列,并将请求发送到您的数据存储。
  4. 将项目放置在WebJob内后,将WorkItemQueue配置为启动,在每个项目上启动5个单独的线程,并且当队列不为空时,为每个线程取消工作项并尝试执行出队的工作。
    1. 尝试1,如果失败,等待&重试。
    2. 尝试2,如果失败,请等待&重试。
    3. 尝试3,如果失败,将项目排队回DequeueJob
  5. 将您的网站配置为自动缩放到x个cpu(注意您的网站和网络作业共享相同的资源)
  6. Here's a short 10 minute video概述了如何利用队列存储和Web作业。


    修改

    你可能会遇到这些错误的另一个原因可能是因为其他两个因素,这也是因为它出现在MVC应用程序中...

    如果您在应用了WorkItemQueue属性的情况下编译应用程序,而是推送了WorkItemQueue版本,那么由于DEBUG中的设置,您可能会遇到问题,如果没有RELEASE属性,ASP.NET Web应用程序将运行最多90秒的请求,如果请求的时间超过此时间,它将处理请求。

    要将超时时间延长至 90秒,您需要更改web.config中的DEBUG属性...

    [httpRuntime][3]

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

    web.config

答案 1 :(得分:0)

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

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

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