Forum: Ruby Multiple threads on single port

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
9f8ef676e9b0095de0c2ec36a0481a30?d=identicon&s=25 Stuart Brand (stuartbrand)
on 2006-06-06 16:54
Hi all

Can I use Ruby threads to have more then 1 server process running on the
same port

something like

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
threads = []


10.times do |i|
threads[i] = Thread.new {
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end
}
end

Would this produce 10 processes that could take independent connection?
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-06-06 18:03
Stuart Brand wrote:
> Hi all
>
> Can I use Ruby threads to have more then 1 server process running on the
> same port
>
> something like

[... example elided ...]


Not quite.  I believe you can only have one thread listening to a port
at a given time.  The idiom generally is to accept the connection in one
thread, and then pass the accepted connection to a different thread for
processing.  So one thread handles accepting and multiple threads manage
the processing.

-- Jim Weirich
F889bf17449ffbf62345d2b2d316a937?d=identicon&s=25 Michal Suchanek (Guest)
on 2006-06-06 18:37
(Received via mailing list)
On 6/6/06, Stuart Brand <stuart@server-solution.co.uk> wrote:
> threads = []
> }
> end
>
> Would this produce 10 processes that could take independent connection?

This will probably create multiple threads that accept connections. I
only did
while(session = server.accept)
  Thread.new{...}
end
and it was in C. But you should be aware of the fact that depending on
the request processing you do in your thread you may not get any
thread switch until the request is handled. But at least print should
probably trigger the ruby thread scheduler.

HTH

Michal
1b5341b64f7ce0244366eae17f06c801?d=identicon&s=25 Kirk Haines (Guest)
on 2006-06-06 18:47
(Received via mailing list)
On Tuesday 06 June 2006 8:55 am, Stuart Brand wrote:

>   session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
>   session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
>   session.close
> end
> }
> end

Don't do this.

Just have a thread of execution that is in a while loop doing the
accepts on
the socket, and have it spawn threads to handle the connections.

def handle_connection(session)
   puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end

while (session = server.accept)
  Thread.new {handle_connection(session)}
end


Kirk Haines
481b8eedcc884289756246e12d1869c1?d=identicon&s=25 Francis Cianfrocca (Guest)
on 2006-06-06 18:50
(Received via mailing list)
It works, but not terribly well. Whenever you call TCPServer#accept in a
program with more than one thread, the acceptor socket goes on a wait
queue
inside Ruby until it's readable- it doesn't cross into the kernel. But I
tried your program and stress-tested it with ten threads, and
performance
was abysmal. So I'd guess there's some interaction with Ruby's thread
scheduler that isn't quite normal. I'm not sure what you're trying to do
but
you might be better off calling accept in one thread and passing the
accepted sockets to a thread pool, or using nonblocking IO. Another
standard
alternative is to fork a process after accepting each socket- this is a
perfectly good solution if your performance needs are low.
9f8ef676e9b0095de0c2ec36a0481a30?d=identicon&s=25 Stuart Brand (stuartbrand)
on 2006-06-06 20:53
Ok, the final code for this example I have done is


require 'socket'
port = (ARGV[0] || 123).to_i
server = TCPServer.new('localhost', port)
threads = []


10.times do |i|
threads[i] = Thread.new {
        while (session = server.accept)
                puts "Request: #{session.gets}"
                session.print "HTTP/1.1 200/OK\r\nContent-type:
text/html\r\n\r\n"
                session.print
"<html><body><h1>#{Time.now}</h1></body></html>\r\n"
                session.close
        end
}
end

threads.each { |t| t.join}

However, the only stress I can do is the ab apache test, this shows the
same 1, 10 or 100 threads, how do I do a proper stress test??

Many thanks

Stuart
This topic is locked and can not be replied to.