ActiveMq,一

ActiveMQ
面向消息的中间件(Message Oriented Middleware,MOM):
发送者将消息发送给消息服务器,消息服务器将消息存放在若干队列中,在合适的时候,再将消息转发给接收者。
这种模式下,发送和接收是异步的,发送者无需等待,二者的生命周期未必相同。发送消息的时候接收者不一定运行,接收
消息的时候,发送者也不一定运行。一对多通信:对于一个消息可以有多个接收者。

JAVA消息服务(JMS) 定义了Java中访问消息中间件的接口。JMS只是接口,并没有给予实现,实现JMS接口的消息中间件称为
JMS Provider,已有的MOM系统有ActiveMQ,RabbitMQ,RocketMQ等,基本遵循JMS规范。

pub/sub publish/subscribe,即发布/订阅的消息模型。对于订阅了某个主题的接收方,在发送方发送消息的时候,接收方,就可以收到消息。
Topic 主题目标

PTP point to point,即点对点的消息模型, 发送方将消息发送到队列中,接收方从队列读取信息。
Queue 队列目标

Session
Session是我们对消息进行操作的接口,可以通过 session 创建生产者、消费者、消息等。
Session 提供了事务的功能,如果需要使用 session 发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。

ActiveMQ安全机制:
activemq管控台使用jetty部署,所以需要修改密码则需要到相应的配置文件:
apache-activemq-5.11.1\conf\jetty-realm.properties
activemq应该设置有安全机制,只有符合认证的用户才能进行发送和获取消息,所以我们也可以在activemq.xml里去添加安全验证配置。
apache-activemq-5.11.1\conf\activemq.xml
123行后,添加插件。设置特定用户才能进行发送,接收消息。






注意:
Connection方法创建连接,使用完后必须关闭连接(节约资源,提高mq反应速度)

Session方法使用:
一旦从ConnectionFactory中获得一个Connection,必须从Connection中创建一个或者多个Session。Session是一个发送
或者接收消息的线程,可以使用Session创建MessageProducer,MessageConsumer和Message.

Session createSession(boolean transacted,int acknowledgeMode);
其中transacted为使用事务标识,acknowledgeMode为签收模式。
结束事务有两种方法:
提交或者回滚。当一个事务提交,消息被处理。如果事务中有一个步骤失败,事务就回滚,这个事务
中的已执行的动作将被撤销。在发送消息最后也必须要使用session.commit()方法表示提交事务。

签收模式有三种形式:(作用:确保消息被正确消费)
	Session.AUTO_ACKNOWLEDGE当客户端从receive或onMessage成功返回时,Session自动签收客户端的这条消息的收条。
	Session.CLIENT_ACKNOWLEDGE,客户端确认模式,由消费端自行调用方法,进行确认。(工作常用,消息消费出现异常时,可以使消息依旧在队列中存在)

ActiveMQ:无法保证消息发送时的顺序性。(优先级属性无法确保消息的顺序性)
消费:先进先出

示例:
生成者

package thead.demo.synchronizeddemo.activemq.a;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Sender {
public static void main(String[] args) throws Exception{
//1 建立ConnectionFactory工厂对象,需要填入用户名,密码,以及要连接的地址,均使用默认即可。
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory(
“bhz”,
“bhz”,
“tcp://localhost:61616”
);
//2通过ConnecttionFactory工厂对象我们创建一个Connection连接,并且调用Connecttion的start方法开启连接,Connection默认是关闭的。
Connection connection=connectionFactory.createConnection();
connection.start();
//3通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用事务,参数配置2为签收模式。一般我们设置为自动签收
//Session session=connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
//使用事务进行消息发送
//Session session=connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);

    //签收模式:指消息是否被正确消费,的回调确认机制。
    // Session.AUTO_ACKNOWLEDGE,常用模式,在消息被消费时,自动进行回调确认(由消费端,自动启动一个线程,通知MQ服务,此条消息已被消费)
    // Session.CLIENT_ACKNOWLEDGE,客户端确认模式,由消费端自行调用方法,进行确认
    Session session=connection.createSession(Boolean.TRUE,Session.CLIENT_ACKNOWLEDGE);
    //4通过Session创建Destination对象,指的是一个客户端用于指定生产消息目标和消费消息来源的对象。
    // PTP模式中,Destination为Queue
    // 发布/订阅模式中,Destination为主题,Topic
    // 在程序中可以使用多个Queue和Topic
    Destination destination=session.createQueue("queue1");
    //5我们需要通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer/MessageConsumer
    //MessageProducer messageProducer=session.createProducer(destination);
    MessageProducer messageProducer=session.createProducer(null);
    //6我们可以使用MessageProducer的setDeliveryMode方法为其设置持久化特性和非持久化特性(DeliveryMode),我们稍后详细介绍
    //messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    //7最后我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据。MessageConsumer的receive方法接收数据。
    for(int i=1;i<=5;i++){
        TextMessage textMessage=session.createTextMessage();
        textMessage.setText("我是消息内容,id为:"+i);
        //messageProducer.send(textMessage);
        // 消息发送目的地
        // 消息
        // 是否持久化
        // 优先级(0-9,0-4表示普通,5-9表示加急,默认为4
        // 消息在mq上存放有效期
        messageProducer.send(destination,textMessage,DeliveryMode.NON_PERSISTENT,i,1000*60*2);
        System.out.println("生产者:"+textMessage.getText());
    }

    //使用事务发送消息Boolean.TRUE,必须提交才能将消息发送到队列中(确保消息发送到队列时,要么全部成功,要么都不发送)
    session.commit();

    //发送消息完成,关闭连接
    if(connection!=null){
        connection.close();
    }

}

}

消费者
package thead.demo.synchronizeddemo.activemq.a;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Receiver {
public static void main(String[] args) throws Exception {
//1 建立ConnectionFactory工厂对象,需要填入用户名,密码,以及要连接的地址,均使用默认即可。
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory(
“bhz”,
“bhz”,
“tcp://localhost:61616”
);
//2通过ConnecttionFactory工厂对象我们创建一个Connection连接,并且调用Connecttion的start方法开启连接,Connection默认是关闭的。
Connection connection=connectionFactory.createConnection();
connection.start();
//3通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用事务,参数配置2为签收模式。一般我们设置为自动签收
Session session=connection.createSession(Boolean.FALSE,Session.CLIENT_ACKNOWLEDGE);
//4通过Session创建Destination对象,指的是一个客户端用于指定生产消息目标和消费消息来源的对象。
// PTP模式中,Destination为Queue
// 发布/订阅模式中,Destination为主题,Topic
Destination destination=session.createQueue(“queue1”);
//5我们需要通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer/MessageConsumer
MessageConsumer messageConsumer=session.createConsumer(destination);
//7最后我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据。MessageConsumer的receive方法接收数据。
while (true){
//receive()无参形式,执行接收端,当队列没有数据,则阻塞在这里。
TextMessage message=(TextMessage)messageConsumer.receive();
//手工去签收消息,另起一个线程(TCP)去通知我们的MQ服务,确认签收
message.acknowledge();
if(message==null)break;
System.out.println(“收到的内容:”+message.getText());
}
//接收消息完成,关闭连接
if(connection!=null){
connection.close();
}
}
}

<div class="post-text" itemprop="text"> <p>I am trying to write a simple string message to an ActiveMQ queue:</p> <pre class="lang-py prettyprint-override"><code>def write_to_amq(message, host_name, port, queue): conn = BlockingConnection(f'{host_name}:{port}') sender = conn.create_sender(queue) sender.send(Message(body='message')) conn.close() </code></pre> <p>The message gets to the queue just fine, but it appears to have some binary data in it when I view it on the ActiveMQ web UI. It reports the contents as <code>SpESsESw�message</code>. I was expecting the contents to just be <code>message</code></p> <h2>[Additional data point]</h2> <p>I am also seeing this in a separate Go program I have written using the <code>pack.ag/amqp</code> package. </p> <pre><code>func (s *amqpSender) SendResult(data string) error { session, err := s.client.NewSession() if err != nil { return fmt.Errorf("failure creating AMQP session: %s", err) } ctx := context.Background() sender, err := session.NewSender( amqp.LinkTargetAddress(s.workQueueName), ) if err != nil { return fmt.Errorf("failure creating sender link: %s", err) } ctx, cancel := context.WithTimeout(ctx, s.timeout) defer func() { cancel() sender.Close(ctx) }() err = sender.Send(ctx, amqp.NewMessage([]byte(data))) if err != nil { return fmt.Errorf("failure sending message: %s", err) } return nil } </code></pre> <p>When I send a different message to ActiveMQ, I get similar behavior, seeing <code>Su�vMy message</code> in the ActiveMQ Message Details. Could this just be a web UI anomaly?</p> </div>
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页