You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Wolfgang Hoschek <wo...@cern.ch> on 2001/09/29 01:56:08 UTC

Re: Filters and Transfer-Encoding: chunked

> > I am facing a problem when useing a filter.  The problem is that the
>"Transfer-Encoding" header does not appear to be getting set.  In this case
>the filter is doing some simple xsl transformations and passing on the
>results to the response's output stream.  Unfortunatly because the content
>is not being chunked by Tomcat the socket just sits there open.
> >
> > I'm not sure how tomcat knows to chunk the data.  When working with an
>unfiltered jsp page the data gets chunked as expected.  Does the filter need
>to do anything to "chunk" the data?
>
>No, I don't think so.  I was able to use filter to set different headers
>including "Content-Encoding" to write out to the response's outputstream
>just fine.  Hope this help.

Somwhat related problem here (TC4 stand-alone).
I would like to use response chunked encoding with http.HttpConnector but 
so far fail to do so.
Let me try and explain: The servlet in use does not set the response 
content-length. This apparently switches off chunked encoding. Browsing 
through the TC4 source it seems that a servlet can effectively switch off 
chunked encoding with a single outputStream.flush() early on, say flushing 
a couple of bytes (even though the servlet buffer size may be very large), 
which might be the cause of my problems.

ResponseStream.flush() reads

         /**
          * Flush any buffered data for this output stream, which also 
causes the
          * response to be committed.
          */
         public void flush() throws IOException {

                 if (closed)
                         throw new 
IOException(sm.getString("responseStream.flush.closed"));

                 if (commit)
                         response.getResponse().flushBuffer();

         }

Q1: Is this behaviour defined somewhere in the spec? Open to 
interpretation? Intuitively I'd think only response.flushBuffer() should 
really flush to the socket and ResponseStream.flush() above should copy 
into the buffer as long as it does not overflow. (response.flushBuffer() is 
automatically called finally anyway).

Now I can't fix the closed source third party servlet (big XSLT stuff). As 
a work-around I've been trying to write a filter, but so far no luck.

Q2: Probably needs a custom Outputstream to go with the filter!? Any 
suggestions on how to do the buffer handling properly in such a custom stream?

The other option would perhaps be to turn off the commit flag above. The 
source seems to toggle the flag on/off repeatadly for PrintWriters (huh?), 
and always keeps it on for straight OutputStreams.

Q3: Why does it do this and where would be the right place to switch the 
commit flag off permanently.

Thanks,
Wolfgang.


Re: Filters and Transfer-Encoding: chunked

Posted by Remy Maucherat <rm...@home.com>.
> > > I am facing a problem when useing a filter.  The problem is that the
> >"Transfer-Encoding" header does not appear to be getting set.  In this
case
> >the filter is doing some simple xsl transformations and passing on the
> >results to the response's output stream.  Unfortunatly because the
content
> >is not being chunked by Tomcat the socket just sits there open.
> > >
> > > I'm not sure how tomcat knows to chunk the data.  When working with an
> >unfiltered jsp page the data gets chunked as expected.  Does the filter
need
> >to do anything to "chunk" the data?
> >
> >No, I don't think so.  I was able to use filter to set different headers
> >including "Content-Encoding" to write out to the response's outputstream
> >just fine.  Hope this help.
>
> Somwhat related problem here (TC4 stand-alone).
> I would like to use response chunked encoding with http.HttpConnector but
> so far fail to do so.
> Let me try and explain: The servlet in use does not set the response
> content-length. This apparently switches off chunked encoding. Browsing
> through the TC4 source it seems that a servlet can effectively switch off
> chunked encoding with a single outputStream.flush() early on, say flushing
> a couple of bytes (even though the servlet buffer size may be very large),
> which might be the cause of my problems.
>
> ResponseStream.flush() reads
>
>          /**
>           * Flush any buffered data for this output stream, which also
> causes the
>           * response to be committed.
>           */
>          public void flush() throws IOException {
>
>                  if (closed)
>                          throw new
> IOException(sm.getString("responseStream.flush.closed"));
>
>                  if (commit)
>                          response.getResponse().flushBuffer();
>
>          }
>
> Q1: Is this behaviour defined somewhere in the spec? Open to
> interpretation? Intuitively I'd think only response.flushBuffer() should
> really flush to the socket and ResponseStream.flush() above should copy
> into the buffer as long as it does not overflow. (response.flushBuffer()
is
> automatically called finally anyway).
>
> Now I can't fix the closed source third party servlet (big XSLT stuff). As
> a work-around I've been trying to write a filter, but so far no luck.
>
> Q2: Probably needs a custom Outputstream to go with the filter!? Any
> suggestions on how to do the buffer handling properly in such a custom
stream?
>
> The other option would perhaps be to turn off the commit flag above. The
> source seems to toggle the flag on/off repeatadly for PrintWriters (huh?),
> and always keeps it on for straight OutputStreams.
>
> Q3: Why does it do this and where would be the right place to switch the
> commit flag off permanently.

I don't understand what your servlet is doing. According to your description
(at least as I understand it), it does the same as the HelloWorld servlet
from the examples, which will produce chunked output.

Also, the current standalone HTTP connector won't really prevent you from
breaking the protocol from a servlet (by setting some special headers).

Remy


Re: Filters and Transfer-Encoding: chunked

Posted by Wolfgang Hoschek <wo...@cern.ch>.
>I don't understand what your servlet is doing. According to your description
>(at least as I understand it), it does the same as the HelloWorld servlet
>from the examples, which will produce chunked output.
>
>Also, the current standalone HTTP connector won't really prevent you from
>breaking the protocol from a servlet (by setting some special headers).
>
>Remy

Yes, since the servlet in question is closed source I can only guess what 
it is doing.

Current status is that if I switch off chunking in the connector via 
allowChunking="false", and have a preprocess filter that just sets a large 
setBufferSize() I get very good performance with Java and C Clients.

Here are all 4 combinations (TC4 standalone):

(1) With allowChunking="false" AND buffersize > response  --> 25 MB/s (C 
and Java)
(2) With allowChunking="false" AND buffersize < response  --> 2 MB/s (C and 
Java)
(3) With allowChunking="true"  AND buffersize < response  --> 2 MB/s (C) 
and 0.3 MB/s (Java)
(4) With allowChunking="true"  AND buffersize > response  --> 25 MB/s (C) 
and 0.3 MB/s (Java)

Where a response is 10 MB large. The Java client lib is 'HTTPClient', the C 
client is 'wget'.
Discussion:

(1) is fine, probably because TC seems to automatically set the ContentLength.
(2) is not fine, but probably there is nothing that can't be done about it.
(3) is not fine, and I'm wondering why. 'HTTPClient' has a performance 
problem with chunked reads. But also the wget behaves poorly.
(4) Now wget is doing fine and HTTPClient does not improve at all.

The preliminary conclusion is that chunking doesn't work well and that only 
(1) gives decent performance for C and Java, at least for this given 
servlet. But clearly huge buffer sizes are not desirable if there are many 
concurrent clients.

I tried having allowChunking="true" and patching flushBuffer() and/or 
finishResponse() in ReponseBase, HTTPResponseBase and HTTPResponseImpl and 
ended up with some improvement for the given request, although most likely 
not correct in the general case.

I'll see whether I can come up with someting more useful.

BTW, Sorry for not being subscribed. I read this list a lot, but only post 
occasionally, so http://marc.theaimsgroup.com/?l=tomcat-dev is a good way 
for keeping up to date without drowning in local mail.

Wolfgang.