SignalR Stops Working After A While - javascript

For some reason, SignalR will just stop calling client methods after a short period of time (about 1 hour or less I estimate). I have a page that shows Alerts... a very simple implementation. Here's the Javascript:
$(function () {
// enable logging for debugging
$.connection.hub.logging = true;
// Declare a proxy to reference the hub.
var hub = $.connection.alertHub;
hub.client.addAlert = function (id, title, url, dateTime) {
console.log(title);
};
$.connection.hub.start().done(function () {
console.log("Alert Ready");
});
});
If I refresh the page, it works again for about an hour, then will stop calling the client event addAlert. There are no errors in the log, no warnings. The last event in log (other than the pings to the server) is:
[15:18:58 GMT-0600 (CST)] SignalR: Triggering client hub event
'addAlert' on hub 'AlertHub'.
Many of these events will come in for a short while, then just stop, even though the server should still be sending them.
I am using Firefox 35.0.1 on Mac and SignalR 2.0.0.
I realize that a work-around is to force a page refresh every 10 mins or so, but I'm looking for a way to fix the root cause of the problem.
I enabled SignalR tracing on the server. I created an "alert" on the server after a fresh refresh of the Alert page and the alert came through. I waited about 10 mins and I tried it again, and it failed to come through. Here's what the logs read (sorry for the verbosity, not sure what was relevant):
SignalR.Transports.TransportHeartBeat Information: 0 : Connection b8b21c4c-22b4-4686-9098-cb72c904d4c9 is New.
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
There are dozens more of the SignalR.Transports.TransportHeartBeat messages, but nothing else.

i think theres a timeout of default 110 seconds for signalr. Can you try signalr disconnected event to reconnect it back.
$.connection.hub.disconnected(function () {
setTimeout(function () {
startHub();
}, 5000);
});
and in startHub() you can start connection again.
reference : https://github.com/SignalR/SignalR/issues/3128
and How to use SignalR events to keep connection alive in the right way?

As it turns out the problem was the way I was handling the AlertHub connections. I am using Enterprise Library Caching to store connections backing the AlertHub, and I was expiring the cache entries 20 minutes after they were created. Ergo, when the server called the client method, no errors where reported because there were no client(s) to send the message(s) to.
I have since increased the cache expiration to a reasonable value, which solved the problem.

You can refresh page if client is inactive, no mouse movement (in about every 15-30 min). I had same problem and solved it that way. That was nasty workaround but later i forgot about it and never fixed it completly ;)

Related

ERR_INSUFFICIENT_RESOURCES ajax code for REAL-TIME CLOCK

I created a real-time clock that updates every second. When I run it locally I see no errors. However when I uploaded it to my web host I saw a lot of error messages in the console every time the AJAX code runs.
I think that's the reason why web host suspended my site, telling that my site has performed too many requests.
Here is my code:
$(document).ready(function() {
setInterval(function() {
$('#time').load('timewithdate.php')
}, 1000);
setInterval(function(){
$('#time2').load('time.php')
}, 1000);
})
I'm not sure what kind of answer you are looking for. Your code is a certain way to kill a server: it's making 2 calls to the server every second for each client (read more about DDOS). There is no need to make a server call, just use javascript to get the current time and format it the way you want. You can have something like this:
$(document).ready(function() {
setInterval(function() {
let curTime = new Date();
let date = curTime.toLocaleDateString();
let time = curTime.toLocaleTimeString();
$('#time').text(date + " " + time);
$('#time2').text(time);
}, 1000);
})
The error is because you have effectively DDOS'd your own server with 2 requests every second * number of concurrent clients. I would strongly suggest you remove these AJAX requests and perform the countdown on the client side.
If you're trying to keep the clocks in sync with server time, get the time from the server when the page loads, then add seconds to it on the client side. Do not use AJAX for this, and do not use AJAX polling in future. It's an anti-pattern.

How to use pubnub timetoken to handle page refreshes

When pubnub is connected, users inside my app receive messages no problem. However, let's say they refresh the page or go to another page within the app. There's a 2 -> 5 seconds of downtime before the user can connect to pubnub again. During this time some pubnub messages may be missed.
Thankfully, the pubnub subscribe API allows you to specify a timetoken to point to a past time (e.g. 10 seconds ago).
pubnub.subscribe({
channels: ['my_channel'],
timetoken: '13534398158620385'
});
Description:
Specifies timetoken from which to start returning any available cached messages.
Question:
What's the safest way to specify this timetoken such that few messages are missed?
First, listen out for beforeunload events on the window. These will be fired before the page is moved away from. Inside this create a cookie to save the current timetoken:
window.addEventListener('beforeunload', () => {
const now = new Date().getTime();
// pubnub timetokens are 17 digits long
const timetoken = `${now}0000`;
createCookie(PUBNUB_TIMETOKEN_COOKIE, timetoken, EXPIRATION);
});
Note: PUBNUB_TIMETOKEN_COOKIE and EXPIRATION are constants of your choosing. I set my cookie to expire after 10 seconds to prevent clashes. Also you'll need to define a createCookie function similar to this one.
Next, when subscribing to pubnub on page load, use this cookie if it exists:
pubnub.subscribe({
channels: ['my_channel'],
timetoken: getCookie(PUBNUB_TIMETOKEN_COOKIE)
});
This way, if the user refreshes or navigates to another page, missed messages should be caught.

Server saturation with Ajax calls

I'm using PHP over IIS 7.5 on Windows Server 2008.
My web application is requesting repeatedly with Ajax in the background 3 different JSON pages:
page 1 Every 6 seconds
page 2 Every 30 seconds
page 3 Every 60 seconds
They retrieve data related with the current state of some tables. This way I keep the view updated.
Usually I have no much trouble with it, but lately I saw my server saturated with hundreds of unanswered requests and I believe the problem can be due to a delay in one of the request.
If page1, which is being requested every 6 seconds, needs 45 seconds to respond (due to slow database queries or whatever), then it seem to me that the requests start getting piled one after the other.
If I have multiple users connected to the web application at the same time (or with multiple tabs) things can turn bad.
Any suggestion about how to avoid this kind of problem?
I was thinking about using some thing such as ZMQ together with Sockets.io in the client side, but as the data I'm requesting doesn't get fired from any user action, I don't see how this could be triggered from the server side.
I was thinking about using some thing such as ZMQ together with Sockets.io in the client side...
This is almost definitely the best option for long-running requests.
...but as the data I'm requesting doesn't get fired from any user action, I don't see how this could be triggered from the server side.
In this case, the 'user action' in question is connecting to the socket.io server. This cut-down example is taken from one of the socket.io getting started docs:
var io = require('socket.io')(http);
io.on('connection', function(socket) {
console.log('a user connected');
});
When the 'connection' event is fired, you could start listening for messages on your ZMQ message queue. If necessary, you could also start the long-running queries.
I ended up solving the problem following the recommendation of #epascarello and improving it a bit if I get no response in X time.
If the request has not come back, do not send another. But fix the serverside code and speed it up.
Basically I did something like the following:
var ELAPSED_TIME_LIMIT = 5; //5 minutes
var responseAnswered = true;
var prevTime = new Date().getTime();
setInterval(function(){
//if it was answered or more than X m inutes passed since the last call
if(responseAnsswered && elapsedTime() > ELAPSED_TIME_LIMIT){
getData()
updateElapsedTime();
}
}, 6000);
function getData(){
responseAnswered = false;
$.post("http://whatever.com/action.json", function(result){
responseAnswered = true
});
}
//Returns the elapsed time since the last time prevTime was update for the given element.
function elapsedTime(){
var curTime = new Date().getTime();
//time difference between the last scroll and the current one
var timeDiff = curTime - prevTime;
//time in minutes
return (timeDiff / 1000) / 60;
}
//updates the prevTime with the current time
function updateElapsedTime(){
prevTime = new Date().getTime();
}
This is a very bad setup. You should always avoid polling if possible. Instead of sending request every 6 seconds from client to server, send data from server to the clients. You should check at the server side if there is any change in the data, then transfer the data to the clients using websockets. You can use nodejs at the server side to monitor any changes in the data.

Timeout from navigator.geolocation.getCurrentPosition is not triggering error callback

I have the following Javascript code, for getting user localization:
navigator.geolocation.getCurrentPosition(getStores, getStoresError, {
'enableHighAccuracy' : true,
'timeout' : 10000,
'maximumAge' : 0
});
Both callbacks are being called when the user accepts or rejects the localization request. But if no answer is provided in 10 secs I was expecting timeout to expire and getStoresError to be called. This is not happening. Any ideas?
The timeout timer doesn’t start counting down until after the user gives permission to even try to calculate their position
var options = {timeout:10000,enableHighAccuracy:true,maximumAge:0};
navigator.geolocation.getCurrentPosition(getStores,getStoresError,options);
Try creating a global variable which is only updated on the success method for navigator.geolocation.getCurrentPosition. You can then create a setTimeout function lasting 10 secs which checks whether that value has been updated or not.
The only problem with this is that if the user clicks on Allow and your timeout expires just before the location is retrieved, you might be handling the response prematurely.
After try a lot in dev environment. I finally found that from 2016 chrome has disable that api in unsecured environment, it has to be done from https, hope this would save people's time. See this link below, https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only.

How configure reconnecting in socket.io?

I create socket.io connection with next code
var socket = new io.connect('http://localhost:8181', {
'reconnect': true,
'reconnection delay': 500,
'max reconnection attempts': 50
});
But when I kill server CTRL+C and start it again, reconnection isn't happening. But disconnect event raised on client side. What maybe reason of it?
This is an old question, but for other people like me, who are looking how to configure reconnect in socket.io (1.x) here is a correct syntax:
var socket = new io.connect('http://localhost:8181', {
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionDelayMax' : 5000,
'reconnectionAttempts': 5
});
I realise this is an old question, but I've been having some trouble with socket io reconnecting and found this post high in the search results, so thought I would contribue. Try debugging exactly which events are firing using the following code:
# coffeescript. compile if you're writing javascript, obviously.
socket.on 'connect',-> console.log 'connected'
socket.on 'reconnect',-> console.log 'reconnect'
socket.on 'connecting',-> console.log 'connecting'
socket.on 'reconnecting',-> console.log 'reconnecting'
socket.on 'connect_failed',-> console.log 'connect failed'
socket.on 'reconnect_failed',-> console.log 'reconnect failed'
socket.on 'close',-> console.log 'close'
socket.on 'disconnect',-> console.log 'disconnect'
This should give you more insight into the state of the client socket.
Also, try looking in the Network tab of your web inspector to see if it is firing XHR requests as a fallback. Finally, in your web console, try typing io.sockets and expand it out to see whether it is actually trying to reconnect or not.
I have encountered problems with reconnect_failed not firing, and the reconnect tally not resetting. The following are links to discussions of these issues on github.
reconnection delay - exponential back off not resetting properly
reconnect_failed gets never fired
some potential fixes/workarounds
This is an old question, but I had the same question (for a different reason) when using v1.4.5. My chat room app worked beautifully, but when I hit Ctrl+C in the terminal, my browser continued to loop and report ERR_CONNECTION_REFUSED every few seconds until I shut it down.
Changing a previous answer just a bit gave me the solution.
For v1.4.5, here is my original code for "var socket" in my client js file:
var socket = io();
And here is the solution:
var socket = io({
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionDelayMax' : 5000,
'reconnectionAttempts': 5
});
Obviously I could change the values if I want, but the important point is that this killed the never ending reconnection requests.
reconnection delay is too small 500ms increase that, on top of that 50 retries means 500 * 50 = 25000 ms which is 25 seconds. If that doesn't help set a timeout on error event on client side to recreate the socket object (After error and some delay retry to create connection).

Categories

Resources