Keep alives are NOT for HTTP only. They are needed also when you have some kind of control channel like WebSockets, as you can't be sure the user is still there even though no TCP disconnection has been detected (e.g., still waiting for timeouts to fire). This is standard practice in other frameworks as well. Anyway, I agree that it's a bit awkward to keep-alive each session when you're sharing the channel across multiple sessions, but unfortunately there's not much we can do about that, considering the modular nature of transports (different transports may have different requirements).
If you want to reduce that number, and you're already wrapping the communication on the server side, one thing you may want to do is using a single session and add all the handles there, so that you only have to keep-alive one: the downside is it might be trickier to keep track of individual users (e.g., if you're using a session for each of them) and to get rid of a specific session (you have to know which handles to remove, when before you could just remove the session entirely).
L.