<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html><body style='font-size: 10pt; font-family: Verdana,Geneva,sans-serif'>
<p>You could do it similar proxy module is buffering the response, for instance see <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering">proxy_buffering</a> directive:</p>
<p style="padding-left: 30px;"><em>When buffering is enabled, nginx receives a response from the proxied server as soon as possible, saving it into the buffers set by the <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size">proxy_buffer_size</a> and <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers">proxy_buffers</a> directives. If the whole response does not fit into memory, a part of it can be saved to a <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_temp_path">temporary file</a> on the disk. Writing to temporary files is controlled by the <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_max_temp_file_size">proxy_max_temp_file_size</a> and <a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_temp_file_write_size">proxy_temp_file_write_size</a> directives.</em></p>
<p>This or other communicating modules (like fcgi, scgi or uwsgi) using upstream buffering of response. The handling around buffering of upstream is almost the same in all modules.<br />This is already event-driven - handler is called on readable, by incoming response chunk (or on writable of downstream).</p>
<p>Basically depending on how your module architecture is built, you could:</p>
<ul>
<li>either use default upstream buffering mechanism (if you have something like upstream or can simulate that). In thin case you have to set certain properties of r->upstream: buffering, buffer_size, bufs.num and bufs.size, temp_file_write_size and max_temp_file_size and of course register the handler reading the upstream pipe.</li>
<li>or organize your own response buffering as it is implemented in ngx_event_pipe.c and ngx_http_upstream.c, take a look there for implementation details.</li>
</ul>
<p>As for performance (disk I/O, etc) - it depends (buffer size, system cache, mount type of temp storage, speed of clients downstream, etc). But if you would configure the buffers large enough, nginx could use it as long as possible and the storing in temp file can be considered as safe on demand fallback to smooth out the peak of load, to avoid OOM situation.<br />Usage a kernel pipe buffers could be surely faster, but indirect you'd just relocate the potential OOM issue from nginx process to the system.</p>
<p>Regards,<br />Sergey</p>
<p>10.11.2020 02:54, Jeff Heisz wrote:</p>
<blockquote type="cite" style="padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px"><!-- html ignored --><!-- head ignored --><!-- meta ignored -->
<pre>Hi all, I've asked this before with no response, trying one last time
before I just make something work.

I'm making a custom module for nginx that does a number of things but
one of the actions is a long-running (in the nginx sense) task that
could produce a large response.  I've already got proper processing
around using worker tasks for the other long-running operations that
have small datasets, but worry about accumulating a large amount of
memory in a buffer chain for the response.  Ideally it would drain as
fast as the client can consume it and throttle appropriately, there
could conceivably be gigabytes of content.

My choices (besides blowing all of the memory in the system) are:

- write to a temporary file and attach a file buffer as the response,
less than ideal as it's essentially translating a file to begin with,
so it's a lot of disk I/O and performance will be less than stellar.
>From what I can tell, this is one of the models for the various CGI
systems for caching, although in my case caching is not of use

- somehow hook into the eventing system of nginx to detect the write
transitions and implement flow control directly using threading
conditionals.  I've tried this for a few weeks but can't figure out
the 'right' thing to make the hooks work in a separate module without
changing the core nginx code, which I'm loathe to do (unless you are
looking for someone to contribute such a solution, but I'd probably
need some initial guidance)

- attach a kernel pipe object (yah yah, won't work on Windows, don't
care) to each of my worker instances and somehow 'connect' that as an
upstream-like resource, so that the nginx event loop handles the
read/write consumption and the thread automatically blocks when full
on the kernel pipe.  Would need some jiggery to handle reuse and
start/end markers.  Also not clear if I can override the connection
model for the upstream without again changing core nginx server code

Any thoughts?  Not looking for code here (although telling me to look
at the blah-blah-blah that does exactly this would be awesome), but if
someone who is more familiar with the inner workings of the nginx data
flow could just say which solution is a non-starter (so I don't waste
time trying to make it work) or even which would be a suitable
solution would be awesome!

jmh
_______________________________________________
nginx-devel mailing list
<a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a>
</pre>
</blockquote>
</body></html>