Skip to content

Commit

Permalink
README and licensing
Browse files Browse the repository at this point in the history
BSD 2-clause for double-boiler and MIT carried over from Foreman.

Signed-off-by: Dan Farina <drfarina@acm.org>
  • Loading branch information
Dan Farina committed Oct 4, 2011
1 parent 13c7bb2 commit b8177e8
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (c) 2011, Daniel Farina
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 changes: 11 additions & 0 deletions LICENSE.foreman
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(The copyright years and holders are not explicitly filled out in the
Foreman projct, but they do say "MIT", so here's a copy of the license
text that follows)

Copyright (c) <year> <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
96 changes: 96 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
Double-Boiler
=============

Double Boiler is a work-in-progress demonstration of how to pack extra
processes into every Heroku (or other Heroku-alike) process, as well
as attempting to squeeze as much throughput as possible out of a
single Heroku process.

It currently uses Python, Django, Celery, and Foreman, a desktop
implementation of the Procfile format that is preferred by Heroku.
Because there is a second Procfile *not* interpreted by Heroku
(``LocalProcfile``) that is used to start more processes within a
single Heroku process (seen in ``Procfile``) there is a
double-layering of Procfiles. It is this technique that gives the
project its name.

The intention was that hobbyists who wanted some asynchronous
execution via Celery who cannot justify two full Heroku processes
could still get all the expressivity they desire, so long as all their
required processes fit into one of the containers furnished by their
platform-as-a-service provider. In a system large enough to keep
multiple process types busy this trick is probably just extra
complexity.

Finally, each of the processes started in ``LocalProcfile`` are
themselves multi-process: Celery starts multiple forked workers to
service asynchronous jobs, and Gunicorn starts multiple web serving
backends. To get even more throughput from each forked Gunicorn
worker, the gevent backend is used to process multiple requests per
Gunicorn backend in a cooperatively interleaved fashion, using the
time that would normally be spent waiting for I/O to do even more
work.

The history of the project in Git attempts to be reasonably well
documented, but there is no reason why it cannot be used as a
hello-world template in its latest revision.

Caveats
-------

* Because this project intended to be a template of kinds, no stable
Django ``SECRET_KEY`` (in ``settings.py``) is defined. Instead, a
random one is created upon every startup. It is completely
necessary to make a stable ``SECRET_KEY`` in production settings,
and the current code reads an environment variable called
``DJANGO_SECRET_KEY``.

One can set it in their Heroku environment easily::

$ heroku config:add DJANGO_SECRET_KEY='my-long-random-thing-here'

* Also, as a normal Django project, it is necessary to run ``syncdb``
to have things run at all correctly, especially the first time. You
can do this on Heroku with::

$ heroku run hellodjango/manage.py syncdb

* There has been no attempt to try tweaking the concurrency (aka
number of forked workers) levels of Celery and Gunicorn to be
sensible for Heroku. If you see out of memory errors (Python calls
these MemoryError exceptions) then some of your workers or web
processes may be using too much memory, and reducing the number of
forked workers may help.

* gevent monkey-patches underlying Python libraries to make I/O done
through them also imply a cooperative-scheduling task-switching
opportunity. This very often but does not always work (bugs or
misbehavior between gevent and other common packages are tracked
with the gevent project and mailing lists). One can opt-out of
gevent by using the 'sync' backend (as detailed by the Gunicorn
documentation) instead of the gevent one.

* Foreman is a tool written in Ruby with a standalone tarball that
only requires the interpreter itself. Unfortunately I found a bug
in the standalone package, so I had to patch it. The modified
source is included in the vendor/foreman directory. Vendoring the
full project feels a bit excessive, but as long as one must use a
Procfile to use Heroku, one may as well write two Procfiles, rather
than a Procfile and a shell script.

The bug is reported, and when foreman is re-freshed to a new version
no patches will likely be necessary.

TODO
----

The current and (currently) very unexciting demonstration of this can
be seen at http://double-boiler.heroku.com. It just shows a hello
world Django page; it is indiscernible from a normal Django "hello
world".

I'd like to have a more compelling demo than hello world (say,
generating jobs rapidly via many, many ajax calls and then serving
them) to show gevent, Gunicorn, and Celery in action. A mini
benchmark would be nice. I would like contributions in this area,
because I'm not really a great nor enthusiastic web developer.

0 comments on commit b8177e8

Please sign in to comment.