RabbitMQ and relationship between channel and connection - java

The RabbitMQ Java client has the following concepts:
Connection - a connection to a RabbitMQ server instance
Channel - ???
Consumer thread pool - a pool of threads that consume messages off the RabbitMQ server queues
Queue - a structure that holds messages in FIFO order
I'm trying to understand the relationship, and more importantly, the associations between them.
I'm still not quite sure what a Channel is, other than the fact that this is the structure that you publish and consume from, and that it is created from an open connection. If someone could explain to me what the "Channel" represents, it might help clear a few things up.
What is the relationship between Channel and Queue? Can the same Channel be used to communicate to multiples Queues, or does it have to be 1:1?
What is the relationship between Queue and the Consumer Pool? Can multiple Consumers be subscribed to the same Queue? Can multiple Queues be consumed by the same Consumer? Or is the relationship 1:1?

A Connection represents a real TCP connection to the message broker, whereas a Channel is a virtual connection (AMQP connection) inside it. This way you can use as many (virtual) connections as you want inside your application without overloading the broker with TCP connections.
You can use one Channel for everything. However, if you have multiple threads, it's suggested to use a different Channel for each thread.
Channel thread-safety in Java Client API Guide:
Channel instances are safe for use by multiple threads. Requests into
a Channel are serialized, with only one thread being able to run a
command on the Channel at a time. Even so, applications should prefer
using a Channel per thread instead of sharing the same Channel across
multiple threads.
There is no direct relation between Channel and Queue. A Channel is used to send AMQP commands to the broker. This can be the creation of a queue or similar, but these concepts are not tied together.
Each Consumer runs in its own thread allocated from the consumer thread pool. If multiple Consumers are subscribed to the same Queue, the broker uses round-robin to distribute the messages between them equally. See Tutorial two: "Work Queues".
It is also possible to attach the same Consumer to multiple Queues.
You can understand Consumers as callbacks. These are called everytime a message arrives on a Queue the Consumer is bound to. For the case of the Java Client, each Consumers has a method handleDelivery(...), which represents the callback method. What you typically do is, subclass DefaultConsumer and override handleDelivery(...). Note: If you attach the same Consumer instance to multiple queues, this method will be called by different threads. So take care of synchronization if necessary.

A good conceptual understanding of what the AMQP protocol does "under the hood" is useful here. I would offer that the documentation and API that AMQP 0.9.1 chose to deploy makes this particularly confusing, so the question itself is one which many people have to wrestle with.
TL;DR
A connection is the physical negotiated TCP socket with the AMQP server. Properly-implemented clients will have one of these per application, thread-safe, sharable among threads.
A channel is a single application session on the connection. A thread will have one or more of these sessions. AMQP architecture 0.9.1 is that these are not to be shared among threads, and should be closed/destroyed when the thread that created it is finished with it. They are also closed by the server when various protocol violations occur.
A consumer is a virtual construct that represents the presence of a "mailbox" on a particular channel. The use of a consumer tells the broker to push messages from a particular queue to that channel endpoint.
Connection Facts
First, as others have correctly pointed out, a connection is the object that represents the actual TCP connection to the server. Connections are specified at the protocol level in AMQP, and all communication with the broker happens over one or more connections.
Since it's an actual TCP connection, it has an IP Address and Port #.
Protocol parameters are negotiated on a per-client basis as part of setting up the connection (a process known as the handshake.
It is designed to be long-lived; there are few cases where connection closure is part of the protocol design.
From an OSI perspective, it probably resides somewhere around Layer 6
Heartbeats can be set up to monitor the connection status, as TCP does not contain anything in and of itself to do this.
It is best to have a dedicated thread manage reads and writes to the underlying TCP socket. Most, if not all, RabbitMQ clients do this. In that regard, they are generally thread-safe.
Relatively speaking, connections are "expensive" to create (due to the handshake), but practically speaking, this really doesn't matter. Most processes really will only need one connection object. But, you can maintain connections in a pool, if you find you need more throughput than a single thread/socket can provide (unlikely with current computing technology).
Channel Facts
A Channel is the application session that is opened for each piece of your app to communicate with the RabbitMQ broker. It operates over a single connection, and represents a session with the broker.
As it represents a logical part of application logic, each channel usually exists on its own thread.
Typically, all channels opened by your app will share a single connection (they are lightweight sessions that operate on top of the connection). Connections are thread-safe, so this is OK.
Most AMQP operations take place over channels.
From an OSI Layer perspective, channels are probably around Layer 7.
Channels are designed to be transient; part of the design of AMQP is that the channel is typically closed in response to an error (e.g. re-declaring a queue with different parameters before deleting the existing queue).
Since they are transient, channels should not be pooled by your app.
The server uses an integer to identify a channel. When the thread managing the connection receives a packet for a particular channel, it uses this number to tell the broker which channel/session the packet belongs to.
Channels are not generally thread-safe as it would make no sense to share them among threads. If you have another thread that needs to use the broker, a new channel is needed.
Consumer Facts
A consumer is an object defined by the AMQP protocol. It is neither a channel nor a connection, instead being something that your particular application uses as a "mailbox" of sorts to drop messages.
"Creating a consumer" means that you tell the broker (using a channel via a connection) that you would like messages pushed to you over that channel. In response, the broker will register that you have a consumer on the channel and begin pushing messages to you.
Each message pushed over the connection will reference both a channel number and a consumer number. In that way, the connection-managing thread (in this case, within the Java API) knows what to do with the message; then, the channel-handling thread also knows what to do with the message.
Consumer implementation has the widest amount of variation, because it's literally application-specific. In my implementation, I chose to spin off a task each time a message arrived via the consumer; thus, I had a thread managing the connection, a thread managing the channel (and by extension, the consumer), and one or more task threads for each message delivered via the consumer.
Closing a connection closes all channels on the connection. Closing a channel closes all consumers on the channel. It is also possible to cancel a consumer (without closing the channel). There are various cases when it makes sense to do any of the three things.
Typically, the implementation of a consumer in an AMQP client will allocate one dedicated channel to the consumer to avoid conflicts with the activities of other threads or code (including publishing).
In terms of what you mean by consumer thread pool, I suspect that Java client is doing something similar to what I programmed my client to do (mine was based off the .Net client, but heavily modified).

I found this article which explains all aspects of the AMQP model, of which, channel is one. I found it very helpful in rounding out my understanding
https://www.rabbitmq.com/tutorials/amqp-concepts.html
Some applications need multiple connections to an AMQP broker. However, it is undesirable to keep many TCP connections open at the same time because doing so consumes system resources and makes it more difficult to configure firewalls. AMQP 0-9-1 connections are multiplexed with channels that can be thought of as "lightweight connections that share a single TCP connection".
For applications that use multiple threads/processes for processing, it is very common to open a new channel per thread/process and not share channels between them.
Communication on a particular channel is completely separate from communication on another channel, therefore every AMQP method also carries a channel number that clients use to figure out which channel the method is for (and thus, which event handler needs to be invoked, for example).

There is a relation between like A TCP connection can have multiple Channels.
Channel: It is a virtual connection inside a connection. When publishing or consuming messages from a queue - it's all done over a channel Whereas Connection: It is a TCP connection between your application and the RabbitMQ broker.
In multi-threading architecture, you may need a separate connection per thread. That may lead to underutilization of TCP connection, also it adds overhead to the operating system to establish as many TCP connections it requires during the peak time of the network. The performance of the system could be drastically reduced. This is where the channel comes handy, it creates virtual connections inside a TCP connection. It straightaway reduces the overhead of the OS, also it allows us to perform asynchronous operations in a more faster, reliable and simultaneously way.

Related

EMS Performance Issue

I am writing a service which serves stateless incoming requests. The requests are all mathematical calculation, which does not take very long to execute ( max 2ms).
I use Tibco EMS to communicate between client/server. A client library is provided which wraps the client side logic (e.g. convert data into EMS message etc) and send the request to a request queue. The server side processes the request and send the response into a separate queue. This works fine.
The server side is multi-threaded. A new thread is created when a new incoming request is received. Requests are therefore handled concurrently.
The server side uses one single EMS connection to the EMS server. However, because EMS Session is not thread safe, if I want to be able to write the response to EMS queue in each thread, I have to create one session for each thread using the connectionFactory. This degraded the performance.
The time spent on traffic is around 3-4ms, i.e. Time between a request is sent and a response is received is around 5-6ms.(3-4ms for transportation, marshal/unmarshal, 2ms for calculation).
Is there any solution which allows me to concurrently send to a EMS queue without creating two much JMS objects?
Are there any other important rules I need to follow to further optimize the service? Some basic optimization guidelines are already followed:
Use CachedConnectionPool
Send JMS message as NON_PERSISTANT
Use one EMS connection for all requests.
Thank you very much.
The behavior you are experiencing is not specific to EMS. The behavior is dictated by the JMS specification itself. Here is an extract from section 2.8 of the JMS Specification:
There are two reasons for restricting concurrent access to Sessions. First, Sessions are the JMS entity that supports transactions. It is very difficult to implement transactions that are multithreaded. Second, Sessions support asynchronous message consumption. It is important that JMS not require that client code used for asynchronous message consumption be capable of handling multiple, concurrent messages. In addition, if a Session has been set up with multiple, asynchronous consumers, it is important that the client is not forced to handle the case where these separate consumers are concurrently executing. These restrictions make JMS easier to use for typical clients. More sophisticated clients can get the concurrency they desire by using multiple sessions.
If you want to avoid the creation (and destruction) of that many objects, you might want to pre-create a pool of threads, and allocate a session to each thread up front.

Detect closed client UDP channel in Netty 4

I'm using Netty as part of a UDP server which opens a number of persistent connections with various clients on a single server channel. I need to perform some cleanup when a client terminates the connection. Specifically, I need to know when the connection is terminated and from which IP address the terminating client is located at so that I can cleanup the data.
Perhaps I'm misunderstanding the Netty model, but I'm unsure how to detect this. I normally distinguish between various clients by checking the sender's IP address from the DatagramPacket instances, perhaps that is wrong and I should be using multiple channels or something like that? Either way, I'm looking for some way to handle a closed connection.
You're misunderstanding UDP, not Netty. There is no such thing as a "persistent connection" in UDP, although there can be application-managed sessions, and UDP provides no information about whether the other endpoint is still active. Ideally, you'll have a "close" message, but you'll need to have a timeout or other mechanism to identify dead connections and clean them up (for crashed clients, etc.). This will require some sort of garbage-collection process, maybe a background thread that checks a "last heard from" timestamp and closes inactive sessions.

How does threading work in Mule 1.3?

I have a tcp endpoint which send messages to a java component that calls a stored procedure in db and do some processing on the result and return it to the same tcp.
What I knew that every tcp request will be in it's own thread , but if the messages comes from the same connection does that mean i'll have only one thread , I need to configure mule to make the java component multi-threaded.
The only thing I found is this :
http://www.mulesoft.org/documentation/display/MULE3USER/Tuning+Performance#TuningPerformance-pooling
and I can't understand it :D
In Mule 3, whose doc you've linked in your question, message receivers (ie inbound endpoints) typically have a dedicated work manager with a pool of threads assigned to process requests in parallel (the exception is the JMS connector which acts a little different).
So in your case, the TCP inbound endpoint will have, by default, 16 threads assigned to deal with incoming requests that hits the single open TCP socket.
No need to use pooled components.
EDIT: The question is about Mule 1.3, which is super old and has a very different threading model. In that case, each endpoint has a different thread pool.

How to design an MQ Server?

I'm unclear as to whether there should be a 1-1 or a 1-* relationship between:
Server-Connection Channel and JMS Topic
Server-Connection Channel and Listener
Listener and Topic
Regards the design of our application layer, there is a single MDB that in response to a message, does some work, then publishes messages onto a variety of output topics. The service layer is listening on these output topics.
Currently I have a 1-1-1 between Channel-Listener-Topic, and therefore an instance of JmsConnectionFactory for each publisher (on the app side) and listener (on the service side).
There are a couple of different ways to look at this. From the point of view of your application one connection factory can have many sessions. Each session may have many consumers but units of work are scoped per session, not per consumer. So more than likely you want one connection factory with multiple sessions where each session has a listener on a particular topic. If you have a listener assigned to multiple consumers on a single session, any acknowledge (or COMMIT in a transacted session) commits all messages got or put in that session.
From the WMQ server's point of view, one channel definition can have many running instances. So you only need the one SVRCONN channel defined per app, regardless of how many channel instances it needs to start. Try not to put different apps on the same SVRCONN though because you often want to administer or authorize the apps separately. For example, with apps on separate channels you could easily figure out which app was misbehaving if you suddenly found yourself with 3000 running channels.
For purposes of administration and debugging, I'd probably have one CF for the app side and one CF for the service side. Each would point to a different SVRCONN channel as described above. Inside the app server I'd stick with one topic per session unless it is valid for your app to consume off multiple topics in a single unit of work. In the subscription you can specify a wildcard topic to get all topics below a certain point in the topic tree with a single subscriber.
Just for best practices, I'd also set the CF to use FAILIFQUIESCE to make sure the QMgr can be stopped in an orderly fashion and I'd use SYNCPOINTALLGETS (or a transacted session with explicit commit calls) in order to improve reliability as per the JMS 1.1 spec, sestion 4.4.13 which states:
If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return from the sending method. It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages.
A message that is redelivered due to session recovery is not considered a duplicate message.
The SYNCPOINTALLGETS (a.k.a. SPAG) insures that messages retrieved from the queue are delivered to your app before being committed and permanently removed from the queue. Otherwise if you lose your connection while the QMgr is trying to return a message, it's gone for good. With SPAG set you might see the same message twice as described in the JMS spec, but you'll never drop one.
For more details of the options available to the CF, queue and topic objects, see: Properties of objects in the WebSphere MQ Using Java manual.
WMQ v6.0 is end-of-life as of September 2012 so please be sure to develop using the v7 clients, even if the server is at v6. This will reduce your migration effort next year. Download v7 client here and the WMQ v7.1 client here.
An MDB in a container creates a pool of MDBs that concurrently process messages. If you simply process and write to the topic you will be fine. With this in mind you do not have a 1-1-1 relationship.
In your MDB just do a JNDI lookup of your TopicConnectionFactory and your Topic and then just write. Look here: http://middleware.its.state.nc.us/middleware/Documentation/en_US/htm/csqzaw09/csqzaw0931.htm

JMS - common uses

What is common and useful uses of JMS and Message Driven Beans?
Asynchronous communication: The caller returns quickly, and can continue its work (without creating a new thread) and the message can be processed later. Messages can be stored, and even when the server fails, they can continue to be processed, once the server starts up again. Messages can be distributed to multiple machines (optionally based on rules).
Callers and callees can be decoupled (the caller doesn't have to know, who will consume the message, and how many message consumers there are).
It can have enormous performance advantages compared to synchronous communication. Such a messaging middleware can be crucial for services that have to handle lots of messages per second (think of Twitter for example). But it's not restricted to human readable messages.
Another reason to choose JMS and MDBs is guaranteed delivery. A synchronous, point to point call fails if the receiver is unavailable, but a queue can be set up to guarantee delivery, handle retries or transactional failures, use error queues for messages that are "poison", etc.
There are two transmission models built into JMS: point-to-point using queues and publish/subscribe using topics. Each has its own advantages.
The downside of JMS and MDBs is speed of response. You might like the decoupling, but if you block and wait for a response it'll certainly be slower than a direct remote method invocation, because there are two network trips involved instead of just one.

Categories