【问题标题】:Ensure a web server's query will complete even if the client browser page is closed确保即使客户端浏览器页面关闭,Web 服务器的查询也会完成
【发布时间】:2014-08-04 11:14:29
【问题描述】:

我正在尝试编写一个控制面板

  1. 告知某些 KPIS
  2. 使用户能够通过按下按钮来启动某些请求/作业,然后在 DB 上运行存储的过程或设置特定设置等

到目前为止,一切都很好,除了我想运行一些更大的作业,其中作业运行的时间长度未知,并且可能在脚本超时期限和用户愿意等待的时间内运行回复。

我想要的是一个“即发即弃”的过程,这样用户点击按钮,即使他们关闭页面或关闭手机,他们也知道工作已经启动并将完成。

我正在研究 C# BeginExecuteNonQuery,它是对查询的异步调用,因此触发了 proc,但控件不必等待它的响应继续进行。但是我不知道当触发它的页面/应用程序关闭时会发生什么。

我还在考虑某种 Ajax 命令,它会在后台触发页面中的代码,因此用户不知道它正在运行,但我再次相信,如果用户关闭页面,脚本将会死掉并且该命令也会在服务器上死掉。

我知道的唯一方法是一个“队列”表,其中作业被插入到这个表中,然后每隔一两分钟就会有一个 MS 代理作业出现,检查新的插入,然后运行代码(如果有的话)。这样它就在数据库上,只有数据库崩溃会破坏它。这对等待同时运行的多个作业没有帮助,这两者都需要很长时间,但这是我唯一可以确定的,这将确保代码完全运行。

有什么想法吗?

任何语言都可以。

【问题讨论】:

  • 看已经commented on your previous post 你想扩展它继续并通过编辑原件来扩展它,不要只是乱扔没有答案的问题。问题是网页总是会期待一个结果,无论它是否是异步的,那篇文章中详述的方法似乎是你最好的选择。构建一个数据库来处理请求,然后触发一些外部进程(在 SQL Server 中,您可以使用计划作业)。

标签: sql asp.net stored-procedures asynchronous asp-classic


【解决方案1】:

由于网络浏览器未连接,因此来自它们的请求总是会占用全部时间。控制因素不是浏览器做了什么,而是网站本身允许操作持续多长时间。

IIS(以及一般的 Web 服务器)对请求有一个超时期限,如果完成的工作时间过长,请求就会终止。这将涉及突然停止任何需要很长时间的事情,例如数据库调用、运行代码等等。

简单地使您的长时间运行的操作异步似乎是一个好主意,但我不建议这样做。原因是在 ASP 和 ASP.Net 中,异步调用的代码仍然以阻止其他合法请求通过的方式消耗线程(在某些情况下,您最终可能会消耗两个线程!)。这可能会以不明显的方式对性能产生影响。最好只是增加超时并允许同步阻塞任务完成。完全完成这样的请求没有什么特别需要做的,即使发件人关闭浏览器或立即关闭手机也会发生这种情况(假设已收到整个请求)。

如果您仍然担心完成某些工作,无论 Web 请求发生了什么,那么最好创建一个进程外服务器/服务来完成工作以及此类任务的目标可以移交。然后,您的网站调用一个方法,该方法在服务内部启动自己的异步线程来完成工作,然后立即返回。也许它还返回一个请求ID,以便网页稍后可以通过其他方法检查请求的工作状态。

【讨论】:

    【解决方案2】:

    您可以使用异步方法并从此方法调用查询。 您可以通过以下方式将您的简单方法更改为异步方法。

    假设您有一个要异步调用的 Test 方法 -

         Class AsynchDemo
         {       
                public string TestMethod(out int threadId) 
                {
    
                  //call your query here
                }
    
               //create a asynch handler delegate: 
    
               public delegate string AsyncMethodCaller(out int threadId);
         }
    

    在您的主程序/或您必须调用测试方法的地方:

         public static void Main() 
         {
    
            // The asynchronous method puts the thread id here. 
            int threadId;
    
            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();
    
            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
    
            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke( 
                out threadId, null, null);
    
    
            // Call EndInvoke to wait for the asynchronous call to complete, 
            // and to retrieve the results. 
            string returnValue = caller.EndInvoke(out threadId, result);
    
            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
    
       }
    

    【讨论】:

      【解决方案3】:

      根据我的经验,即使客户端断开连接,Classic ASP 或 ASP.NET 页面也会一直运行到完成,除非您准备好检查客户端是否仍处于连接状态并在未连接时执行某些操作,或者超时到达。

      但是,将这些类型的作业作为计划任务运行可能会更好。

      在提交您的网页时,可以在数据库中记录需要运行的任务,然后在计划任务运行时检查并启动作业。

      许多网络主机和/或网络控制面板允许您创建按计划调用 URL 的计划任务。

      或者,如果您可以直接访问 Web 服务器,则可以在服务器上创建计划任务以按计划调用 URL。

      或者,如果是 ASP.NET,您可以将一些代码放在 global.asax 中以按计划运行。但请注意,如果您的网站设置为在一段时间不活动后停止,那么除非有频繁的持续活动,否则这将不起作用。

      【讨论】:

      • 每分钟运行一次的计划任务?
      • 当然,或者每 30 秒,或者每 5 分钟,或者在适合情况的时候。
      猜你喜欢
      • 2012-07-23
      • 2011-04-10
      • 1970-01-01
      • 2014-12-13
      • 1970-01-01
      • 2020-01-31
      • 2016-05-20
      • 2016-04-10
      相关资源
      最近更新 更多