about summary refs log tree commit homepage
DateCommit message (Collapse)
2015-06-11yahns 1.8.0 - minor updates v1.8.0
Most notably, the Rack response body is now closed during rack.hijack. Middlewares such as Rack::Lock (used by Rails) break badly unless the response body is closed on hijack, so we will close it to follow the lead of other popular Rack servers. While it's unclear if there's anybody using rack.hijack besides yahns/proxy_pass we'll try to emulate the behavior of other servers as much as possible. ref: https://github.com/ngauthier/tubesock/issues/10 We'll also support SIGWINCH if not daemonized This has no effect for the (default) single process case with no master/worker relationship as that does not support SIGWINCH. Some process managers such as foreman and daemontools rely on yahnsnot daemonizing, but we still want to be able to process SIGWINCH in that case. stdout and stderr may be redirected to a pipe (for cronolog or similar process), so those are less likely to be attached to a TTY than stdin. This also allows users to process SIGWINCH when running inside a regular terminal if they redirect stdin to /dev/null. This follows unicorn commit a6077391bb62d0b13016084b0eea36b987afe8f0 Thanks to Dan Moore for suggesting it on the unicorn list. A few more minor changes, more memory reduction changes coming... * proxy_pass: no point in closing StringIO * proxy_pass: allow filtering or overriding response headers * support SIGWINCH even if not daemonized * use Unicorn::HttpParser#response_start_sent accessor * reduce inline constant cache overheads * proxy_pass: skip tests if kcar is missing * ensure body is closed during hijack
2015-06-10ensure body is closed during hijack
Middlewares such as Rack::Lock (used by Rails) break badly unless the response body is closed on hijack, so we will close it to follow the lead of other popular Rack servers. While it's unclear if there's anybody using rack.hijack besides yahns/proxy_pass we'll try to emulate the behavior of other servers as much as possible. ref: https://github.com/ngauthier/tubesock/issues/10 While we're at it, use DieIfUsed correctly in test_ssl.rb :x
2015-06-10proxy_pass: skip tests if kcar is missing
We don't require kcar to be installed since most users will never use the proxy_pass feature, but show an informative error in case they want to test this functionality.
2015-06-05reduce inline constant cache overheads
We can use symbols in the SleepyPenguin APIs to trade speed for space in uncommon code paths.
2015-06-05use Unicorn::HttpParser#response_start_sent accessor
We don't need to waste a valuable ivar slot on each socket when we know unicorn already maintains this flag for us.
2015-06-05support SIGWINCH even if not daemonized
This has no effect for the (default) single process case with no master/worker relationship as that does not support SIGWINCH. Some process managers such as foreman and daemontools rely on yahnsnot daemonizing, but we still want to be able to process SIGWINCH in that case. stdout and stderr may be redirected to a pipe (for cronolog or similar process), so those are less likely to be attached to a TTY than stdin. This also allows users to process SIGWINCH when running inside a regular terminal if they redirect stdin to /dev/null. This follows unicorn commit a6077391bb62d0b13016084b0eea36b987afe8f0 Thanks to Dan Moore for suggesting it on the unicorn list.
2015-05-18proxy_pass: allow filtering or overriding response headers
We shouldn't blindly pass the "Server" tag through, since we may be proxying Apache instances and we don't want to misadvertise, either. IMHO, it is best to say nothing at all to save bandwidth and reduce the potential for attackers in case a vulnerability is discovered in yahns.
2015-05-12proxy_pass: no point in closing StringIO
It does not release memory immediately and GC can handle it reliably, so don't waste a constant lookup + cache entry on it. While we're at it, explain why we can't do a simpler respond_to? check instead.
2015-05-11yahns 1.7.0 - rack.hijack improvements and more v1.7.0
Nothing really significant, so there's no need to upgrade if you're not affected by the minor fixes and changes in this release. For all users, LoadError and SyntaxError exceptions are now logged and non-fatal within worker threads serving application code. Thanks to Lin Jen-Shin <godfat@godfat.org> for bringing this up on the mailing list. Additionally, temporary files buffered to the filesystem will now support the Rack::TempfileReaper middleware in rack 1.6+ For rack.hijack users, there are some changes and improvements. rack.hijack should return a usable IO-like object for SSL users, now. The rack.input object is no longer closed on hijacking, allowing apps to continue using buffered input after hijacking. There is also a bugfix for the rare apps which hijack requests after emitting 100-continue responses. Note: there is also a work-in-progress and under-documented asynchronous Yayns::ProxyPass Rack app which uses rack.hijack internally. This will allow yahns to act as a fully-buffering reverse proxy to upstream servers which cannot handle slow clients. Yahns::ProxyPass NOT production-ready as of this release. The old, synchronous extras/proxy_pass.rb code remains usable. There's also the usual round of minor code bloat reduction.
2015-05-11extras/proxy_pass: remove compatibility note
We'll have to support both, it seems.
2015-05-11worker threads log LoadError and SyntaxError, too
Some applications may lazily load code during app dispatch, triggering LoadError or SyntaxError exceptions. Log the error and backtrace so application maintainers can more easily notice and diagnose problems. Keep in mind users are likely to have performance and race condition problems with lazy loading, and the process may still be in a bad state due to partially-loaded code. This commit is only intended to give application authors a chance to notice and fix or avoid problems in the future. Note: logging fatal exceptions by default in all threads was proposed in ruby-core, but currently not implemented in any released version: https://bugs.ruby-lang.org/issues/6647 Reported-by: Lin Jen-Shin (godfat) <godfat@godfat.org> <CAA2_N1umJO12XH9r+JHnA6r=z=Mwp_PqOrdnW65oqW2K2-iAoQ@mail.gmail.com>
2015-05-09support for Rack::TempfileReaper middleware
Rack::TempfileReaper was added in rack 1.6 to cleanup temporary files. Make Yahns::TmpIO ducktype-compatible and put it into env['rack.tempfiles'] array so Rack::TempfileReaper may be used to free up space used by temporary buffer files. ref: commit 3bdf5481e49d76b4502c51e5bdd93f68bfd1f0b4 in unicorn
2015-05-09proxy_pass: favor literal hash over arrays for error responses
Arrays are less verbose, but they have more bytecode overhead which actually matters at runtime.
2015-05-09ssl: ensure rack.hijack users get "normal" IO methods
We do not want rack.hijack users relying on kgio_* methods since kgio is trying to make itself obsolete (as Ruby itself adopts kgio features). This is a bit wonky since our common case tries to minimize object allocation by only using the Kgio::Socket derived class.
2015-05-09openssl_client: remove shutdown call
OpenSSL::SSL::SSLSocket does not actually respond to a shutdown method, and it would not be safe to call anyways. Merely shutdown at the OS level and let any handling thread clean it up.
2015-05-08avoid excess allocations for rack.hijack support
Proc object allocation is not cheap, so avoid doing it and allow Yahns::HttpClient to be assigned as the env["rack.hijack"] callback for Rack applications.
2015-05-08proxy_pass: avoid unnecessary close method
No point in wasting space and reducing code clarity with this method to remove references to live objects.
2015-05-08proxy_pass: fix race condition due to ensure
When calling proxy_busy_mod_blocked to re-enable a descriptor via epoll, the ensure block is dangerous because the "ensure" clause modifies the object after the ReqRes is injected into epoll. This is extremely dangerous as we give up exclusive access to the object once we call epoll_ctl. This simplifies the code a bit while we're at it.
2015-05-08proxy: ensure GC sees the client socket upon reactivation
Reactivating a client socket after the proxied response is complete requires the object remain visible to the Ruby GC while no thread is accessing it. So we must place the object back into the fdmap to prevent the GC from eating it (and having epoll return an invalid pointer).
2015-04-24proxy_pass: clear backtrace on ECONNREFUSED
Bad connections or dead upstreams cannot be solved looking at a backtrace, so avoid polluting logs with them and making other problems less visible.
2015-04-22favor #nil? instead of "== nil" comparisons in cold code
We don't need optimized dispatch methods in cold code, so use the more space-efficient "nil?" method dispatch to save us one word per-call site for a rough total of 24 bytes saving.
2015-04-22config: avoid unnecessary binmode call
We may set binary mode upon open by passing "b" in the mode string, so avoid the extra method dispatch and bytecode/cache overhead that entails.
2015-04-21proxy_pass: fix race condition due to flawed hijack check
The entire idea of a one-shot-based design is all the mutual exclusion is handled by the event dispatch mechanism (epoll or kqueue) without burdening the user with extra locking. However, the way the hijack works means we check the Rack env for the 'rack.hijack_io' key which is shared across requests and may be cleared. Ideally, this would not be a problem if the Rack dispatch allowed returning a special value (e.g. ":ignore") instead of the normal status-headers-body array, much like what the non-standard "async.callback" API Thin started. We could also avoid this problem by disallowing our "unhijack-ing" of the socket but at a significant cost of crippling code reusability, including that of existing middleware. Thus, we allocate a new, empty request object here to avoid a TOCTTOU in the following timeline: original thread: | another thread HttpClient#yahns_step | r = k.app.call(env = @hs.env) # socket hijacked into epoll queue <thread is scheduled away> | epoll_wait readiness | ReqRes#yahns_step | proxy dispatch ... | proxy_busy_mod_done ************************** DANGER BELOW ******************************** | HttpClient#yahns_step | # clears env # sees empty env: | return :ignore if env.include?('rack.hijack_io') | In other words, we cannot ever touch the original env seen by the original thread since it must see the 'rack.hijack_io' value because both are operating in the same Yahns::HttpClient object. This will happen regardless of GVL existence. Avoiding errors like this is absolutely critical to every one-shot based design.
2015-04-11proxy_pass: attempt to forward premature upstream responses
Upstreams may shut us down while we're writing a request body, attempt to forward any responses from the upstream back to the client which may explain the rejection reason for giant uploads.
2015-04-09proxy_pass: capture local variable earlier for rescue
This giant method needs to spew an error response in case uploads to the upstream fail, ensure the local variable is defined early.
2015-04-08proxy_pass: support backends which rely on EOF to terminate
Not all backends are capable of generating chunked responses (especially not to HTTP/1.0 clients) nor can they generate the Content-Length (especially when gzipping), so they'll close the socket to signal EOF instead.
2015-04-07extras/proxy_pass: reinstate synchronous version
Since yahns/proxy_pass is not a drop-in replacement, reinstate the old, synchronous version to avoid breaking existing setups which require Rack middleware support.
2015-04-07wbuf: fix writev calls for vectors
kgio_writev returns nil on success instead of the number of bytes written, so we must manually calculate the number of bytes written intead :x This is triggerable when sending giant chunked responses.
2015-04-07proxy_pass: avoid needless regexp
A dumb string comparison will do here, so there's no point in paying the memory and CPU cost of a regexp match when we already extracted the suffix from a header key.
2015-04-07proxy_pass: possibly avoid breaking some middlewares
hijack seems incompatible with many middlewares, so return a wonky response tuplet just in case...
2015-04-07http_context: avoid defining our own *buffer_tmpdir methods
Instance variable attr methods are cheaper and we can shove the complexity down to tmpio by allowing it to accept a nil argument for the temporary directory. This adds 4 bytes to tmpio but removes over 1K in http_context on a 32-bit system.
2015-04-07use String#include? for cold, simple substring matches
Literal regexps costs over 400 bytes of memory on x86-64 per-site, so there's no point in using them to cause bloat at cold call sites where runtime performance does not matter.
2015-04-07test/test_proxy_pass: remove buffer size tuning
On one of my ancient, cache-starved home systems, this tends to cause pathologically bad performance during some of these tests.
2015-04-07proxy_pass: send 1.0 requests to upstreams for 1.0 clients
We cannot pass trailers from upstreams to HTTP/1.0 clients without fully-buffering the response body AND trailers before forwarding the response header. Of course, one of the reasons yahns exists is to support lazy buffering, so fully-buffering up front is wasteful and hurts latency. So instead, degrade to 1.0 requests to upstreams for HTTP/1.0 clients, this should prevent upstreams from sending trailers in the first place. HTTP/1.0 clients on Rails apps may suffer, but there probably are not too many HTTP/1.0 clients out there.
2015-04-07proxy_pass: preliminary support for passing trailers
Rack apps may (through a round-about way) send HTTP trailers to HTTP/1.1 clients, and we need a way to forward those responses through without losing the trailers.
2015-04-04proxy_pass: more tests for giant headers and truncations
We need to ensure more uncommon cases such as gigantic upstream headers and truncated upstream responses are handled properly and predictably.
2015-04-03proxy_pass: expand pipelining tests for after-upload behavior
Pipelining uploads is rare in practice, but they must behave properly in case some brave soul wants to start doing it.
2015-04-03proxy_pass: test for truncated response behavior
Even if a response is screwed, we need to ensure breakage is predictable.
2015-04-03proxy_pass: test and fix larger uploads
We were incorrectly stashing the return value of detach_rbuf! into the inter-thread buffer buffer which is bound to the client.
2015-04-03proxy_pass: rewrite to be async, using rack.hijack
This allows our reverse proxy to avoid having an innefficient 1:1 relationship between threads and upstream connections, reducing memory usage when there are many upstream connections (possibly to multiple backend machines).
2015-04-03allow vector args to wbuf_write
This allows us to write chunked response bodies without extra copying to clients which support streaming.
2015-04-03http_client: preserve HTTP state after hijack
We'll be supporting "un-hijacking" a client socket for proxy_pass and we must preserve state for pipelined requests.
2015-04-03wbuf: store busy signal inside this object
This should make it easier to track state for asynchronous proxy_pass buffering.
2015-04-01tmpio: add writev support via kgio
This will allow us to write arrays for chunked output without unnecessary data copies.
2015-04-01test/test_proxy_pass: rename test name, too
This is no longer a part of the "extras" section
2015-04-01doc: note possible removal of client_body_buffer_size
This is probably the least useful tuning knob and may be removed in the future; so at least warn users about it. ref: <CAA2_N1t_UJZO9Vu9vx3NxysCx+okip8_pM+NpwhHrExM+f1e+Q@mail.gmail.com>
2015-03-17avoid EPOLL_CTL_DEL calls on rack.hijack
We will support "un-hijacking", so the repeated ep_insert/ep_remove sequences in the kernel will get expensive and complicated for our user-land code, too.
2015-03-14proxy_pass: officially become a part of yahns
This will rely on rack.hijack in the future to support asynchronous execution without tying up a thread when waiting for upstreams. For now, this allows simpler code with fewer checks and the use of monotonic time on newer versions of Ruby.
2015-03-14extras/proxy_pass: support Unix domain sockets as backends
Of course, some users will prefer to bind HTTP application servers to Unix domain sockets for better isolation and (maybe) better performance.
2015-03-14extras/proxy_pass: implicit $fullpath expansion for upstreams
This is slightly more nginx-style behavior and allows simpler configuration.