如何在生产中部署Blazor服务器并解决SignalR重新连接问题?

时间:2020-02-03 00:11:14

标签: blazor blazor-server-side

Blazor服务器是一项很棒的技术,但是由于SignalR无法重新连接到服务器,它会不断崩溃。

如何在生产中解决此问题?我让人们让笔记本电脑处于睡眠状态,或者让手机与网站通话5秒钟,而不是-“尝试重新连接”。

总是失败。用户正等着看“重新加载”按钮。

即使网站在移动浏览器或睡眠PC的浏览器中未处于活动状态,仍然可以克服此问题并强制重新连接SignalR吗?

1 个答案:

答案 0 :(得分:3)

概述

Blazor内置了用于自定义启动过程的选项,但它们的文档记录并不十分完善。

据我所知,就是这样:Configure the SignalR client for Blazor Server apps

但是,还有更多选项,包括设置重新连接选项的功能。

样本

在下面的代码示例中,我设置了maxRetries和retryIntervalMilliseconds(第48/49行)-定义了在通信中断时客户端将尝试重新连接的积极程度。

我还配置了一个自定义reconnectionHandler(第51行),它具有一个最小的实现,它将尝试重新连接(不显示任何UI),如果所有尝试均失败,它将仅重新加载页面。

这不是一件特别聪明的事情,但是它作为示例来说明如何进行定制流程。

进一步阅读 AspNetCore Circuits Client Side Code

**请不要在生产中使用该示例-仅是说明性的**

首先,使用autostart="false"关闭Blazor引导过程
<script autostart="false" src="_framework/blazor.server.js"></script>
然后,您可以提供自己的连接处理程序和设置
<script>
    async function connectionDown(options) {
        console.log("Connection Down - you could do some UI here...");
        for (let i = 0; i < options.maxRetries; i++) {
            console.log("Waiting for reconnect attempt #"+(i+1)+" ...");
            await this.delay(options.retryIntervalMilliseconds);
            if (this.isDisposed) {
                break;
            }

            try {
                // reconnectCallback will asynchronously return:
                // - true to mean success
                // - false to mean we reached the server, but it rejected the connection (e.g., unknown circuit ID)
                // - exception to mean we didn't reach the server (this can be sync or async)
                console.log("Starting Reconnect attempt #"+(i+1)+" ...");
                const result = await window.Blazor.reconnect();
                if (!result) {
                    // If the server responded and refused to reconnect, log it 
                    console.error("Server Rejected");
                } else {
                    // Reconnected!
                    return;
                }
            } catch (err) {
                // We got an exception so will try again 
                console.error(err);
            }
        }
        // all attempts failed - let's try a full reload
        // This could be a UI change instead or something more complicated
        location.reload();
    }

    function delay(durationMilliseconds) {
        return new Promise(resolve => setTimeout(resolve, durationMilliseconds));
    }

    function connectionUp(e) {
        // Reconnected
        console.log("Connection UP!");
        // if you have a UI to hide/change you can do that here.
    }

    window.Blazor.start({
        reconnectionOptions: {
            maxRetries: 30,
            retryIntervalMilliseconds: 500,
        },
        reconnectionHandler: {
            onConnectionDown: e => connectionDown(e),
            onConnectionUp: e => connectionUp(e)
        }
    });
</script>