简体   繁体   English

在IIS中重新启动网站时,如何检索已启动的Ignite实例?

[英]How do I retrieve a started Ignite instance when a website restart occurs in IIS?

I use Apache Ignite .NET EntityFramework second level caching in my ASP.NET MVC 5 website. 我在ASP.NET MVC 5网站中使用Apache Ignite .NET EntityFramework二级缓存。 Everything work as expected on my development machine, but things get complicated when I try to publish the website using Web Deploy on the production IIS. 一切都在我的开发机器上按预期工作,但当我尝试在生产IIS上使用Web Deploy发布网站时,事情变得复杂。

I always get a class org.apache.ignite.IgniteException: Ignite instance with this name has already been started: GridName when I publish or restart the website on IIS. 我总是得到一个class org.apache.ignite.IgniteException: Ignite instance with this name has already been started: GridName当我在IIS上发布或重新启动网站时, class org.apache.ignite.IgniteException: Ignite instance with this name has already been started: GridName The error is pretty clear, Ignite is already running. 错误非常明显,Ignite已经在运行。

The only way I found to get away this error is restarting the application pool of the website. 我发现逃避此错误的唯一方法是重新启动网站的应用程序池。 However, I don't want to do this every time I publish the website in production (which happens several times a week). 但是,每次我在生产中发布网站(每周发生几次)时,我都不想这样做。

I tried stopping the Ignite instance in the global.asax Dispose() or Application_End(), but the thing is that the AppDomain takes many seconds to stop. 我尝试在global.asax Dispose()或Application_End()中停止Ignite实例,但事实是AppDomain需要很多秒才能停止。 Ignite therefore has the time to try starting itself before it is stopped and causes the error mentioned above. 因此,Ignite有时间在停止之前尝试自行启动并导致上述错误。

I also tried to call Ignition.TryGetIgnite() to retrieve the running instance instead of trying to start it, but it always return null. 我还尝试调用Ignition.TryGetIgnite()来检索正在运行的实例,而不是尝试启动它,但它总是返回null。 Looking at the source code of this function in the Apache Ignite Github repository, I see that the Ignition object simply keeps a static list of nodes in memory and perform operations on this list. 在Apache Ignite Github存储库中查看此函数的源代码,我看到Ignition对象只是在内存中保留一个静态节点列表并在此列表上执行操作。 Since the AppDomain restarted at this point, the list is empty but the Ignite node is still running in the JVM. 由于此时AppDomain重新启动,因此列表为空,但Ignite节点仍在JVM中运行。

Is there a way to retrieve the Ignite instance or to stop it reliably, so I don't need to restart the application pool each time? 有没有办法检索Ignite实例或可靠地停止它,所以我不需要每次都重启应用程序池?

This is a known problem: AppDomain is stopped, but JVM keeps running (because process is not stopped), so Java part of Ignite nodes is still there. 这是一个已知问题:AppDomain已停止,但JVM仍在运行(因为进程未停止),因此Ignite节点的Java部分仍然存在。

Workaround is to stop all Ignite nodes with Ignition.StopAll in Application_End event like this in Global.asax.cs : 解决方法是在Global.asax.cs中的Application_End事件中使用Ignition.StopAll停止所有Ignite节点:

    protected void Application_Start()
    {
        ...

        using (new Mutex(true, "ignite_" + Process.GetCurrentProcess().Id))
        {
            var ignite = Ignition.TryGetIgnite() ?? Ignition.Start();
        }
    }

    protected void Application_End()
    {
        using (new Mutex(true, "ignite_" + Process.GetCurrentProcess().Id))
        {
            Ignition.StopAll(true);
        }
    }

Mutex is necessary here because old domain stopping overlaps with new domain starting. 此处需要互斥锁,因为旧域停止与新域启动重叠。 Process id is included in mutex name to ensure process-wide exclusive lock, but not machine-wide. 进程ID包含在互斥锁名称中,以确保进程范围的独占锁定,但不是机器范围的。


Another workaround , probably more robust and clean: 另一个解决方法 ,可能更强大和干净:

1) Stop all nodes in AppDomain.DomainUnload: 1)停止AppDomain.DomainUnload中的所有节点:

AppDomain.CurrentDomain.DomainUnload += (sender, args) => Ignition.StopAll(true);

2) Use different IgniteConfiguration.GridName every time: 2)每次使用不同的IgniteConfiguration.GridName

Ignition.Start(new IgniteConfiguration { GridName = Guid.NewGuid().ToString() });

This way existing nodes won't prevent you from starting a new one. 这样,现有节点不会阻止您启动新节点。 Eventually, old nodes will be stopped and cleaned up from memory. 最终,旧节点将被停止并从内存中清除。

Documentation: https://apacheignite-net.readme.io/docs/deployment#section-aspnet-deployment 文档: https//apacheignite-net.readme.io/docs/deployment#section-aspnet-deployment

Not exactly what I was looking for but I solved the problem for the moment. 不完全是我想要的,但我暂时解决了这个问题。

What I do is in Application_End , I call Ignition.StopAll() as suggested by Pavel, but since Application_End sometimes takes a long time to be called, the new AppDomain loaded for the website has time to start and receive requests before Ignite is stopped in the other AppDomain. 我所做的是在Application_End ,我按照Pavel的建议调用Ignition.StopAll() ,但由于Application_End有时需要很长时间才能被调用,因此为网站加载的新AppDomain有时间启动并在Ignite停止之前接收请求另一个AppDomain。

To go around this, I start Ignite using the following code (which could be improved): 为了解决这个问题,我使用以下代码启动Ignite(可以改进):

//Try to get already launched Ignite Instance
IIgnite ignite = Ignition.TryGetIgnite(igniteName);

while (ignite == null)
{
    try
    {
        //Try to start Ignite
        ignite = Ignition.Start(igniteConfig);
    }
    catch (Exception) //If failing to start Ignite, wait a bit for the previous AppDomain to stop the Ignite running instance...
    {
        HttpRequest request = null;
        try
        {
            request = HttpContext.Current.Request;
        }
        catch { }

        //Check if there is a request coming from the same machine, if yes, cancel it.
        if (request == null || !(request.IsLocal || request.UserHostName.EndsWith("myhostname.com"))
            Thread.Sleep(1000);
        else
            throw new HttpException(500, "Server error. Server rebooting.");
    }
}

//Use ignite variable here...

Note that in the code above, I put an additionnal check (which may not be needed by everyone), to check if there is a current request originating from the same machine. 请注意,在上面的代码中,我进行了额外的检查(每个人可能不需要),以检查是否有来自同一台机器的当前请求。 If you want to know why, read below, otherwise just take the code and remove the last if else part and simply keep the Thread.Sleep() . 如果你想知道原因,请阅读下面的内容,否则只需获取代码并删除最后一个if else部分,然后保留Thread.Sleep()

If request originates from the same machine, an HttpException is thrown to cancel the request, otherwise, it is conserved. 如果请求来自同一台机器,则抛出HttpException以取消请求,否则,它将被保留。 The reason I put this code is that if I publish the website on IIS, I don't want consumers to see an error, but I don't mind if they wait a bit for the previous AppDomain to stop. 我放这个代码的原因是,如果我在IIS上发布网站,我不希望消费者看到错误,但我不介意他们等待前一个AppDomain停止。 But if I receive a request from the same machine (or website), I want the request to abort, since it probably originates from code of the old AppDomain and will therefore delay the Application_End and Ignition.StopAll() from the old AppDomain. 但是,如果我收到来自同一台机器(或网站)的请求,我希望请求中止,因为它可能源自旧AppDomain的代码,因此会延迟旧AppDomain中的Application_EndIgnition.StopAll()

Hopefully some future Apache Ignite .NET development could make the instance closing easier and more reliable than this workaround. 希望未来的一些Apache Ignite .NET开发可以使实例关闭比这种解决方案更容易,更可靠。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用.Net NuGet Apache Ignite软件包时,如何启用ignite-http-rest模块? - How do I enable ignite-http-rest module when using the .Net NuGet Apache Ignite package? 如何在网站中检索标签的值? - How do I retrieve the value of a label in a website? 如何重新启动单个实例winforms应用程序 - how do I restart a single instance winforms application 使用try-catch异常,如果发生异常,如何在捕获括号内重新启动程序? - Using a try-catch exception, within the catch brackets how do I restart the program if an exception occurs? 当我们从IIS重新启动网站时,将触发哪个事件 - Which event will be triggered when we RESTART Website from IIS 如何在 IIS 托管的网站中接收自定义 webhook? - How do I receive a custom webhook in an IIS hosted website? 当点击发生在 UI 元素之外时,如何关闭它? - How do I close a UI element when a tap occurs outside of it? 每次重新启动或发布网站时,如何在iis7.5上手动为asp.net mvc创建首次请求? - How manually create first request for asp.net mvc on iis7.5 when every time restart or release the website? 如何填写网站表单并使用C#检索结果? - How do I fill in a website form and retrieve the result in C#? 从MVC控制器重新启动IIS网站 - Restart IIS website from MVC controller
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM