[rabbitmq-discuss] Use of Java 1.4 with the RabbitMQ Java Client library

Kirk Wylie kirk at kirkwylie.com
Wed Jan 7 16:46:08 GMT 2009


On Wed, Jan 7, 2009 at 3:33 PM, Holger Hoffstätte <holger at wizards.de> wrote:
> Kirk Wylie wrote:
>> One of the first things I wanted to do was to improve the current test
>> suite to add quite a few more "pure" unit tests (right now it's almost
>
> good - though not sure how much they are ultimately worth it, as much of
> the functionality is in the autogenerated protocol. Other than that I
> found the code to be very readable and understandable, especially
> considering how much time could be spent on it.

Oh, yeah, the code is definitely in good shape, but it could always be
better. :-)

The primary reason I thought to add some pure "unit" tests is that in
conjunction with coverage tools (which you and I both have referenced)
you can get some pretty interesting optimization and bang-for-the-buck
test cases. It's also a lot easier to identify precisely WHERE you've
broken the code with low-level tests-in-isolation.

>> Then the first crazy/mundane thing that I was going to attempt was a
>> connection pooling system. Because that'll be quite complex, I want to
>> tackle the test side first so that I'm confident that I'm not breaking
>> things in subtle ways.
>
> Oh dear. :) Got so many connections? I thought they were supposed to be
> kept open.

They are. That's the point. :-)

The issue is one similar to JDBC-based systems. You may have an object
which is otherwise stateless that needs to just publish out a message
when certain things happen. Does that one object need its own
Connection? No. Does it need to really hold open a stateful socket? No
as well. So it's probably easiest conceptually for the block to:
- Acquire a Connection
- Publish Message
- Release the Connection
Given that you may want to have blocks like that, and you might NOT
want to actually have "acquire a connection" mean "open a TCP socket",
you have a natural case for connection pools.

Admittedly, this is less useful than in JDBC, where a connection is
also a session, but I've come across cases where it would be useful in
the past, so no reason why we couldn't give it a shot! :-)

> Crazy German Alert!
>
> - define common org.amqp interfaces (ala JMS) so that client app code
> doesn't rely on the client lib implementation. Would require some work
> with the WG but as the spec, entities and semantics keep changing it would
> be a moving target so I haven't really bothered yet. Not sure if anybody
> would even care as soon as the JMS mapping has been wrangled into the spec.

I think JMS is quite possibly the better strategy for this, as you've
indicated. But the fact that your multiple client libraries are
implementing the same protocol means that you're probably not in as
bad a situation as you would be with JMS, and that locks everybody
into the same API at the code level. Perhaps one of the things that
AMQP brings to the table is that you can choose the protocol
implementation that most closely matches your desired API rather than
choosing your API based on the protocol that it needs to implement.

Once 0-9-1 reaches full interoperability, I don't expect for example
that there will even BE multiple AMQP Java client libraries that have
equivalent enough code APIs that you could do this. Why would there
be?

> - n:m mapping of channels to socket connections, based on either some
> up-front fixed ratio/priority scheme or dynamically adjusted traffic per
> channel (maybe grouping slow/mostly-idle periodic polling/ticker channels
> together). This would allow to connect to multiple broker instances in
> parallel.

Think of this in terms of a connection pool. That's what I'm talking about.

The connection pool concept here is more subtle than one for a
database (where connection == session/channel). In fact, rather than
having a "locked out/locked in" nature, you have a load factor on each
individual connection, which may be based on # channels, or something
even more sophisticated (load in messages or bytes/second, burst rate,
etc.).

> - maybe moving to NIO since it might nicely map to AMQP channels. A Netty
> AMQP packet codec should be easy, and a consumer could register a payload
> decoder on top of a channel for easy payload disassembly - Thrift,
> Protobufs, XML (arrgh).

NIO does match well, but NIO in Java doesn't match thread-blocking
old-IO for performance yet. It's far more a server-side technology in
terms of performance these days, because you have to have a LOT of
sockets open for NIO to beat OldIO for performance by any metric.

But it would definitely be an interesting talking point for the
community, and an NIO-based client could be quite useful for people
trying to do big AMQP routing and relaying in Java (see my comment
above about letting a thousant client libraries bloom with different
code-level APIs). I think if you're working with pure asynch IO, you
might want a different client API entirely to take advantage of it.

BTW, thanks for the link to Netty. Hadn't run across it yet.

> - more concurreny all the way, decoupling fragment assembly/concurrent
> consumer delivery and the reader thread, backed by an injectable Executor
> (looking at you, WorkManager). Incidentally that's how Netty works too.
> Also the channel map is pretty oversynchronized and used from multiple
> paths..not so good for multiple connections.

> - no blocking queues and only concurrent dequeues where they cannot be
> avoided. only blocking on condition objects, and always with timeouts.

Yep, there's definitely some places where concurrent performance could
be improved. And continuing to rely on backports-concurrent might
hinder that (which is why I started this trying to figure out whether
people are even using it in 1.4).

> - find a way towards as-zero-copy-as-possible fragment assembly. Each time
> I see dozens of litte byte[]s being copied around 17 times for a single
> message because of the !"§$ stream APIs my inner geek dies a little.
>
> - JMX beanz for stats
>
> - write a Spring-Integration transport because it happens to be based on
> channel abstractions and will likely map nicely.
>
> like I said, crazy.. and probably totally useless.

I don't think any of those are crazy or probably useless. If nothing
else, it gives me some fodder to get going with!

Kirk




More information about the rabbitmq-discuss mailing list