Home Benchmarks Real World Use / Testimonials Documentation FAQ / Support Upcoming Release Features Mongrel Download Changelog
Swiftcore Swiftiply v. 0.6 Documentation
Change Summary
Repository Interface

Contents

Overview
Installation
Quickstart
Command Line
Framework Support
Configuration
Sample Configurations
Other Resources
Overview

Swiftiply is a clustering proxy server for web applications. What makes it different from other clustering proxies, however, is that it expects the backend processes to connect to it. That is, the backend processes are clients of the Swiftiply server, as are the browsers out in userland. The advantage of this is that it permits the back ends to maintain a persistent connection with the proxy server, which eliminates socket setup/teardown costs. And even more importantly than that, it permits backend processes to be started up or shut down without requiring any notification or configuration of the proxy. So, if more capacity is needed, all one needs to do is start the processes. It will immediately be available and will begin to be utilized.

The drawback to this sort of an architecture is that it is exactly opposite of what most web frameworks expect. Most Ruby frameworks, however, utilize Mongrel as one of their primary deployment tools, which allows this drawback to be neutralized. Swiftiply provides a class that overrides pieces of Mongrel (version 1.0.1), allowing any Mongrel handler to be used with Swiftiply, transparently.

Because Mongrel is the preferred deployment method for most Ruby frameworks, Swiftiply includes a version of Mongrel (found in swiftcore/swiftiplied_mongrel.rb) that has been modified to work as a swiftiply client. This should be transparent to any existing Mongrel handlers, allowing them all to work with Swiftiply.

In addition, as an offshoot of the swiftiplied_mongrel, there is a second version that is available. This other version is found in swiftcore/evented_mongrel.rb; it is a version of Mongrel that has its network traffic handled by EventMachine, creating a Mongrel that runs in an event based mode instead of a threaded mode. For many applications, running in an event based mode will give better throughput than running in a threaded mode, especially when there are concurrent requests coming in.

This is because the event based operation handles requests efficiently, on a first come, first served basis, without the overhead of threads. For the typical Rails application, this means that request handling may be slightly faster than the threaded Mongrel for single, non-concurrent requests. When there are concurrent requests, though, the differential increases quickly.

Installation

To install Swiftiply:

ruby setup.rb

The Swiftiply executable will be installed installed into the ruby installation's bindir, along with associated scripts, and the libraries into the site lib. rdoc information will also be generated.

ruby setup.rb --help

to see a full list of options.

After installation, the test suite (full test suite coming soon) can be ran with:

ruby setup.rb test

Swiftiply depends on EventMachine and the Mongrel support is written against Mongrel 1.0.1. Swiftiply (and EventMachine) can be installed as a gem via gem install swiftiply.

Quickstart

To start a Swiftiply instance, first create a configuration file (YAML format):

cluster_address: swiftcore.org
cluster_port: 80
daemonize: true
epoll: true
epoll_descriptors: 20000
map:
  - incoming:
    - swiftcore.org
    - www.swiftcore.org
    outgoing: 127.0.0.1:30000
    default: true
    docroot: /var/www/swiftcore.org/docs
  - incoming: iowa.swiftcore.org
    outgoing: 127.0.0.1:30010
  - incoming: analogger.swiftcore.org
    outgoing: 127.0.0.1:30020
  - incoming:
    - swiftiply.com
    - www.swiftiply.com
    - swiftiply.swiftcore.org
    outgoing: 127.0.0.1:30030
    redeployable: true
    docroot: /var/www/swiftiply.swiftcore.org/docs
    cache_directory: public
    cache_extensions:
      - htm
      - html
      - txt

Then start Swiftiply:

swiftiply -c config_file

An instance of Swiftiply is now running, listening on a socket for connections from browsers.

Swiftiply Command Line Arguments
-c, --config CONFFILE
Use this option to specify the configuration file that Swiftiply will use.
--cluster-address [ADDRESS]
The hostname/IP address that swiftiply will listen for connections on.
--cluster-port [PORT]
The port that swiftiply will listen for connections on.
--backend-address [ADDRESS]
The default hostname/IP address that swiftiply will send connections to that don't match something else in the configuration file.
--backend-port [PORT]
The default port that swiftiply will send connections to that don't match something else in the configuration file.
-d, --daemonize [YN]
Whether swiftiply should put itself into the background.
-t, --timeout [SECONDS]
The server unavailable timeout. Defaults to 3 seconds. Keep this number small.
-p, --print-config
Print the full configuration.
Framework Support
Swiftcore IOWA

IOWA has built in support for running in evented and clustered modes.

Rails

Swiftiply provides a _REPLACEMENT_ to mongrel_rails that, throught the use of an environment variable, can be told to run in either the evented mode or the swiftiplied mode.

To run a Rails app in evented mode, set the EVENT environment variable. On a unixlike system:

env EVENT=1 mongrel_rails

To run in swiftiplied mode:

env SWIFT=1 mongrel_rails

Because Swiftiply backends connect to the Swiftiply server, they all connect on the same port. This is important. Each of the backends runs against the same port. To make it easier to start multiple Rails backends, a helper script, swiftiply_mongrel_rails, is provided. It is just a light wrapper around mongrel_rails that will let one start N backends, with proper pid files, and stop them.

Merb

The merb source (trunk only, at this point), has Swiftiply support that works just like the Rails support, built in.

Ramaze

A couple adapters for Ramaze are included, to allow Ramaze to run with either the evented or the swiftiplied mongrels. They are installed into

ramaze/adapter/evented_mongrel.rb ramaze/adapter/swiftiplied_mongrel.rb
Other Frameworks

Swiftiply has been tested with Camping and Nitro, as well. Direct support for them is not yet bundled, but will be in an upcoming release. In the meantime, all that really needs to happen to use the evented_mongrel or swiftiplied_mongrel with your application is to require the proper library -- swiftcore/evented_mongrel or swiftcore/swiftiplied_mongrel.

Configuration

Swiftiply takes a single configuration file which defines for it where it should listen for incoming connections, whether it should daemonize itself, and then provides a map of incoming domain names and the address/port to proxy that traffic to. That outgoing address/port is where the backends for that site will connect to. The configuration file uses a YAML format. For the purposes of Swiftiply configuration, what this means is that key/value pairs are placed one per line, with a : between the key and the value, and lists of items are created by leading off a list item with - , one per line.

The following items can be specified in a Swiftiply configuration file:

cluster_address
cluster_address: 0.0.0.0

This is the address/IP that Swiftiply will listen on for traffic from browsers.

cluster_port
cluster_port: 8080

This is the port, on the cluster_address, that Swiftiply will listen on for traffic from browsers.

daemonize
daemonize: true

If this is set to true, Swiftiply will attempt to put itself into the background. This currently only works on platforms where forks() is supported (i.e. not win win32 platforms).

epoll
epoll: true

With version 0.8.0, EventMachine now supports using epoll() for the event loop instead of select() on platforms that support it (Linux 2.6). The benefit to epoll() is that performance does not degrade as the number of file descriptos increases, and it can handle more than the 1024 descriptors that select() under Ruby is limited to. This lets Swiftiply to scale to handling many thousands of connections all at the same time. There is no downside to attempting to enable epoll, as it will silently fail on plaforms where it is not supported, so Swiftiply currently defaults to attempting to enable epoll support. If, for some reason, you want to ensure that it is not used, you can use epoll: false to disallow it.

epoll_descriptors
epoll_descriptors: 20000

Swiftiply defaults to a descriptor table size of 4096. This means that it will handle 4096 active connections. If you would like that limit to be higher, you may use this config setting to change that table size.

timeout
timeout: 3

The timeout is the number of seconds that Swiftiply will hold on to a browser's connection, waiting for a backend to take the connection and service it, before giving up and returning a 503 Server Unavailable error to the browser. The default is three seconds. If your web framework actions are slow, you may want to increase that number, but try to keep it as low as you can.

map
map:
  - incoming:
    - swiftcore.org
    - www.swiftcore.org
    outgoing: 127.0.0.1:30000
    default: true
    docroot: /var/www/swiftcore.org/docs
  - incoming: iowa.swiftcore.org
    outgoing: 127.0.0.1:30010
  - incoming: analogger.swiftcore.org
    outgoing: 127.0.0.1:30020
  - incoming:
    - swiftiply.com
    - www.swiftiply.com
    - swiftiply.swiftcore.org
    outgoing: 127.0.0.1:30030
    docroot: /var/www/swiftiply.swiftcore.org/docs
    cache_directory: public
    cache_extensions:
      - htm
      - html
      - txt

The map section contains the mapping of incoming hostnames to the outgoing address/port that the backend(s) for the site are listening on.

incoming
  - incoming: foo.bar.com

or

  - incoming:
    - foobar.com
    - www.foobar.com

This is the hostname or hostnames to match against.

outgoing
outgoing: 127.0.0.1:33333

This is the address/port that the backend(s) for the site are expected to be connected to.

default
default: true

If this option is set to true, then this incoming/outgoing set is the default set. Any request that comes into Swiftiply that does not match another set is sent to the default.

docroot
docroot: /var/www/swiftiply.swiftcore.org/docs

Swiftiply will serve your static files directly, itself. To enable this, just provide a docroot declaration. Swiftiply will check in the docroot for a file that matches the requested uri before dispatching the request to a backend. If a match is found, it will be delivered.

cache_directory
cache_directory: public

Rails, and other frameworks, can cache generated pages in a directory that the webserver can then use to fullfill requests, eliminating the need for those requests to go all the way back inside of the framework to be fulfilled. If your app is using a page cache, you can have Swiftiply serve files from it with this directive. Swiftiply will look in docroot/cache_directory if it doesn't find the requested uri in the docroot. If it doesn't find a file to fulfill the uri as requested, it will append .html to the uri and check again.

cache_extensions
cache_extensions:
  - htm
  - html
  - txt

If you would like Swiftiply to check more extensions than just .html, list each of them under a cache_extensions directive. Each will be checked in order until a match is found. If none is found, then the request will be dispatched to a backend for handling.

redeployable
redeployable: true

If the redeployable attribute is turned on (it defaults to off), then if a backend goes away -- is killed, crashes, hangs, has a walrus fall from the sky on top of it, etc... -- Swiftiply will detect that and will redeploy the request to the next available backend, so long as the backend had not started to return a response.

There is a limit to the size of the requests that will be redeployed, however. It defaults to 16k, but may be set to a different size by assigning that size to the redeployable attribute. e.x.

redeployable: 114168

Requests that exceed the size limit are treated like any other request, and will be dropped instead of redeployed if the backend handling it goes away.

Samples
Resources

In addition to this site, there is a mailing list for Swiftiply, and an IRC channel on http://freenode.net, #swiftcore.

There is an RSS feed that is updated automatically when site content is updated. It is at http://swiftiply.swiftcore.org.