EMS Performance Issue - java

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.

Related

how does jms interact with the underlying database?

I understand JMS as depicted by the following diagram:
(source: techhive.com)
Is there any way for me to access the underlying database using JMS or some other thing? Further, the JDBC connections that the JMS server maintains, can I add new connections in it so as to access other databases also and do CRUD operations on them? If yes, how?
Where did you get this from?
Normally JMS is used to send messages to queue (or topics). You have message producers that push messages in the queue and message consumers consume them and process it.
In your exemple it seems that you have multiple queues. One for the messages that need to be processed, and one for each client to retrieve the result the processing of its messages.
With JMS Server you don't necessarily have a database behind. Everything can stay in memory, or can be written to files. You will need database server behind only if you configure your JMS server to be persistent (and to assure that even if server/application crash your messages won't be lost). But in that case you will never have to interact with the database. Only the JMS server will and you will interact with the JMS server sending and consuming messages.

RabbitMQ and relationship between channel and connection

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.

How JMS client notice about new message

I'm learning JMS and wonder how a JMS client (e.g MessageListener) can notice about a new message in queue it registed. Is it frequently send requests to broker via TCP to see if there's a new message? If so, is this request synchronousor asynchronous?
JMS is just an API. It does not specify any wire level protocol. So you can't really tell how the client will behave with the broker. It could use a homing piegon for all we know. Ok, maybe not, but brokers like WebSphere MQ and ActiveMQ both supply in memory transport as well as TCP based.
Most vendors have thier own properitary protocols even though AMQP is visible on the horizon as a wire protocol standard (but far from all vendors have started to look at it).
When talking TCP there is no need to poll as long as there is a live connection going on. The broker can easily notify the client that there is a new message published while the client sleeps and the other way around.
A common way, however, is to actually do poll. But rather poll for consumer.receive(TIMEOUT); in some longer intervals (seconds). This makes it possible to use distributed transactions in frameworks like spring. Still the broker sends actual TCP messages to the client on demand.
If it would not have been like this, then JMS/Messaging would not have been such a fast, wide psread and scalable technology
1) First of all, JMS does not have something called absolute synchronous messaging. You can definitely implement so called JMS Synchronous messaging by implementing Sync service methods but in fact it just appears to be mimicking as Synchronous messaging. In fact it is also Async Messaging.
2) Technically it is the JMS Server / Broker which sends Messages to Message Consumers through dedicated queues. Broker simply delivers the message to Message Consumer's onMessage() method. And then Container executes onMessage() method.

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.

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