首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

7.3 使用JMS实现请求/对答程序

2013-11-15 
7.3 使用JMS实现请求/应答程序}...?The listener creates a new message, assigns the appropriate correl

7.3 使用JMS实现请求/应答程序

}

...

?

The listener creates a new message, assigns the appropriate correlation ID, and sends

a message to the reply-to queue. Simple stuff, but still important. Although this message

listener isn’t earth shattering in its implementation, it demonstrates the basic

steps necessary to complete the task of the worker. Any amount of extra processing or

database access could be added to the listener in your systems depending on the

requirements.

?

消息监听器创建一个新消息,并设置合适的correlation ID,然后将消息发送到响应消息队列.

很简单但是很重要.尽管在这个消息监听器的实现中没做什么惊天动地的事情,但是它展示了

工作者完成器任务的必要的基本步骤.根据需求,,可以在监听器中添加其他任意额外的操作

或者数据库访问操作.

?

Starting the server is rather obvious: create an instance of it and call the start()

method. All of the server functionality is housed in the main method, as shown in the

following listing.

启动服务很简单:创建一个server实例并调用start()方法.main方法容纳了server的的所有功能,如

下面的代码清单所示:

?

Listing 7.16 Starting the server for the request-reply example

...

public static void main(String[] args) throws Exception?

{

? Server server = new Server();

? server.start();

? System.out.println();

? System.out.println("Press any key to stop the server");

? System.out.println();

? System.in.read();

? server.stop();

}

...

?

Once the server is started and the worker is running, everything is ready to accept

requests from the client.

?

一旦server启动完成,worker就正常运行了,这样所有准备接收客户端请求的工作已经就绪.

?

7.3.2 Implementing the client

7.3.2 实现客户端

?

The job of the client is to initiate requests to the broker. This is where the whole

request/reply process begins, and is typically triggered by one of your business processes.

This process could be to accept an order, fulfill an order, integrate various business

systems, or buy or sell a financial position. Whatever the case may be, request/reply

begins by sending a message.

?

客户端要做到额工作是初始化发送到代理的请求.这是整个请求/应答过程的起点,并且通常在一个

业务逻辑处理过程中触发.这个过程可能是接受订单,履行订单,整合各类业务系统,财务状况中

的买入卖出等.不管是什么情况,请求/响应过程从发送一个消息开始.

?

Sending a message to the broker requires the standard connection, session, destination,

and producer which are all created in the client by the start() method. This

is all shown in the following listing.

?

发送一个消息到代理需要标准的连接(connection),session,消息目的地(destination)以及消息

生产者(producer),它们都是在client的start()方法中创建的.下面的的代码清单中提供了完整的

示例:

?

Listing 7.17 Methods for starting and stopping the request/reply client

代码清单7.17 启动和停止响应/应答系统客户端的方法

?

...

public void start() throws JMSException?

{

? ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);

? connection = connectionFactory.createConnection();

? connection.start();

? session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

? Destination adminQueue = session.createQueue(requestQueue);

? producer = session.createProducer(adminQueue);

? producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

? tempDest = session.createTemporaryQueue();

? consumer = session.createConsumer(tempDest);

? consumer.setMessageListener(this);

}

?

public void stop() throws JMSException?

{

? producer.close();

? consumer.close();

? session.close();

? connection.close();

}

...

The producer sends a message to the request queue and then the consumer listens on

the newly created temporary queue. Now it’s time to implement an actual logic for the

client, as shown next.

?

消息生产者发送也给消息到请求队列中,然后消息消费者监听新创建的临时队列.下面的代码中

展示了实现客户端的真正逻辑:

?

Listing 7.18 Implementation of logic for request/reply client

代码清单7.18 实现客户端请求/应答逻辑

?

...

public void request(String request) throws JMSException?

{

? System.out.println("Requesting: " + request);

? TextMessage txtMessage = session.createTextMessage();

? txtMessage.setText(request);

? txtMessage.setJMSReplyTo(tempDest);

? String correlationId = UUID.randomUUID().toString();

? txtMessage.setJMSCorrelationID(correlationId);

? this.producer.send(txtMessage);

}

?

public void onMessage(Message message)?

{

? try?

? {

? ? System.out.println("Received response for: " + ((TextMessage) message).getText());

? }?

? catch (JMSException e)?

? {

? ? e.printStackTrace();

? }

}

...

?

The request() method shown in listing 7.18 creates a message with the request content,

sets the JMSReplyTo property to the temporary queue, and sets the correlation

ID—these three items are important. Although the correlation ID in this case uses a

random UUID, just about any ID generator can be used. Now we’re ready to send a

request.

?

代码清单7.18中所示的request()方法使用请求内容创建一个消息并设置JMSReplyTo属性值,接着发送

这个消息到临时队列,最后设置correlation ID 属性值.上述3个步骤很重要.在这个例子中,是使用

一个随机的UUID值来设置correlation ID的,也还可以使用其他任何ID生成器来生成这个ID.

接下就可以发送一个请求了.

?

Just like starting the server was a simple main method, the same is true of the client

as shown in the next listing.

启动客户端也可以像启动sever一样,简单的使用一个main方法即可,下面是代码清单:

?

Listing 7.19 Starting the request/reply client

代码清单7.19 启动请求/应答系统客户端

?

...

public static void main(String[] args) throws Exception?

{

? Client client = new Client();

? client.start();

? int i = 0;

? while (i++ < 10)?

? {

? ? client.request("REQUEST-" + i);

? }

? Thread.sleep(3000); //wait for replies

? client.stop();

}

...

?

As explained earlier, this is a simple implementation. So upon starting up the client,

10 requests are sent to the broker. Now it’s time to actually run the example.

?

如前文所述,这个是一个简单的请求/应答系统的实现.因此,启动客户端以后,会发送10个请求到代理.

下面让我们真正的运行一下这个实例.

?

7.3.3 Running the request/reply example

7.3.3 运行请求/应答实例程序

?

Running the example requires two terminals: one for the server and one for the client.

The server needs to be started first. The server is implemented in a class named

Server and the client is implemented in a class named Client. Because each of these

classes is initiated via a main method, it’s easy to start each one. The following listing

demonstrates starting up the server class.

?

运行这个实例程序需要两个终端(译注:两个dos窗口或者两个Linux命令窗口):一个用于运行server,另一个

用于client,必须先运行server.sever通过Server类来实现,client通过Client类实现.因为这两个类都是

通过main方法初始化的,所以运行它们很容易.启动这两个类的代码如下所示:

?

Listing 7.20 Start up the server for the request/reply example

?

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.sync.Server

?

...

INFO | Using Persistence Adapter: MemoryPersistenceAdapter

INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) is starting

INFO | For help or more information please see:http://activemq.apache.org/

INFO | Listening for connections at: tcp://dejan-bosanacs-macbook-pro.local:61616

INFO | Connector tcp://dejan-bosanacs-macbook-pro.local:61616 Started

INFO | ActiveMQ JMS Message Broker (localhost, ID:dejanb-57522-1271170284460-0:0) started

Press any key to stop the server

INFO | ActiveMQ Message Broker(localhost, ID:dejanb-57522-1271170284460-0:0) is shutting down

INFO | Connector tcp://dejan-bosanacs-macbook-pro.local:61616 Stopped

INFO | ActiveMQ JMS Message Broker (localhost, ID:dejanb-57522-1271170284460-0:0) stopped

...

?

When the server is started up, then it’s time to start up the client and begin sending

requests. The following listing shows how to start up the client.

?

server启动后,即可启动client一边发送请求.启动client代码如下面代码清单所示:

?

Listing 7.21 Start up the client for the request/reply example

代码清单7.21 启动请求/响应实例客户端(client)

?

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.sync.Client

...

Requesting: REQUEST-1

Requesting: REQUEST-2

Requesting: REQUEST-3

Requesting: REQUEST-4

Requesting: REQUEST-5

Requesting: REQUEST-6

Requesting: REQUEST-7

Requesting: REQUEST-8

Requesting: REQUEST-9

Requesting: REQUEST-10

Received response for: Response to 'REQUEST-1'

Received response for: Response to 'REQUEST-2'

Received response for: Response to 'REQUEST-3'

Received response for: Response to 'REQUEST-4'

Received response for: Response to 'REQUEST-5'

Received response for: Response to 'REQUEST-6'

Received response for: Response to 'REQUEST-7'

Received response for: Response to 'REQUEST-8'

Received response for: Response to 'REQUEST-9'

Received response for: Response to 'REQUEST-10'

...

?

Note that when the client is started, 10 requests are sent to initiate the request/reply

process and 10 replies are received back from the worker. Although it’s not glorious,

the power in this simple request/reply example will become evident when you apply it

to your own business processes.

?

注意到当client启动后,发送了10个请求用于激活请求/响应进程,然后收到了来自worker的响应.

尽管这个例子算不上很辉煌,但是日后必将称为你在其他业务中实现请求/响应系统的参考.

?

Using the request/reply pattern, envision that there are thousands of requests

entering the broker every second from many clients, all distributed across many hosts.

?

使用请求/应答模式,代理将每秒钟收到的来自无数的客户端的成千上万个请求全部分发到不同的

主机中处理.

?

In a production system, more than just a single broker instance would be used for the

purposes of redundancy, failover, and load balancing. These brokers would also be

distributed across many hosts. The only way to handle this many requests would be to

use many workers. Producers can always send messages much faster than a consumer

can receive and process them, so lots of workers would be needed, all of them spread

out across many hosts as well.

?

在生产系统中,会使用更多的代理实例用于备份,失效转移以及负载均衡.这些代理也会被分布于很多

的主机上.处理如此多请求的唯一方法是使用多工作者(worker).因为消息发送者发送消息的速度

可能比消息消费者接收并处理消息的速度快的多,所以就需要大量的工作者(worker),这些工作者

同样也分布于大量的主机上.

?

The advantage of using many workers is that each one

can go up and down at will, and the overall system itself isn’t affected. The producers

and workers would continue to process messages, and even if one of them crashed, it

wouldn’t affect the system. This is exactly how many large-scale systems can handle

such a tremendous load—through the use of asynchronous messaging like that demonstrated

by the request/reply pattern.

?

使用多工作者的好处是任何的工作者都可以根据需要启用或者停用,而整个系统不会收到影响.消息生产者

和工作者会正常处理消息,即使她们当中的一些已经崩溃了,也不会影响系统运行.这正是那些大型系统可以

处理海量负载的原因--使用前文介绍过的基于请求/应答模式的异步消息系统.

?

The JMS API can be tedious, as it requires you to write a lot of code for initializing

all the necessary JMS objects such as connections, sessions, producers, consumers, and

so forth. This is where the Spring Framework provides a lot of benefit. It helps you to

remove such boilerplate code by supplying a more cogent API and by simplifying the

overall configuration.

?

JMS的API可以说是繁琐的,因为它要求开发者书写大量的初始化代码用于初始化必要的JMS对象,包括

connection, session, producer, consumer等等.使用Spring框架通过提供可靠的API来帮助开发者

移除(类似于JMS对象初始化)的哪些固定的代码,以便简化整个配置过程.这正式使用Spring框架带来

的好处.

热点排行