AJP/Java connector issues

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

AJP/Java connector issues

mturk
Hi,

Just noticed a strange behavior in the Java part of the
JK dealing with large (over 8184 bytes) data transfers.

Since with 8192 bytes AJP packet size, the maximum
transferred size per each packet is 8184 bytes one
would expect that for 20000 bytes file the packets
would be in a form of:
1:8184,2:8184,3:3632 thus total of 20000 bytes.

But in fact the behavior is rely weird:
1:8184,2:8,3:8184,4:8,5:3616.

Instead only three, the five! packets are transferred.

Seems that algorithm is breaking 8192 bytes of data to
two packets (8184 and 8 bytes).

Bill,
Any idea how to solve this, because it's way too
inefficient.
What's makes the things even worse is that for each
packet Apache2 creates a transient bucket thus
rising the memory usage.


Regards,
Mladen.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

Bill Barker-2

----- Original Message -----
From: "Mladen Turk" <[hidden email]>
To: "Tomcat Developers List" <[hidden email]>
Cc: "Bill Barker" <[hidden email]>
Sent: Wednesday, May 18, 2005 11:44 PM
Subject: AJP/Java connector issues


> Hi,
>
> Just noticed a strange behavior in the Java part of the
> JK dealing with large (over 8184 bytes) data transfers.
>
> Since with 8192 bytes AJP packet size, the maximum
> transferred size per each packet is 8184 bytes one
> would expect that for 20000 bytes file the packets
> would be in a form of:
> 1:8184,2:8184,3:3632 thus total of 20000 bytes.
>
> But in fact the behavior is rely weird:
> 1:8184,2:8,3:8184,4:8,5:3616.
>
> Instead only three, the five! packets are transferred.
>
> Seems that algorithm is breaking 8192 bytes of data to
> two packets (8184 and 8 bytes).
>
> Bill,
> Any idea how to solve this, because it's way too
> inefficient.
> What's makes the things even worse is that for each
> packet Apache2 creates a transient bucket thus
> rising the memory usage.
>
It's probably Nagle (which is off by default).  Try tcpNoDelay="false".

>
> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
>

This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.

In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

Bill Barker-2
In reply to this post by mturk

----- Original Message -----
From: "Mladen Turk" <[hidden email]>
To: "Tomcat Developers List" <[hidden email]>
Cc: "Bill Barker" <[hidden email]>
Sent: Wednesday, May 18, 2005 11:44 PM
Subject: AJP/Java connector issues


> Hi,
>
> Just noticed a strange behavior in the Java part of the
> JK dealing with large (over 8184 bytes) data transfers.
>
> Since with 8192 bytes AJP packet size, the maximum
> transferred size per each packet is 8184 bytes one
> would expect that for 20000 bytes file the packets
> would be in a form of:
> 1:8184,2:8184,3:3632 thus total of 20000 bytes.
>
> But in fact the behavior is rely weird:
> 1:8184,2:8,3:8184,4:8,5:3616.
>
> Instead only three, the five! packets are transferred.
>
> Seems that algorithm is breaking 8192 bytes of data to
> two packets (8184 and 8 bytes).
>
> Bill,
> Any idea how to solve this, because it's way too
> inefficient.
> What's makes the things even worse is that for each
> packet Apache2 creates a transient bucket thus
> rising the memory usage.
>
I see what this is now:  The default Connector OutputBuffer size is 8K, so
it's sending the output to JkInputStream in 8K chunks.  JkInputStream sends
all of the 8K to Apache in two chunks.

As a Coyote OutputBuffer, it's not really JkInputStream's job to do
additional buffering.  It's probably better to do
response.setBufferSize(20000); so that the Connector will send the whole
thing to JkInputStream as one chunk.

>
> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
>


This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.

In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

jean-frederic clere
In reply to this post by mturk
Mladen Turk wrote:

> Hi,
>
> Just noticed a strange behavior in the Java part of the
> JK dealing with large (over 8184 bytes) data transfers.
>
> Since with 8192 bytes AJP packet size, the maximum
> transferred size per each packet is 8184 bytes one
> would expect that for 20000 bytes file the packets
> would be in a form of:
> 1:8184,2:8184,3:3632 thus total of 20000 bytes.
>
> But in fact the behavior is rely weird:
> 1:8184,2:8,3:8184,4:8,5:3616.
>
> Instead only three, the five! packets are transferred.

Look to Ajp13.java:
public static final int  MAX_SEND_SIZE = MAX_PACKET_SIZE - H_SIZE - 4;
8184.
The CoyoteWriter gets called with blocks of 8192 bytes max... 8184+8...

>
> Seems that algorithm is breaking 8192 bytes of data to
> two packets (8184 and 8 bytes).
>
> Bill,
> Any idea how to solve this, because it's way too
> inefficient.
> What's makes the things even worse is that for each
> packet Apache2 creates a transient bucket thus
> rising the memory usage.
>
>
> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

jean-frederic clere
In reply to this post by mturk
Mladen Turk wrote:

> Hi,
>
> Just noticed a strange behavior in the Java part of the
> JK dealing with large (over 8184 bytes) data transfers.
>
> Since with 8192 bytes AJP packet size, the maximum
> transferred size per each packet is 8184 bytes one
> would expect that for 20000 bytes file the packets
> would be in a form of:
> 1:8184,2:8184,3:3632 thus total of 20000 bytes.
>
> But in fact the behavior is rely weird:
> 1:8184,2:8,3:8184,4:8,5:3616.
>
> Instead only three, the five! packets are transferred.
>
> Seems that algorithm is breaking 8192 bytes of data to
> two packets (8184 and 8 bytes).

Ajp13.java... No that is the old code the new one is in JkCoyoteHandler.java.
In JkCoyoteHandler the method doWrite cuts the 8192 bytes in 2 messages: one of
8184 and the other of 8 bytes that is the problem.

>
> Bill,
> Any idea how to solve this, because it's way too
> inefficient.
> What's makes the things even worse is that for each
> packet Apache2 creates a transient bucket thus
> rising the memory usage.
>
>
> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

mturk
In reply to this post by Bill Barker-2
Bill Barker wrote:

>
>
> I see what this is now:  The default Connector OutputBuffer size is 8K,
> so it's sending the output to JkInputStream in 8K chunks.  JkInputStream
> sends all of the 8K to Apache in two chunks.
>
> As a Coyote OutputBuffer, it's not really JkInputStream's job to do
> additional buffering.  It's probably better to do
> response.setBufferSize(20000); so that the Connector will send the whole
> thing to JkInputStream as one chunk.
>


Sure that seems to be the problem, but it's hard to convince the users
to write the applications having AJP packet size in mind ;)
The best would be that instead default 8192 bytes, when AJP connector
is loaded that response size is either set to 8184 or 16386 bytes
(one or two packets) by default.

Is something like that possible?

Regards,
Mladen.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

Bill Barker-2

----- Original Message -----
From: "Mladen Turk" <[hidden email]>
To: "Tomcat Developers List" <[hidden email]>
Sent: Thursday, May 19, 2005 2:19 PM
Subject: Re: AJP/Java connector issues


> Bill Barker wrote:
> >
> >
> > I see what this is now:  The default Connector OutputBuffer size is 8K,
> > so it's sending the output to JkInputStream in 8K chunks.  JkInputStream
> > sends all of the 8K to Apache in two chunks.
> >
> > As a Coyote OutputBuffer, it's not really JkInputStream's job to do
> > additional buffering.  It's probably better to do
> > response.setBufferSize(20000); so that the Connector will send the whole
> > thing to JkInputStream as one chunk.
> >
>
>
> Sure that seems to be the problem, but it's hard to convince the users
> to write the applications having AJP packet size in mind ;)
> The best would be that instead default 8192 bytes, when AJP connector
> is loaded that response size is either set to 8184 or 16386 bytes
> (one or two packets) by default.
>
> Is something like that possible?
>
It would be really easy to default to 8184 for all Connectors (just change
the value in o.a.c.connector.OutputBuffer).  I'm not so sure how happy that
would make Remy.

It wouldn't be too hard to have Connector.createResponse check the protocol,
and if it's AJP/1.3 then set the buffer size to 16386 (currently it's not
possible to decrease the buffer size).

It wouldn't be that hard to add buffering to JkInputStream so that it always
tries to write out a 8184 packet.  This would also prevent fracturing in the
event that the webapp programmer decides to call response.setBufferSize
herself.  The downside would be an extra arraycopy when writing (and, of
course, an extra 8184*numThreads bytes of memory used :).

> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>



This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.

In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

mturk
Bill Barker wrote:
>>
>>Is something like that possible?
>>
>
> It would be really easy to default to 8184 for all Connectors (just change
> the value in o.a.c.connector.OutputBuffer).  I'm not so sure how happy that
> would make Remy.
>

Not much I'm afraid ;)


> It wouldn't be too hard to have Connector.createResponse check the protocol,
> and if it's AJP/1.3 then set the buffer size to 16386 (currently it's not
> possible to decrease the buffer size).
>

That would be great.


> It wouldn't be that hard to add buffering to JkInputStream so that it always
> tries to write out a 8184 packet.  This would also prevent fracturing in the
> event that the webapp programmer decides to call response.setBufferSize
> herself.  The downside would be an extra arraycopy when writing (and, of
> course, an extra 8184*numThreads bytes of memory used :).
>

Not very optimal IMO. If somebody sets the buffer size by hand, then,
well, he probably knows better :)

Regards,
Mladen.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

remm
Mladen Turk wrote:

> Bill Barker wrote:
>
>>>
>>> Is something like that possible?
>>>
>>
>> It would be really easy to default to 8184 for all Connectors (just
>> change
>> the value in o.a.c.connector.OutputBuffer).  I'm not so sure how happy
>> that
>> would make Remy.
>>
>
> Not much I'm afraid ;)
>
>
>> It wouldn't be too hard to have Connector.createResponse check the
>> protocol,
>> and if it's AJP/1.3 then set the buffer size to 16386 (currently it's not
>> possible to decrease the buffer size).
>>
>
> That would be great.
>
>
>> It wouldn't be that hard to add buffering to JkInputStream so that it
>> always
>> tries to write out a 8184 packet.  This would also prevent fracturing
>> in the
>> event that the webapp programmer decides to call response.setBufferSize
>> herself.  The downside would be an extra arraycopy when writing (and, of
>> course, an extra 8184*numThreads bytes of memory used :).
>>
>
> Not very optimal IMO. If somebody sets the buffer size by hand, then,
> well, he probably knows better :)

None of these solve a real issue. Right now, the AJP packet generation
will do byte copying, which is bad unless you also use that mandatory
copying to minimize the amount of network packets sent. It's the same as
chunking in HTTP, and does need a socket buffer for best efficiency.
Conviniently, with APR, I need to have direct buffers to handle read and
write, so I'll use them as the socket buffers (like in HTTP).

R?my

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

jean-frederic clere
In reply to this post by mturk
Mladen Turk wrote:

> Hi,
>
> Just noticed a strange behavior in the Java part of the
> JK dealing with large (over 8184 bytes) data transfers.
>
> Since with 8192 bytes AJP packet size, the maximum
> transferred size per each packet is 8184 bytes one
> would expect that for 20000 bytes file the packets
> would be in a form of:
> 1:8184,2:8184,3:3632 thus total of 20000 bytes.
>
> But in fact the behavior is rely weird:
> 1:8184,2:8,3:8184,4:8,5:3616.
>
> Instead only three, the five! packets are transferred.
>
> Seems that algorithm is breaking 8192 bytes of data to
> two packets (8184 and 8 bytes).
I have an ugly patch for that. Find it attached (that just for gettting comments).

Cheers

Jean-Frederic

>
> Bill,
> Any idea how to solve this, because it's way too
> inefficient.
> What's makes the things even worse is that for each
> packet Apache2 creates a transient bucket thus
> rising the memory usage.
>
>
> Regards,
> Mladen.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

Index: Response.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Response.java,v
retrieving revision 1.12
diff -u -r1.12 Response.java
--- Response.java 25 Apr 2005 22:06:30 -0000 1.12
+++ Response.java 20 May 2005 15:56:25 -0000
@@ -68,6 +68,16 @@
 
 
     public Response() {
+        outputBuffer = new OutputBuffer();
+        outputStream = new CoyoteOutputStream(outputBuffer);
+        writer = new CoyoteWriter(outputBuffer);
+        urlEncoder.addSafeCharacter('/');
+    }
+
+    public Response(int size) {
+        outputBuffer = new OutputBuffer(size);
+        outputStream = new CoyoteOutputStream(outputBuffer);
+        writer = new CoyoteWriter(outputBuffer);
         urlEncoder.addSafeCharacter('/');
     }
 
@@ -174,20 +184,19 @@
     /**
      * The associated output buffer.
      */
-    protected OutputBuffer outputBuffer = new OutputBuffer();
+    protected OutputBuffer outputBuffer;
 
 
     /**
      * The associated output stream.
      */
-    protected CoyoteOutputStream outputStream =
-        new CoyoteOutputStream(outputBuffer);
+    protected CoyoteOutputStream outputStream;
 
 
     /**
      * The associated writer.
      */
-    protected CoyoteWriter writer = new CoyoteWriter(outputBuffer);
+    protected CoyoteWriter writer;
 
 
     /**
Index: Connector.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Connector.java,v
retrieving revision 1.18
diff -u -r1.18 Connector.java
--- Connector.java 30 Apr 2005 03:32:43 -0000 1.18
+++ Connector.java 20 May 2005 15:56:42 -0000
@@ -897,7 +897,12 @@
      */
     public Response createResponse() {
 
-        Response response = new Response();
+        System.out.println("Connector: createResponse: getProtocol: " + getProtocol());
+        Response response = null;
+        if ("AJP/1.3".equals(getProtocol()))
+            response = new Response(8184);
+        else
+            response = new Response();
         response.setConnector(this);
         return (response);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: AJP/Java connector issues

Bill Barker-2

----- Original Message -----
From: "jean-frederic clere" <[hidden email]>
To: "Tomcat Developers List" <[hidden email]>
Sent: Friday, May 20, 2005 9:02 AM
Subject: Re: AJP/Java connector issues


> Mladen Turk wrote:
> > Hi,
> >
> > Just noticed a strange behavior in the Java part of the
> > JK dealing with large (over 8184 bytes) data transfers.
> >
> > Since with 8192 bytes AJP packet size, the maximum
> > transferred size per each packet is 8184 bytes one
> > would expect that for 20000 bytes file the packets
> > would be in a form of:
> > 1:8184,2:8184,3:3632 thus total of 20000 bytes.
> >
> > But in fact the behavior is rely weird:
> > 1:8184,2:8,3:8184,4:8,5:3616.
> >
> > Instead only three, the five! packets are transferred.
> >
> > Seems that algorithm is breaking 8192 bytes of data to
> > two packets (8184 and 8 bytes).
>
> I have an ugly patch for that. Find it attached (that just for gettting
comments).
>

If we move the protocol check into Response.setConnector, the patch isn't
even that ugly ;-).

> Cheers
>
> Jean-Frederic
>
> >
> > Bill,
> > Any idea how to solve this, because it's way too
> > inefficient.
> > What's makes the things even worse is that for each
> > packet Apache2 creates a transient bucket thus
> > rising the memory usage.
> >
> >
> > Regards,
> > Mladen.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
> >
> >
>
>

----------------------------------------------------------------------------
----


> Index: Response.java
> ===================================================================
> RCS file:
/home/cvspublic/jakarta-tomcat-catalina/catalina/src/share/org/apache/catali
na/connector/Response.java,v

> retrieving revision 1.12
> diff -u -r1.12 Response.java
> --- Response.java 25 Apr 2005 22:06:30 -0000 1.12
> +++ Response.java 20 May 2005 15:56:25 -0000
> @@ -68,6 +68,16 @@
>
>
>      public Response() {
> +        outputBuffer = new OutputBuffer();
> +        outputStream = new CoyoteOutputStream(outputBuffer);
> +        writer = new CoyoteWriter(outputBuffer);
> +        urlEncoder.addSafeCharacter('/');
> +    }
> +
> +    public Response(int size) {
> +        outputBuffer = new OutputBuffer(size);
> +        outputStream = new CoyoteOutputStream(outputBuffer);
> +        writer = new CoyoteWriter(outputBuffer);
>          urlEncoder.addSafeCharacter('/');
>      }
>
> @@ -174,20 +184,19 @@
>      /**
>       * The associated output buffer.
>       */
> -    protected OutputBuffer outputBuffer = new OutputBuffer();
> +    protected OutputBuffer outputBuffer;
>
>
>      /**
>       * The associated output stream.
>       */
> -    protected CoyoteOutputStream outputStream =
> -        new CoyoteOutputStream(outputBuffer);
> +    protected CoyoteOutputStream outputStream;
>
>
>      /**
>       * The associated writer.
>       */
> -    protected CoyoteWriter writer = new CoyoteWriter(outputBuffer);
> +    protected CoyoteWriter writer;
>
>
>      /**
> Index: Connector.java
> ===================================================================
> RCS file:
/home/cvspublic/jakarta-tomcat-catalina/catalina/src/share/org/apache/catali
na/connector/Connector.java,v

> retrieving revision 1.18
> diff -u -r1.18 Connector.java
> --- Connector.java 30 Apr 2005 03:32:43 -0000 1.18
> +++ Connector.java 20 May 2005 15:56:42 -0000
> @@ -897,7 +897,12 @@
>       */
>      public Response createResponse() {
>
> -        Response response = new Response();
> +        System.out.println("Connector: createResponse: getProtocol: " +
getProtocol());

> +        Response response = null;
> +        if ("AJP/1.3".equals(getProtocol()))
> +            response = new Response(8184);
> +        else
> +            response = new Response();
>          response.setConnector(this);
>          return (response);
>
>
>

----------------------------------------------------------------------------
----


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]



This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.

In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]