RJ / www.metabrew.com

Static site generation for my blog
0 stars 0 forks source link

A Million-user Comet Application with Mochiweb, Part 2 #7

Open RJ opened 3 years ago

RJ commented 3 years ago

Written on 10/23/2008 15:06:08

URL: http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-2

RJ commented 3 years ago

Comment written by scott on 10/23/2008 15:59:24

Wow. A great follow-up to your part one. Thank you! This is incredibly helpful.

RJ commented 3 years ago

Comment written by dsmith on 10/23/2008 18:02:24

Nice. I have been hacking Erlang code for a several years now, and read most of the Erlang related resources I can find. This is the most useful I've seen in a while.

RJ commented 3 years ago

Comment written by daveb on 10/24/2008 05:32:34

Excellent series! I'm not only learning some nice Erlang tricks, but some scripting ones as well. Thanks!

RJ commented 3 years ago

Comment written by pablo on 10/24/2008 17:45:47

Thanks you for such a great article!
I found this one particularly helpful, I've just read it and already applying some of tips!

RJ commented 3 years ago

Comment written by Thijs (Shenzhen) on 10/26/2008 11:18:58

Very nice article. I'm also using Erlang at work and this article has given me some additional ideas. I'm also thinking about making a Comet application with Erlang/Mochiweb and definitely look forward to your results with 1 million clients.

RJ commented 3 years ago

Comment written by John Wright on 10/30/2008 19:12:37

Yes, please do the part 3, :)

RJ commented 3 years ago

Comment written by Mark on 01/01/2009 16:32:59

Richard, this is a great series. I've been diving in and out of learning Erlang because I needed Mnesia rather than SQL, and this has to be the greatest leg-up that I've come across.

Within in the next three months I should finally be able to finish my f*****g application!

RJ commented 3 years ago

Comment written by xuzhe on 08/03/2009 03:56:11

Thanks for your article,I copy the code and test to send messages.Mochiweb report me a error:
{mochiweb_socket_server,235,
{child_error,{noproc,{gen_server,call,[undefined,{login,123,}]}}}}

what's the meaning

RJ commented 3 years ago

Comment written by Shayne on 11/05/2009 15:39:57

Anyone know how to detect client disconnects not using a timeout? In this code, it would not “logout” immediately… I think it involves making the socket active instead of passive, but can’t figure it out. Richard, any thoughts? Thanks!

RJ commented 3 years ago

Comment written by Nemanja on 01/20/2010 17:18:57

Richard, first thank you for this post. It is one of my favourites on the web.

I took the code from these examples and made an attempt to do long-polling using your method. I ran into a huge problem after adding in the proc_lib:hibernate(..) code to save on memory. I'm not sure if perhaps I messed something up or have a different version of Mochiweb than the one you were using, but it seems with that code, the Mochiweb process will never release its socket_acceptor process which handles the next incoming request. Meaning that after the 1M requests, Mochiweb stops accepting any new connections, even if you logout.

Perhaps you may not have noticed this because "mochiweb_http:start([{max, 1000000}" is set so high. As a test, I set the max to 3 concurrent requests. After the 3rd one (even if the previous ones disconnected), I received a message from Mochiweb telling me it was no longer accepting any new connections and I found no way to recover from that.

Removing the proc_lib:hibernate(..) code from the loop(..) and feed(..) functions in mochiconntest_app.erl resolved this.

I was just wondering if it was something you ran into as well or if perhaps I had just messed something up.

RJ commented 3 years ago

Comment written by RJ on 01/20/2010 18:32:39

Nemanja: that isn't something I ran into, since as you said I set the max very high, and restarted in between tests.

It sounds like when a connection is closed, the mochiweb proc doesn't notice since it's hibernating. Perhaps you can put the socket into active mode once you've accepted the connection, so that the proc is sent a msg on close/error (to wake it up from hibernation).

Been a while since I looked at this code, let me know how you get on. I'm RJ2 on irc.freenode.org #erlang if you want to chat.

RJ commented 3 years ago

Comment written by Nemanja on 01/20/2010 19:50:47

Richard, thanks for the (superfast) reply. I figured it had been a while since you looked at this so I thought it was a shot in the dark.

I'll experiment with it some more and let you know if I find a work-around.

Thanks again and see you on IRC. :)

RJ commented 3 years ago

Comment written by Nemanja on 01/20/2010 20:23:26

Richard, I think I got the active socket portion working.

Just replace the following in mochiconntest_web.erl:
loop(Req, DocRoot) ->
"/" ++ Path = Req:get(path),
case Req:get(method) of
Method when Method =:= 'GET'; Method =:= 'HEAD' ->

with:
loop(Req, DocRoot) ->
Socket = Req:get(socket),
inet:setopts(Socket, [{active, once}]),
"/" ++ Path = Req:get(path),
case Req:get(method) of
Method when Method =:= 'GET'; Method =:= 'HEAD' ->

That will grab the socket of the current request and set it to be active. Once that is done at the beginning of the loop to process the request, it is then possible to do the proc_lib:hibernate(..) without any issues and the socket adapters no longer hang! I have not tested it with the olde C10k test to see that the memory consumption savings remain, but I can't see any reason that would change.

Shayne, this might help you since you were looking for a way to make the sockets active to detect disconnects without relying on timeouts.

RJ commented 3 years ago

Comment written by erlnewb on 02/04/2010 19:22:00

Thanks for the tutorial. But i'm having issues running it. I copied and pasted above example but cant seem to get to work properly.

Connecting via browser to
http://localhost:8000/test/123

I get message on router side. But router:send(123, "testing") does not deliver message to browser until I abort mochiweb VM.

Running on OSX.

RJ commented 3 years ago

Comment written by RJ on 03/19/2010 19:24:16

To erlnewb: Try using firefox instead of safari? I think specific headers are required to make comet/streaming behave in safari.

RJ commented 3 years ago

Comment written by Cameron McCloud on 10/18/2011 14:05:05

This is for anyone trying this in a recent Erlang (I'm using R14B04):

The following line fails:

router:send(Id, "Fake message Num = " ++ Num),

The ++ operator doesn't like mixing strings and numbers. I've used the following instead:

router:send(Id, io_lib.format("Fake message Num = ~p", [Num])),

RJ commented 3 years ago

Comment written by Cameron McCloud on 10/18/2011 16:02:22

Another note: if you're testing this by distributing over multiple nodes e.g on AWS EC2, you need port 4369 open and you also need a range of ports open for Erlang to do it's distributed stuff on: (e.g. 9100-9105).

erl -name n2 -kernel inet_dist_listen_min 9100 inet_dist_listen_max 9105 --setcookie abc

RJ commented 3 years ago

Comment written by escorte on 03/20/2012 16:09:53

There are certainly a couple more details to take into consideration, but thank you for sharing this information.