WebSockets in Relation with TCP/IP Sockets on Misultin Erlang HTTP Library-Collection of common programming errors
i must say that i am impressed by Misultin’s support for Web Sockets (some examples here). My JavaScript is firing requests and getting responses down the wire with “negligible” delay or lag, Great !!
Looking at how the data handler loop for WebSockets looks like, it resembles that of normal TCP/IP Sockets, atleast the basic way in Erlang
% callback on received websockets data handle_websocket(Ws) -> receive {browser, Data} -> Ws:send(["received '", Data, "'"]), handle_websocket(Ws); _Ignore -> handle_websocket(Ws) after 5000 -> Ws:send("pushing!"), handle_websocket(Ws) end.
This piece of code is executed in a process which is spawned by Misultin, a function you give to it while starting your server like this below:
start(Port)-> HTTPHandler = fun(Req) -> handle_http(Req, Port) end, WebSocketHandler = fun(Ws) -> handle_websocket(Ws) end, Options = [{port, Port},{loop, HTTPHandler},{ws_loop, WebSocketHandler}], misultin:start_link(Options).
. More Code about this, check out the example page.I have several questions.
Question 1: Can i change the controlling Process of a Web Socket as we normally do with the TCP/IP Sockets in Erlang ? (we normally use: gen_tcp:controlling_process(Socket,NewProcessId)
)
Question 2: Is Misultin the only Erlang/OTP HTTP library which supports WebSockets ? Where are the rest ? EDIT : Now, the reason why i need to be able to transfer the WebSocket control from Misultin
Think of a gen_server
that will control a pool of WebSockets, say its a game Server. In the current Misultin Example, for every WebSocket Connection, there is a controlling process, in other-words for every WebSocket, there will be a spawned process. Now, i know Erlang is a hero with Processes but, i do not want this, i want these initial processes to die as soon as they handle over to my gen_server
the control authority of the WebSocket.
I would want this gen_server
to switch data amongst these WebSockets. In the current implementation, i need to keep track of the Pid
of the Misultin handle_websocket process like this:
%% Here is misultin's control process %% I get its Pid and save it somewhere %% and link it to my_gen_server so that %% if it exits i know its gone handle_websocket(Ws)-> process_flag(trap_exit,true), Pid = self(), link(my_gen_server), save_connection(Pid), wait_msgs(Ws). wait_msgs(Ws)-> receive {browser,Data}-> FromPid = self(), send_to_gen_server(Data,FromPid), handle_websocket(Ws); {broadcast,Message} -> %% i can broadcast to all connected WebSockets Ws:send(Message), handle_websocket(Ws); _Ignore -> handle_websocket(Ws) end.
Above, the idea works very well, whereby i save all controlling process into Mnesia Ram Table and look it up against a given criteria if the application wants to send to that particular user a message. However, with what i want to achieve, i realise that in the real-world, the processes may be so many that my server may crash. I want atleast one gen_server
to control thousands of the Web Sockets than having a process for each Web Socket, in this way, i could some how conserve memory.
Suggestion: Misultin’s Author could create Web Socket Groups implementation for us in his next release, whereby we can have a group of WebSockets controlled by the same process. This would be similar to Nitrogen's Comet Groups
in which comet connections are grouped together under the same control. If this aint possible, we will need the control ourselves, provide an API where we can take over the control of these Web Sockets.
What do you Engineers think about this ?
What is your suggestion and/or Comment about this ?
Misultin’s Author could say something about this. Thanks to all
-
Misultin’s author here.
I strongly discourage you from changing the controlling process, because that will break all Misultin’s internals. Just as Steve suggested, YAWS and Cowboy support WebSockets, and there are implementations done over Mochiweb but I’m not aware of any being actively maintained.
You are discussing about memory concerns, but I think you are mixing concepts. I cannot understand why you do need to control everything ‘centrally’ from a gen_server: your assumption that ‘many processes will crash your VM’ is actually wrong, Erlang is built upon the actor’s model and this has many advantages:
- performance due to multicore usage which is not there if you use a single gen_server
- being able to use the ‘let it crash’ philosophy: currently it looks like your gen_server crashing would bring down all available games
- …
Erlang is able to handle hundreds of thousands processes on a single VM, and you’ll be out of available file descriptors for your open Sockets way before that happens.
So, I’d suggest you consider having your game logic within individual Websocket processes, and use message passing to make them interact. You may consider spawning ‘game processes’ which hold information of a single game’s participants and status, for instance. Eventually, a gen_server that keeps track of the available games – and does only that (eventually by owning an ETS table). That’s the way I’d probably want to go, all with the appropriate supervisors’ structure.
Obviously, I’m not sure what you are trying to achieve so I’m just assuming here. But if your concern is memory – well, as TRIAL AND ERROR EXP said here below: don’t premature optimize something, especially when you are considering to use Erlang in a way that looks like it might actually limit it from doing what it is capable of.
My $0.02.
-
(one) Cowboy developer here.
I wouldn’t recommend using any type of central server being responsible for controlling a set of websocket connections. The main reason is that this is a premature optimization, you are only speculating about the memory usage.
A test done earlier last year for half a million websocket connections on a single server resulted in misultin using 20GB of memory, cowboy using 16.2GB or 14.3GB, depending on if the websocket processes were hibernating or not. You can assume that all erlang implementations of websockets are very close to these numbers.
The difference between cowboy not using hibernate and misultin should be pretty close to the memory overhead of using an extra process per connection. (feel free to correct me on this ostinelli).
I am willing to bet that it is much cheaper to take this into account when buying the servers than it is to design and resolve issues in an application where you don’t have a 1:1 mapping between tasks/resources and processes.
https://twitter.com/#!/nivertech/status/114460039674212352
-
Not sure about question 1, but regarding question 2, Yaws and Cowboy also support WebSockets.