首页 文章

Azure上的MongoDB连接问题

提问于
浏览
11

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

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

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

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

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

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

2 回答

  • 0

    每分钟几千个请求是 big 加载,并且唯一正确的方法是控制和限制可以在任何时间运行的最大线程数 .

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


    实验时间......

    The constants:

    • Items to process:
      每秒
    • 50,换句话说......
      每分钟
    • 3,000,还有一种方法可以看......
      每小时
    • 180,000

    The variables:

    • Data transfer rates:

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

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

    • Processing power:

    • 我假设你在 WebJob 中有这个,而不是在MVC网站内编码它's self. It'效率非常低,并且不适合你想要实现的目的 . 通过使用WebJob,我们可以对要由其他 WebJobs 处理的工作项进行排队 . 有问题的队列是Azure Queue Storage .

    Azure Queue存储是一种用于存储大量消息的服务,可以通过使用HTTP或HTTPS的身份验证调用从世界上任何地方访问这些消息 . 单个队列消息的大小最大为64 KB,队列可以包含数百万条消息,最多可达存储帐户的总容量限制 . 存储帐户最多可包含200 TB的blob,队列和表数据 . 有关存储帐户容量的详细信息,请参阅Azure存储可伸缩性和性能目标 . 队列存储的常见用途包括:创建待处理的工作积压以异步处理将消息从Azure Web角色传递到Azure Worker角色

    The issues:

    • 我们试图每秒完成50个事务,因此如果我们使用50个线程,每个事务应该在1秒内完成 . 我们45秒的时间没有任何目的 .

    • 我们在这里夸大了一点,只是为了说明一点......但想象一下每秒下载50个文本文件 . 处理它,然后尝试将它拍回给同事,希望他们甚至可以 grab 它)

    • 我们需要有一个重试逻辑,如果在3次尝试之后没有处理该项,则需要将它们放回队列中 . 理想情况下,我们应该为服务器提供更多的时间来响应而不是每次失败仅一秒钟,让我们说我们在第一次失败时给它2秒休息,然后是4秒,然后是10,这将大大增加我们坚持的几率/检索我们需要的数据 .

    • 我们 assuming 我们的 MongoDb 可以每秒处理这个数量的请求 . 如果你事实上我们正在从单一来源提出这一数量的请求,这将是你问题的最可能原因 .

    The solution:

    • 设置 WebJob 并将其命名为 EnqueueJob . 这个 WebJob 只有一个目的,即在 Queue Storage 中对要处理的工作项进行排队 .

    • 创建名为 WorkItemQueueQueue Storage Container ,此队列将充当下一步的触发器并启动我们的扩展操作 .

    • 创建另一个名为 DequeueJobWebJob . 此 WebJob 也有一个唯一目的,即从 WorkItemQueue 出列工作项并将请求发送到您的数据存储 .

    • 配置 DequeueJob 在项目放置在 WorkItemQueue 内后旋转,在每个项目上启动5个单独的线程,当队列不为空时,出列每个线程的工作项,并尝试执行出队作业 .

    • 尝试1,如果失败,请等待并重试 .

    • 尝试2,如果失败,请等待并重试 .

    • 尝试3,如果失败,将项目排队回 WorkItemQueue

    • 将您的网站配置为自动缩放到x个cpu(请注意您的网站和Web作业共享相同的资源)

    Here's a short 10 minute video概述了如何利用队列存储和Web作业 .


    Edit:

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

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

    要将超时增加到超过 90 seconds ,您需要更改 web.config 中的 [httpRuntime][3] 属性...

    <!-- Increase timeout to five minutes -->
    <httpRuntime executionTimeout="300" />
    

    您需要注意的另一件事是您的浏览器> 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();
    }
    
  • 3

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

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

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

相关问题