idchlife
idchlife

Reputation: 678

How to deploy Blazor server in production and overcome SignalR re-connection problems?

Blazor server is a fantastic technology, but it constantly breaks with SignalR not being able to reconnect to the server.

How would one fix this in production? I'm having people leaving their laptops in sleep or putting phone with website for a 5 seconds away, than - "Attempting to reconnect".

And always failed. Users are waiting just to see "Reload" button.

Hot to overcome this issue and force reconnect SignalR, even if website was not active in mobile browsers or browsers of sleeping pc?

Upvotes: 20

Views: 12691

Answers (3)

Iman Hamidi
Iman Hamidi

Reputation: 198

I know this is an old question and my answer may be irrelevant, but it may help too!

I had the same problem with Blazor in production: Continuously (every 1 minute) getting the reconnect error, but everything else (Blazor functionalities) had worked well. I am using Apache Linux to host my Blazor app. I figured out that the web socket connection was failing with a 502 error, and Blazor tried to reconnect it, but it would fall again. Finally, I understood that the problem is the bad configuration for Apache. I changed the conf from

<VirtualHost *:80>
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>

to

<VirtualHost *:80>
    ProxyPass / ws://127.0.0.1:5000/
    ProxyPassReverse / ws://127.0.0.1:5000/
</VirtualHost>

and it completely solved my problem!

Upvotes: 1

aryeh
aryeh

Reputation: 1040

For a simpler solution than Mister Magoo, you could use:

<script src="_framework/blazor.server.js" autostart="false"></script>
  <script>
    Blazor.start().then(() => {
      Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
        document.location.reload();
      }
    });
</script>

This keeps the original startup process and just adds a reload when connection goes down.

Upvotes: 1

Mister Magoo
Mister Magoo

Reputation: 8974

Overview

Blazor has built in options for customising the startup process

and to Configure the SignalR client for Blazor Server apps

They have even added a sample for how to automatically reload when reconnecting fails.

Sample - taken from the docs at this date:

First, turn off the Blazor boot process with autostart="false" and register your boot.js script

<body>
    ...

    <div id="reconnect-modal" style="display: none;"></div>
    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script src="boot.js"></script>
</body>

Then, you can provide your own connection handler and settings in boot.js

(() => {
  const maximumRetryCount = 3;
  const retryIntervalMilliseconds = 5000;
  const reconnectModal = document.getElementById('reconnect-modal');

  const startReconnectionProcess = () => {
    reconnectModal.style.display = 'block';

    let isCanceled = false;

    (async () => {
      for (let i = 0; i < maximumRetryCount; i++) {
        reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`;

        await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds));

        if (isCanceled) {
          return;
        }

        try {
          const result = await Blazor.reconnect();
          if (!result) {
            // The server was reached, but the connection was rejected; reload the page.
            location.reload();
            return;
          }

          // Successfully reconnected to the server.
          return;
        } catch {
          // Didn't reach the server; try again.
        }
      }

      // Retried too many times; reload the page.
      location.reload();
    })();

    return {
      cancel: () => {
        isCanceled = true;
        reconnectModal.style.display = 'none';
      },
    };
  };

  let currentReconnectionProcess = null;

  Blazor.start({
    reconnectionHandler: {
      onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
      onConnectionUp: () => {
        currentReconnectionProcess?.cancel();
        currentReconnectionProcess = null;
      },
    },
  });
})();

Upvotes: 25

Related Questions