README.md in reel-0.2.0 vs README.md in reel-0.3.0.pre

- old
+ new

@@ -1,16 +1,18 @@ ![Reel](https://github.com/celluloid/reel/raw/master/logo.png) ======= [![Build Status](https://secure.travis-ci.org/celluloid/reel.png?branch=master)](http://travis-ci.org/celluloid/reel) +[![Dependency Status](https://gemnasium.com/celluloid/reel.png)](https://gemnasium.com/celluloid/reel) +[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/celluloid/reel) Reel is a fast, non-blocking "evented" web server built on [http_parser.rb][parser], -[libwebsocket][websockets],[ Celluloid::IO][celluloidio], and [nio4r][nio4r]. Thanks +[websocket_parser][websockets], [Celluloid::IO][celluloidio], and [nio4r][nio4r]. Thanks to Celluloid, Reel also works great for multithreaded applications and provides traditional multithreaded blocking I/O support too. [parser]: https://github.com/tmm1/http_parser.rb -[websockets]: https://github.com/imanel/websocket-ruby +[websockets]: https://github.com/afcapel/websocket_parser [celluloidio]: https://github.com/celluloid/celluloid-io [nio4r]: https://github.com/tarcieri/nio4r Connections to Reel can be either non-blocking and handled entirely within the Reel::Server thread, or the same connections can be dispatched to worker @@ -22,25 +24,25 @@ This gives you the best of both worlds: non-blocking I/O for when you're primarily I/O bound, and threads for where you're compute bound. ### Is it any good? -[Yes](http://news.ycombinator.com/item?id=3067434), -but it has room for improvement. A "hello world" web server benchmark, -run on a 2GHz i7 (OS X 10.7.3). All servers used in a single-threaded mode. +[Yes](http://news.ycombinator.com/item?id=3067434) +Here's a "hello world" web server benchmark, run on a 2GHz i7 (OS X 10.7.3). +All servers used in a single-threaded mode. + Reel performance on various Ruby VMs: ``` # httperf --num-conns=50 --num-calls=1000 Ruby Version Throughput Latency ------------ ---------- ------- -JRuby HEAD 5650 reqs/s (0.2 ms/req) -Ruby 1.9.3 5263 reqs/s (0.2 ms/req) -JRuby 1.6.7 4303 reqs/s (0.2 ms/req) +JRuby 1.7.0 3978 req/s (0.3 ms/req) rbx HEAD 2288 reqs/s (0.4 ms/req) +Ruby 1.9.3 2071 req/s (0.5 ms/req) ``` Comparison with other web servers: ``` @@ -52,43 +54,127 @@ ``` All Ruby benchmarks done on Ruby 1.9.3. Latencies given are average-per-request and are not amortized across all concurrent requests. -Usage ------ +API +--- -Reel provides an extremely simple API: +Reel also provides a "bare metal" API which was used in the benchmarks above. +Here are some examples: +### Block Form + +Reel lets you pass a block to initialize which receives connections: + ```ruby require 'reel' Reel::Server.supervise("0.0.0.0", 3000) do |connection| while request = connection.request case request when Reel::Request puts "Client requested: #{request.method} #{request.url}" - connection.respond :ok, "hello, world" + request.respond :ok, "Hello, world!" when Reel::WebSocket puts "Client made a WebSocket request to: #{request.url}" - request << "Hello there" - connection.close + request << "Hello everyone out there in WebSocket land" + request.close break end end end ``` When we read a request from the incoming connection, we'll either get back a Reel::Request object, indicating a normal HTTP connection, or a Reel::WebSocket object for WebSockets connections. -Status ------- +### Subclass Form -Reel is still in an extremely early stage of development and may be -missing a lot of features. It seems to be doing a rudimentary job of -speaking HTTP and has basic keep-alive support. +You can also subclass Reel, which allows additional customizations: + +```ruby +require 'reel' + +class MyServer < Reel::Server + def initialize(host = "127.0.0.1", port = 3000) + super(host, port, &method(:on_connection)) + end + + def on_connection(connection) + while request = connection.request + case request + when Reel::Request + handle_request(request) + when Reel::WebSocket + handle_websocket(request) + end + end + end + + def handle_request(request) + request.respond :ok, "Hello, world!" + end + + def handle_websocket(sock) + sock << "Hello everyone out there in WebSocket land!" + sock.close + end +end + +MyServer.run +``` + +Framework Adapters +------------------ +### Rack + +Reel can be used as a standard Rack server via the "reel" command line +application. Please be aware that Rack support is experimental and that there +are potential complications between using large numbers of rack middlewares +and the limited 4kB stack depth of Ruby Fibers, which are used extensively +by Celluloid. In addition, the Rack specification mandates that request bodies +are rewindable, which prevents streaming request bodies as the spec dictates +they must be written to disk. + +To really leverage Reel's capabilities, you must use Reel via its own API, +or another Ruby library with direct Reel support. + +### Webmachine + +The most notable library with native Reel support is +[webmachine-ruby](https://github.com/seancribbs/webmachine-ruby), +an advanced HTTP framework for Ruby with a complete state machine for proper +processing of HTTP/1.1 requests. Together with Reel, Webmachine provides +full streaming support for both requests and responses. + +To use Reel with Webmachine, add the following to your Gemfile: + +```ruby +gem 'webmachine', git: 'git://github.com/seancribbs/webmachine-ruby.git' +``` + +Then use `config.adapter = :Reel` when configuring a Webmachine app, e.g: + +```ruby +MyApp = Webmachine::Application.new do |app| + app.routes do + add ['*'], MyHome + end + + app.configure do |config| + config.ip = MYAPP_IP + config.port = MYAPP_PORT + config.adapter = :Reel + end +end + +MyApp.run +``` + +See the [Webmachine documentation](http://rubydoc.info/gems/webmachine/frames/file/README.md) +for further information Contributing ------------ * Fork this repository on github