-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[websocket] Implement ping/pong for maintaining websockets through proxies. #1410
Comments
There is a package out there that seems to do what we need: it's called wska. |
That looks like it might do the trick, would that replace reconnecting-websocket on the client side? I'm also unsure whether the ping/pong needs to be delivered through the connection as jsonrpc2 or not, or if I am just not grokking how its working. |
Hi @Zate. I'll start looking into the issue, but I'll also need to learn the technical details of websockets. If you want to submit a patch as a learning experience, you are very welcome. It doesn't have to be perfect :) |
I will give that a shot thanks :) |
I managed to replace reconnecting-websocket with wska and resolve a couple of issues but I'm stuck at something to do with crypto and the browser when it goes to create the websocket. Trying to work out how to use crypto-browserify to perhaps fix it. |
👍
Could this thread help to resolve your issue? It recommends marking If we you want to modify the generated webpack configuration, you can look into the generator here. |
Thank you! I think that is exactly what I am after. Will test that here in a bit. |
It is there to reconnect on connection loss. So I think the ping/pong and reconnecting are both needed. It would be nice if the terminal would auto-reconnect, too. |
Agreed, the wska module claims to do both. I'll see once I can get it to run heh :) |
I have tried many different things. Tried to add crypto to the "externals" in webpack-generator.ts as in that link above, tried using browserify / crypto-browserify in many different ways. Back to just doing the externals and getting this :
Going to keep trying and looking but there is so much about how node/npm/yarn/typescript works that I do not understand. I'm not able to have vscode on my chromebook so being able to host this myself and write Golang in a browser would be great :) (do not want to use dev mode). |
@Zate, please create a PR with your changes (as is), add the If that is a build/config issue, I can take a look. |
Created a PR with the changes I ended up on. I removed a great deal of cruft out of it as I tried a whole bunch of things but this is ultimately where I have it now. #1431 |
Did not work for me either. I have opened a follow-up here. Maybe, we should try to implement our own ping/pong mechanism either built on the top of |
ws has the functions for ping/pong existing in it, I just couldn't find the right place to put them. It feels like we'd need a setInterval() loop on socket creation to send a ping from the server every 30s (or what ever we decide). I was also not sure if vscode-ws-jsonrpc was getting in the way in some way. Sorry I understand what needs to happen but not enough about js/ts to implement it. we could leave the current reconnecting-websocket on the client side and simply implement ping on the server side I think. |
Why don't do https://github.com/websockets/ws#how-to-detect-and-close-broken-connections here: https://github.com/theia-ide/theia/blob/592c54b90ebcf1357f1e6bbf7ac395f062ea50ba/packages/core/src/node/messaging/connection.ts#L43 It is used by json-rpc as well as by terminals. |
I had tried that before and couldn't get it to work. It wasn't erroring, it just wasnt emitting pings. I will give it another shot and paste back what I come up with so someone can see if I am making some kind of silly mistake. |
So a couple of updates. I got ping/pong working for all the websockets, even terminal. I just need to clean up the code a little and I can submit a PR. On the other hand, I worked out my specific issue is Cloudflare. They have a hard limit on websocket connections of 100 seconds. It disconnects and then the reconnecting-websockets reconnects. The terminal socket doesn't reconnect. There are some issues with the code I've put in, I think it's not good from a performance/resource usage perspective and it seems to ping/pong too often, or has multiple of them running per websocket. It does help with keeping sockets open with no deliberate tampering such as cloudflare in the way, but I've yet to test if that was happening anyhow. So I plan to redo the swarm I am hosting these docker containers on and move cloudflare out of the way to see if it still happens. If it does in code without my fix, I'll clean up my code and do a PR, if it doesn't actually happen with CF out of the way and the traefik proxy in place then I can assume the issue is Cloudflare and only related to that and no fix is required. |
In our case we're using the traefik proxy too and suspect it to drop the inactive websocket connections. Please keep us updated with what you find! |
Signed-off-by: Zate Berg <zate75@gmail.com>
Signed-off-by: Zate Berg <zate75@gmail.com>
Signed-off-by: Zate Berg <zate75@gmail.com>
Signed-off-by: Zate Berg <zate75@gmail.com>
Signed-off-by: Zate <zate75@gmail.com>
New PR for this : #1534 |
Signed-off-by: Zate Berg <zate75@gmail.com>
Signed-off-by: Zate <zate75@gmail.com>
Added a ping from the server side to each socket (even terminal) every 30 seconds. Client will respond with a pong. Signed-off-by: Zate Berg <zate75@gmail.com>
Added a ping from the server side to each socket (even terminal) every 30 seconds. Client will respond with a pong. Signed-off-by: Zate <zate75@gmail.com>
Added a ping from the server side to each socket (even terminal) every 30 seconds. Client will respond with a pong. Signed-off-by: Zate <zate75@gmail.com>
This has been completed and merged. |
I'd like to raise a few issues around the websocket implementation and the troubles it causes systems behind a proxy.
It's highly likely people will end up running Theia behind some kind of proxy, be that nginx or something like traefik or similar at the head of a k8s cluster etc. In those situations the proxies general enforce a timeout for sockets not in use. The websocket RFC contains a mechanism called ping/pong that maintains traffic through a websocket to keep it open. Those calls are included in websockets/ws that is being used by Theia but they are not implemented in the server/client to keep sockets open.
There does seem to be a lib being used on the client side to reopen closed sockets that may have been implemented to help deal with this issue. Ideally a websocket should remain open as long as the program is in use if ping/pong is done correctly unless some kind of network interruption is encountered. In that case being able to re-open the socket is useful, but it should only happen if the socket is closed. As it stands right now, after a period of inactivity the sockets are closed and re-opened and in my testing this can sometimes lead to functionality in the client being broken.
I've also noticed that the terminal instance does not use keep alives and doesn't get re-opened as it seems to be using a different mechanism to do it's sockets (not vscode-ws-jsonrpc).
I think the appropriate place to solve this issue might be in this file and do a setInterval() to handle sending a ping every 30-60s (configurable) across all open sockets. I've tried playing with this in my own fork but I am very new to typescript and javascript and thought it would perhaps be faster to open an issue on it. I can certainly learn from the implementation used if this is addressed.
End result is I think the site should continue to use the same sockets (and not open new ones) until forced to by a disconnect/breakage and the keep alive time be something that can be configurable ( to adjust for differing proxy timeout values you might not have control over). A default of 30s would be appropriate I fee.
I think this is related to #979
The text was updated successfully, but these errors were encountered: