Date | Commit message (Collapse) |
|
|
|
The real reason for Unicorn is to popularize GNU Make as a
parallel programming platform :)
|
|
|
|
|
|
Loading Rails takes a very long time, so consolidate most of the
tests into one big test that allows us to avoid loading Rails.
It makes the test less like unit tests, but they could still
be split up into private functions if one wants to run them
individually.
|
|
Additional tests for Rails have been added
* cookies and sessions
* POST requests
* POST requests with multipart uploads
* 404 handling
* static file serving
* cached static file serving
(resources with ";" caching in some old 1.2.x version
not yet tested)
|
|
The default status was 404 in Mongrel and this is needed to work
with older versions of Rails. Additionally parse the "Status:"
header if it ever got set and the actual "status" code passed
to CGI::headers was not set.
|
|
Otherwise it's hard to tell which version of Rails
test failed when we ran tests in parallel.
|
|
The @output_cookies instance variable was being
ignored, and some versions of Rails uses that.
Additionally, cleanup multi-value headers in
general to avoid dropping headers.
|
|
|
|
Very preliminary for now. Basically just sets up a basic
controller and response. Requires git to clone the official
Rails repository.
|
|
Just use the RAILS_RELATIVE_URL_ROOT variable to support it
since probably works on more versions of Rails. Since no
application I've ever deployed has ever used it, I'm not going
to bother supporting it for Rails <2.3, either.
|
|
Instead of trusting sysread/syswrite to throw EAGAIN if the pipe
is full (highly unlikely); just use non-blocking methods which
are indeed non-blocking and don't care for the #blocking= method
added to it.
|
|
This removes half-implemented support to disable static file
serving. People interested enough can provide their own
config.ru file to save some stat(2) syscalls, but extra
command-config options just complicate things.
|
|
|
|
* Expand addresses like "1:8080" to "127.0.0.1:8080"
beforehand so sock_name() in SocketHelper will
always return consistent results.
* Add support for "unix:/path/to/foo" paths for easier
synchronization with nginx config files.
|
|
Rack does not like it; instead try to set it as
the @status code if possible.
|
|
This makes it easy to run unit or exec tests
independently of the other.
Removed the unused slow-tests targets.
|
|
Makes problems easier to solve if we dump the
exception...
|
|
REQUEST_METHOD got removed from Unicorn::Const
and this module is the only place that currently
uses it.
|
|
This allows config.ru to specify listener and
stuff before we setup the application.
|
|
|
|
Combining command-line and config file options in a reasonable
manner has and always will be a painful experience.
|
|
They were non-conformant for the longest time
|
|
We need to ensure the QUIT signal to the old processes
are processed when fixing the config.
Additionally, the log rotation checker was not reliable
because the master log emitted a similar message to
the workers and we were not distinguishing between
them. Check for all 5 logs (1 master + 4 workers)
to be rotated.
|
|
It makes test_exec more reliable and probably helps
other scripts people may run around this.
|
|
"HTTP_BODY" could conflict with a "Body:" HTTP header if there
ever is one. Also, try to hide this body from the Rack
environment before @app is called since it is only used by
Unicorn internally.
|
|
We still need to support "listeners" for easy use of
command-line options, but folks using the config file should use
"listen" as it is more flexible.
|
|
Instead of having global options for all listeners,
make all socket options per-listener. This allows
reverse-proxies to pick different listeners to get
different options on different sockets.
Given a cluster of machines (10.0.0.1, 10.0.0.2, 10.0.0.3)
running Unicorn with the following config:
------------------ 8< ----------------
listen "/tmp/local.sock", :backlog => 1
listen "*:8080" # use the backlog=1024 default
------------------ 8< ----------------
It is possible to configure a reverse proxy to try to use
"/tmp/local.sock" first and then fall back to using the
TCP listener on port 8080 in a failover configuration.
Thus the nginx upstream configuration on 10.0.0.1 to
compliment this would be:
------------------ 8< ----------------
upstream unicorn_cluster {
# reject connections ASAP if we are overloaded
server unix:/tmp/local.sock;
# fall back to other machines in the cluster via "backup"
# listeners which have a large backlog queue.
server 10.0.0.2:8080 backup;
server 10.0.0.3:8080 backup;
}
------------------ 8< ----------------
This removes the global "backlog" config option which
was inflexible with multiple machines in a cluster
and exposes the ability to change SO_SNDBUF/SO_RCVBUF
via setsockopt(2) for the first time.
|
|
|
|
This is in the Rack specification and a good idea. Remind
ourselves to prevent file descriptor or other resource leaks in
case the body is not an Array.
|
|
We always close the socket immediately after a
successful write for two reasons:
1) To prevent error responses from being rewritten.
If we throw an exception in our request/app/response
chain, we'll attempt to write an HTTP 400/500 response
out if the socket is open. No way to write to
an open socket.
2) To uncork the socket if TCP_CORK is enabled (Linux)
ASAP. This should be a tick faster than waiting
to go back up the stack and close it there.
|
|
This reworks error handling throughout the entire stack to be
more Ruby-ish. Exceptions are raised instead of forcing the
us to check return values.
If a client is sending us a bad request, we send a 400.
If unicorn or app breaks in an unexpected way, we'll
send a 500.
Both of these last-resort error responses are sent using
IO#write_nonblock to avoid tying Unicorn up longer than
necessary and all exceptions raised are ignored.
Sending a valid HTTP response back should reduce the chance of
us from being marked as down or broken by a load balancer.
Previously, some load balancers would mark us as down if we close
a socket without sending back a valid response; so make a best
effort to send one. If for some reason we cannot write a valid
response, we're still susceptible to being marked as down.
A successful HttpResponse.write() call will now close the socket
immediately (instead of doing it higher up the stack). This
ensures the errors will never get written to the socket on a
successful response.
|
|
|
|
|
|
Unicorn always uses lower-level sys{read,write} methods
when doing I/O so setting "client.sync=true" is just
a wasted operation.
|
|
They're easier for me to type and read and just barely faster
when doing comparisons on.
|
|
Instead of rotating logs immediately when SIGUSR1 is caught,
defer it until the current client is processing is complete.
This allows multi-line log messages generated by apps to not be
broken up if SIGUSR1 is received while the app is running.
If we're sleeping inside IO.select, we close a pipe in the
exceptfds set to cause EBADF to be raised.
This also adds a small reliability improvement to test_exec
so we wait until signals are ready before sending USR1
to rotate logs.
|
|
In case there are permissions problems that cause
log rotation to fail, we trap the error and defer
death until the current request finishes running.
|
|
* commit 'v0.2.3':
unicorn 0.2.3
Ensure Tempfiles are unlinked after every request
Don't bother unlinking UNIX sockets
Conflicts:
lib/unicorn/socket.rb
|
|
|
|
Otherwise we bloat TMPDIR and run the host out of space, oops!
|
|
Since we always unlink existing sockets when binding, there's no
point in having code to unlink the sockets when we exit.
Additionally, the old code path was racy.
|
|
bind_listen takes a hash as its second parameter now, allowing
the addition of :sndbuf and :rcvbuf options to specify the size
of the buffers in bytes. These correspond to the SO_SNDBUF and
SO_RCVBUF options via setsockopt(2) respectively.
This also adds support for per-listener backlogs to be used.
However, this is only an internal API change and the changes
have not yet been exposed to the user via Unicorn::Configurator,
yet.
Also add a bunch of SocketHelper tests
|
|
This cuts the HttpParser interface down to #execute and #reset
method. HttpParser#execute will return true if it completes and
false if it is not. http->nread state is kept internally so we
don't have to keep track of it in Ruby; removing one parameter
from #execute.
HttpParser#reset is unchanged.
All errors are handled through exceptions anyways, so the
HttpParser#error? method stopped being useful.
Also added some more unit tests to the HttpParser since I know
some folks are (rightfully) uncomfortable with changing stable C
code. We now have tests for incremental parsing.
In summary, we have:
* more test cases
* less C code
* simpler interfaces
* small performance improvement
=> win \o/
|
|
Most HTTP requests are GET requests and the majority of those
GET requests are complete after one sysread. This is especially
true since we're optimized for fast clients. So short the extra
checks and trust our HTTP parser implementation to do the right
thing (we have decent unit tests for it).
|
|
This resurrects old code from Mongrel to wrap the Rails
Dispatcher for older versions of Rails. It seems that
Rails >= 2.2.0 support Rack, but only >=2.3 requires it.
I'd like to support Rails 1.2.x for a while, too.
|
|
Since we always unlink existing sockets when binding, there's no
point in having code to unlink the sockets when we exit.
Additionally, the old code path was racy.
|
|
Ensure constants are used as hash keys and cleanup unused
constants. This gives a 10-15% improvement with
test/benchmark/request.rb
|
|
The extra split slows things down a little as as it generates an
array with a new string value and adds an extra loop to iterate
through.
|