-
Notifications
You must be signed in to change notification settings - Fork 381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speed up the logout notification when client power cut off #1091
Comments
What version of the server and client are you using? |
Also what type of http service are you using? uWS or ws? uWS deals with heartbeats (heartbeatinterval * 2). With the text protocol we use individual timers on each websocket. But going through the code is appears ws binary implementation is missing that. Can you confirm if thats what your using? |
Server Version: 5.1.3 httpServer:
type: default
options:
# url path for http health-checks, GET requests to this path will return 200 if deepstream is alive
healthCheckPath: /health-check
# -- CORS --
# if disabled, only requests with an 'Origin' header matching one specified under 'origins'
# below will be permitted and the 'Access-Control-Allow-Credentials' response header will be
# enabled
allowAllOrigins: true
# a list of allowed origins
origins:
- 'https://example.com'
# Options required to create an ssl app
# ssl:
# key: fileLoad(ssl/key.pem)
# cert: fileLoad(ssl/cert.pem)
# ca: ... |
Yeah that would probably be the issue then. I'll try get the fix in shortly. |
This should be now fixed in 5.1.6, in exchange to a timeout being setup for each socket. If performance is your ultimate endgame I would recommend trying to use uws, although it has it's own mini quirks (with our implementation at least). TravisCI is super slow nowadays, so let me know if the release doesn't work for you as I need to switch context. Thanks! |
Ended up publishing the macos and windows myself. |
The heartbeat packet mechanism works. When I disconnect the network cable, I can quickly see the message of client disconnection in the log. However, it only outputs disconnection messages continuously. Other clients that subscribe to presence do not receive logout messages.
|
Yeah so it looks like I was calling Anyways, I tagged 5.1.7 now. Also, for anyone seeing this, the server side doesn't actually use a continuous PING/PONG heartbeat mechanism. It just makes sure a packet was received at least within the heartbeat period. This simplifies the code greatly. The server expects a message every
On the client side its checks if a message wasn't received for a So you need to make sure the heartbeat intervals are the same. If development picks up again it would probably be good for the sever to send the heartbeat config to the client on an INITIALISE action on the connection which can update the client with the correct values (or at least verify they are correct). Since it's a stateless action (it doesn't have to happen) it's not a breaking change. Mostly useful for production deployments where you don't want to roll out new deployments to play with heartbeats / use a separate config location. Anyways, hope the fix works this time. Apologies, I don't have a running environment so I'm relying on tests and typescript (e2e and UT), which work really well at catching all sorts of edge cases but not so much at simulating connection loss. |
Thank you for your quick response. Could you help me compile a version of windows. It seems that the automatic compilation process failed. |
It's available on appveyor artefacts https://ci.appveyor.com/project/yasserf/deepstream-io/builds/36504444/artifacts |
If the client only subscribes to the change of server data, and the time interval of server data change is less than heartBeatInterval, the client will not send Ping, and the server will not receive any data from the client, and the client will be considered disconnected. In client side socket-factory.ts, version 5.1.10 socket.onopen = () => {
pingInterval = setInterval(() => {
if (Date.now() - lastRecievedMessageTimestamp > heartBeatInterval) {
try {
socket.send(pingMessage)
} catch (e) {
clearTimeout(pingInterval!)
}
}
}, heartBeatInterval) as never as number
socket.onopened()
} Maybe It should compare the current time with the timestamp of last sent message . Please help me sync 5.1.7 to docker hub. |
I'm afraid CI is down and I haven't used docker in a long time so I don't have the environment running. you can created the docker image via |
Also good point about the client, feel free to raise a PR if you have a moment and I'll publish that! |
I'm not familiar with typescript. I'll try it. |
PR raised, Please check if there is any problem. |
I think I should have fixed the CI failing issue. Still takes forever, hopefully v5.1.8 should have all the artefacts. Once you add Changelogs to your fix happy to publish that as well. |
That was great! The change log has been added. |
Can you confirm it works as expected so I can close this issue? Thanks! |
There may be some problems. I set the log from client
The last line of the log shows that the heartbeat packet sending interval is 20s, not 10s. then the server log
|
I found the problem. In client side socket.onopen = function () {
pingInterval = setInterval(function () {
if (Date.now() - lastSentMessageTimestamp > heartBeatInterval) {
try {
socket.send(pingMessage);
lastSentMessageTimestamp = Date.now();
}
catch (e) {
clearTimeout(pingInterval);
}
}
}, heartBeatInterval);
socket.onopened();
}; There is a time error in Specifically, if the 1200ms for the first heartbeat, I will raise a PR to fix this problem. |
pr raised, deepstreamIO/deepstream.io-client-js#550 |
I found that heartbeat packet detection is bidirectional, which means that the server detects whether the time of the last message received is greater than twice the I think that for heartbeat packets, the client must send them strictly according to the set value, and do not skip the sending of heartbeat packets just because they have sent messages. |
Makes sense, thanks! |
Hi everyone! Sorry for being late to the discussion, but since the 5.1.6 release solves the issue with node ws, there is no need to change the socket-factory in the client from the previous 5.1.10 version. That logic is correct.
This is not correct. For every PING sent there is a PONG response, therefore the client does update its
This is unnecesary as stated before, in fact in high payload situations it will add an extra PING message that has no purpose. This works only in scenarios where the client heartbeatInterval <= 2 x server heartbeatInterval + PingPongTime, as oppposed to the existing logic in version 5.1.10 that works when the client heartbeatInterval <= server heartbeatInterval. Both versions fail when the client heartbeatInterval > 2x server heartbeatInterval + PingPongTime. In conclusion, I propose:
Comments? |
Ping is sent by the client, and the server returns pong and the client update
So I don't think it's a good idea to go back to 5.1.10, but we can solve the problem of too many ping messages based on the current version. |
Ok I finally understood your problem (being subscribed only AND receiving messages with an interval less than heartbeat), although this is an issue only in http server. uws has an However as I mentioned previously the fix on the client version 5.1.12 also breaks when the client heartbeatInterval > 2 x server heartbeatInterval + PingPongTime (try it with 3x). An option that should solve the problem is to keep track of exchanged messages:
This way, we can emulate the What do you think? |
We use different socket wrappers so the code can theoretically stay separate. TBH given we are sending pings every 10 or 20 seconds and they should be aggregated within the socket wrapper bulk (so if there are other messages they get bundled in one websocket frame) I'm wondering if there's any harm with keeping this in until someone asks to make deepstream faster, which hasn't really happened yet 🙈. It's def something we can improve on but I'm not sure if it's a high priority vs getting CI systems working and possibly spitting out some react hooks integrations to see if they teases any adoption 😁 |
Hi, I agree the CI is priority, but this is easier for me now :) Ok maybe the ping is not relevant, but the connection still is closed when the client heartbeat interval is bigger than 2 x the server one using node http server and that's an issue I think. What I propose in the last comment should fix it regardless of the client code. That way we also avoid syncing heartbeats as proposed previously |
I'm afraid I'm not fully following yet. The point for syncing heartbeats is the server and client need a single source of truth. If I put in a heartbeat of a thousand on the server and a million on the client then assuming there is a connection loss that doesn't include the correct handshake the server will close but the client will wait for at least a million milliseconds. How exactly does any scenario fix that without having heartbeat synchronization? |
Ok, just had time to come back to this. I was wrong all along, plugging out devices made me realize it :) uws's One more thing, @yasserf please your comments:
Where's the socket wrapper bulk? Couldn't find it in the client code...I guess it should be on |
In our project, Presence API is used to detect client connectivity. We set heartbeat interval to 60000ms on the js client library. If exit the client in a normal way, the presence API can immediately get a logout notification. However, if the client is powered off directly, We have to wait about 20 minutes before the presence API notifies the logout. We need configuration suggestions about when the client power down directly, how to get logout notification as soon as possible.
The text was updated successfully, but these errors were encountered: