JMS仕様とメッセージ特性(1)

JMS仕様とは何ですか

它是JavaEE体系中的一项Message Service

一般的なメッセージミドルウェアの比較

JMSの構成と特性

JMSプロバイダー

实现jms接口的消息中间件

JMSプロデューサー、JMSコンストマー


JMSメッセージヘッダー

1)jms destination 消息目的地 队列或者主题
2)jms deviverymode 持久化方式
3)jms expiration 消息过期时间 
4)jms 优先级 1到4是普通消息  5-9是加急消息
5)消息id  唯一识别每个消息的标识,是有MQ自己生成
メッセージヘッダーの宛先

ここに画像の説明を挿入
もちろん、メッセージで設定することもできます
ここに画像の説明を挿入

4つのオーバーロード:宛先、メッセージ、優先度、存続時間、永続化するかどうか
。メッセージの宛先:キューとトピック

永続性
ここに画像の説明を挿入
メッセージの有効期限がデフォルトで期限切れになることはありません

消息体

发送的消息类型有哪些:
StringMessage MapMessage ByteMessage StringMessage ObjectMessage 五中类型

要求:发送的消息体和接受的消息体要求类型一致。

ここに画像の説明を挿入
要件:送信されたメッセージ本文と受信されたメッセージ本文には同じタイプが必要です。
ここに画像の説明を挿入

カスタムメッセージ属性

自定义的消息属性能有什么还用呢 ?
去重、识别、重点标注等	

TextMessage textMessage = session.createTextMessage("myTopic……"+ i );
messageProducer.send(textMessage);
textMessage.setStringProperty("自定义消息的key", "自定义消息的value");

メッセージの信頼性を確保するにはどうすればよいですか?

消息的可靠性可以从以下四个方面来回答:
1)消息的持久性
2)消息的事务特性
3)消息的签收机制
4)消息持久化

(キュー)メッセージの永続性

ここに画像の説明を挿入
検証1:
メッセージを非永続に設定し、メッセージを生成して(サーバーはシャットダウンされません)、メッセージを消費します。
ここに画像の説明を挿入
メッセージは通常消費されます。
ここに画像の説明を挿入
検証2:
メッセージを非永続に設定します次に、メッセージを生成し(サーバーが閉じている)、それを消費します。メッセージ
生成メッセージ
ここに画像の説明を挿入
サーバーを閉じた後、メッセージを消費します。
ここに画像の説明を挿入
メッセージは失われ、消費できません。
生成されたばかりのメッセージは失われます。
ここに画像の説明を挿入
検証3:メッセージを永続的に設定してから、メッセージを生成します。これは、生成されたばかりのメッセージです。
ここに画像の説明を挿入
メッセージサーバーをシャットダウンし、メッセージを再起動
ここに画像の説明を挿入
します。メッセージはまだ存在しており、メッセージを消費します。メッセージは正常に消費されました
ここに画像の説明を挿入
ここに画像の説明を挿入

(トピック)メッセージの持続性

トピックメッセージの場合、永続性はあまり意味がありません。トピックモードでは、最初にコンシューマーを起動してからプロデューサーを起動する必要があるためです。メッセージの永続性が設定されているが、コンシューマーが起動されていない場合、これらのメッセージは失われ、消費者が消費することはできません

永続トピックジェネレータを設定する

package com.ttzz.activemq;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ActiveMQProduceByTopic {
    
    
	public static String url = "tcp://localhost:61616";
	public static String topicName = "myTopic";
	
	public static void main(String[] args) throws JMSException {
    
    
		//1.获取工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);
		//2. 创建连接
		Connection connection = activeMQConnectionFactory.createConnection();
		
		//3.创建会话
		// 第一个参数 是否开启开启事务
		// 第二个参数 是签收模式
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		//4. 创建目的地 Topic 
		Topic topic =session.createTopic(topicName);
		//5. 创建生产者
		MessageProducer messageProducer = session.createProducer(topic);
		
		messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
		connection.start();
		//6. 发送消息
		for (int i = 0; i < 4; i++) {
    
    
			TextMessage textMessage = session.createTextMessage("myTopic……"+ i );
			textMessage.setStringProperty("自定义消息的key", "自定义消息的value");
			messageProducer.send(textMessage);
		}
		//关闭资源
		messageProducer.close();
		session.close();
		connection.close();
		System.out.println("OOKK");
	}
}

トピック消費者

package com.ttzz.activemq;

import java.io.IOException;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ActiveMQConsumerByTopic {
    
    
	public static String url = "tcp://localhost:61616";
	public static String topicName = "myTopic";

	public static void main(String[] args) throws JMSException, IOException {
    
    
		// 1.获取工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);
		// 2. 创建连接
		Connection connection = activeMQConnectionFactory.createConnection();
		
		connection.setClientID("消费者1");
		System.out.println("topic消费者1");
		
		// 3.创建会话
		// 第一个参数 是否开启开启事务
		// 第二个参数 是签收模式
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 4. 创建目的地Topic
		Topic topic = session.createTopic(topicName);
		// 5. 创建消费者
		TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "remark..."); // 创建持久化的订阅

		connection.start();

		Message message = topicSubscriber.receive();
		while (message != null) {
    
    
			TextMessage textMessage = (TextMessage) message;
			System.out.println(textMessage.getText());
			message = topicSubscriber.receive();
		}

		session.close();
		connection.close();
		System.out.println("OOKK2");
	}
}

検証1:コンシューマーの開始
ここに画像の説明を挿入
ここに画像の説明を挿入
アクティブな耐久性のあるトピックサブスクライバー:アクティブ状態の
永続的なトピックコンシューマーオフラインの永続的なトピックサブスクライバー:オフライン状態の永続的なトピックコンシューマー
永続的なトピックジェネレーターの開始:
トピックコンシューマーがメッセージを消費する
ここに画像の説明を挿入
メッセージサーバー
ここに画像の説明を挿入
ここに画像の説明を挿入
検証2:コンシューマー1をオフにしてコンシューマー2を開始するそして
ここに画像の説明を挿入
消費者1がオフラインで、プロデューサーの消費を開始する。
ここに画像の説明を挿入
消費者2が正常にメッセージを消費することができます。
ここに画像の説明を挿入
[スタート]消費者1を再び、そして消費者1は、通常、メッセージを消費することができます。
ここに画像の説明を挿入
ここに画像の説明を挿入

メッセージのトランザクション特性

取引は主に生産者向けであり、署名は主に消費者向けです

	//3.创建会话
	// 第一个参数 是否开启开启事务
	// 第二个参数 是签收模式
	Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

検証1:
トランザクションがfalseに設定され、メッセージがサーバーに自動的に送信されます。
ここに画像の説明を挿入
ここに画像の説明を挿入
メッセージの永続性が設定されているため、サーバーがシャットダウンされて再起動されますが、メッセージは引き続き存在します。

検証2:
トランザクションがtrueに設定され、メッセージの実行が送信され、
ここに画像の説明を挿入

サーバーがメッセージを受信するかどうかを確認します。送信されたばかりのメッセージはサーバーから受信されませんでした。メッセージコミット操作がないため、
ここに画像の説明を挿入
トランザクションコミットされ、
ここに画像の説明を挿入
メッセージがキューに入れられ、
ここに画像の説明を挿入
トランザクションが複数のメッセージに対して同時に送信されます。これにより、
session.rollback()のアトミック性が保証されます。

必要性を確認するために、再起動する必要がある場合は、永続的なメッセージを削除してください

操作:構成ファイルactivemq.xmlのブローカーフィールドにdeleteAllMessagesOnStartup = "true"を追加し
ここに画像の説明を挿入
ここに画像の説明を挿入
て、永続メッセージが削除されていることを確認します。

プロデューサートランザクションを開始し、メッセージをメッセージサーバーに送信します。メッセージを
ここに画像の説明を挿入
見ると、
ここに画像の説明を挿入
コンシューマーはメッセージを消費します。
ここに画像の説明を挿入
コンシューマーを再度開始し、メッセージが消費されたことを確認して、メッセージを再消費できないことを示します。
ここに画像の説明を挿入
検証2:トランザクションを開始するようにコンシューマーを設定しますが、送信トランザクションはありません[メッセージは繰り返し消費されます]。コンシューマー1は初めてメッセージを正常に消費します
ここに画像の説明を挿入
が、サーバー上でメッセージが消費されていないことを確認します。
ここに画像の説明を挿入
別のコンシューマーを再起動して、メッセージが複数回消費される可能性があることを確認します。
ここに画像の説明を挿入

面白い現象

プロデューサーは、トランザクション方式でプロデューサーをサーバーに送信します。
コンシューマーは、消費のためにトランザクション開始しますが、トランザクションはコミットされません。コントロールが破壊されないことを確認してください。再び消費者2号を始めたのですが、繰り返し消費できないのでしょうか?
ここに画像の説明を挿入
ここに画像の説明を挿入
コンシューマーを4秒間設定した後、(remove:System.in.read();)の場合、メッセージは表示されず、自動的に閉じられます。コンシューマーNo.2がアクティブになり、繰り返し使用できます。
理由?ハハハッハッハ

おすすめ

転載: blog.csdn.net/weixin_39472101/article/details/114993631