deman_killer
deman_killer

Reputation: 98

How to run multiple Sinatra instances without anything else?

I want to spawn a lot of configurable Sinatra servers.
For example:

require 'sinatra/base'
class AwesomeOne
    def initialize port
        @sapp = Sinatra.new {
            set :port => port
            get '/'do
                "Hi!"
            end
        }
    end
    def run!
        @sapp.run!
    end
end

and then:

ths = []
(1111..9999).each { |port|
    ths.push Thread.new { AwesomeOne.new(port).run! }
}

But something goes wrong: i can't access each page. But some of them seems accessible.

So, how to run Sinatra multiple times in one .rb file?

Upvotes: 2

Views: 649

Answers (1)

peter
peter

Reputation: 42207

I happen to need the same thing soon so I did some research. You could use Sinatra's cascade, routing or middleware options, see https://www.safaribooksonline.com/library/view/sinatra-up-and/9781449306847/ch04.html and search for 'multiple', I advise you to buy the book and read it, it is all very usefull stuff !

But more leaning to your approach you can use the eventmachine Sinatra allready uses to run multiple apps on different ports, Ruby itself is started only once. See http://recipes.sinatrarb.com/p/embed/event-machine for explanation and more examples. I combined the example with your code.

# adapted from http://recipes.sinatrarb.com/p/embed/event-machine

require 'eventmachine'
require 'sinatra/base'
require 'thin'

def run(opts)

  EM.run do
    server  = opts[:server] || 'thin'
    host    = opts[:host]   || '0.0.0.0'
    port    = opts[:port]   || '8181'
    web_app = opts[:app]

    dispatch = Rack::Builder.app do
      map '/' do
        run web_app
      end
    end

    unless ['thin', 'hatetepe', 'goliath'].include? server
      raise "Need an EM webserver, but #{server} isn't"
    end

    Rack::Server.start({
      app:    dispatch,
      server: server,
      Host:   host,
      Port:   port,
      signals: false,
    })
  end
end

class HelloApp < Sinatra::Base
  configure do
    set :threaded, true
  end

  get '/hello' do
    "Hello World from port #{request.port}"
  end
end

ths = []
(4567..4569).each do |port|
  ths.push Thread.new { run app: HelloApp.new, port: port }
end

ths.each{|t| t.join}

output

Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:4567, CTRL+C to stop
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:4568, CTRL+C to stop
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:4569, CTRL+C to stop

In windows cmd netstat -ab this gives

TCP    0.0.0.0:4567           ******:0              LISTENING
TCP    0.0.0.0:4568           ******:0              LISTENING
TCP    0.0.0.0:4569           ******:0              LISTENING

And the hello example on all ports works.

Upvotes: 1

Related Questions