I. Giao dịch của Thông điệp
1. Nhà sản xuất
a. Nhà sản xuất không sử dụng giao dịch
public class JmsQueueProducer {
public static final String BROKER_URL = "tcp://192.168.229.129:61616";
public static final String QUEUE_NAME = "queue01";
public static final String TEXT_MESSAGE_NAME = "textMessage";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = connectionFactory.createConnection();
connection.start();
// Hai tham số transacted=giao dịch, acknowledgeMode=xác nhận
// Nếu nhà sản xuất không sử dụng giao dịch, tức là transacted=false,
// thì tham số thứ hai chỉ cần phù hợp với quy tắc truyền tham số, thông điệp sẽ được gửi đến máy chủ MQ
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageProducer producer = session.createProducer(queue);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
for (int i = 1; i < 4; i++) {
TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i);
producer.send(queue, textMessage);
}
// Giải phóng tài nguyên
producer.close();
session.close();
connection.close();
System.out.println("Nhà sản xuất đã gửi thông điệp đến MQ QUEUE......");
}
}
Tham số thứ hai là kiểu int, các giá trị hợp lệ bao gồm:
- Session.SESSION_TRANSACTED
- Session.AUTO_ACKNOWLEDGE
- Session.CLIENT_ACKNOWLEDGE
- Session.DUPS_OK_ACKNOWLEDGE
Nếu đặt acknowledge thành một số nguyên 5, chương trình sẽ báo lỗi:
Exception in thread "main" javax.jms.JMSException: invalid acknowledgeMode: 5.
Giá trị hợp lệ là
Session.AUTO_ACKNOWLEDGE (1),
Session.CLIENT_ACKNOWLEDGE (2),
Session.DUPS_OK_ACKNOWLEDGE (3),
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE (4)
hoặc cho các phiên giao dịch Session.SESSION_TRANSACTED (0)
b. Nhà sản xuất sử dụng giao dịch
public class JmsQueueProducer {
public static final String BROKER_URL = "tcp://192.168.229.129:61616";
public static final String QUEUE_NAME = "queue01";
public static final String TEXT_MESSAGE_NAME = "textMessage";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageProducer producer = session.createProducer(queue);
try {
for (int i = 1; i < 11; i++) {
TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i);
producer.send(queue, textMessage);
if(i<=5){
session.commit();
}else{
session.rollback();
}
}
System.out.println("Nhà sản xuất đã gửi thông điệp thành công đến MQ QUEUE......");
} catch (Exception e) {
System.out.println("Nếu xảy ra ngoại lệ, thông điệp sẽ được hoàn tác");
session.rollback();
} finally {
// Giải phóng tài nguyên
producer.close();
session.close();
connection.close();
}
}
}
Tóm tắt:
- Khi nhà sản xuất không sử dụng giao dịch, chỉ cần gọi phương thức send(), thông điệp sẽ được gửi đến hàng đợi, nó tự động thực hiện commit(). Tham số thứ hai chỉ cần là một giá trị hợp lệ.
- Khi nhà sản xuất sử dụng giao dịch, gọi phương thức send() không đủ để gửi thông điệp đến máy chủ MQ, cần phải gọi session.commit() để xác nhận. Nếu có ngoại lệ, sử dụng session.rollback() để hoàn tác. Đối với nhà sản xuất, mức độ giao dịch quan trọng hơn xác nhận thông điệp, do đó tham số thứ hai có thể bỏ qua.
- Nhà sản xuất quan tâm đến giao dịch hơn là xác nhận thông điệp, nên tham số thứ hai thường được đặt là AUTO_ACKNOWLEDGE.
2. Người tiêu thụ
a. Người tiêu thụ không sử dụng giao dịch, tự động xác nhận, chỉ có thể tiêu thụ thông điệp một lần.
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
b. Người tiêu thụ sử dụng giao dịch, tự động xác nhận và gọi commit() thủ công, thông điệp chỉ được tiêu thụ một lần, đảm bảo tính đáng tin cậy.
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
session.commit();
II. Cơ chế Xác nhận Thông điệp
Cơ chế xác nhận thông điệp chủ yếu đối với người tiêu thụ, nhà sản xuất chỉ quan tâm đến việc gửi thông điệp.
- Khi người tiêu thụ không sử dụng giao dịch, tự động xác nhận, họ có thể tiêu thụ thông điệp một lần mà không bị lặp lại.
- Khi người tiêu thụ sử dụng giao dịch, tự động xác nhận, phải gọi commit() thủ công, nếu không thông điệp sẽ bị lặp lại.
- Khi người tiêu thụ không sử dụng giao dịch, xác nhận thủ công, phải gọi message.acknowledge() để xác nhận, nếu không thông điệp sẽ bị lặp lại.
- Khi người tiêu thụ sử dụng giao dịch, xác nhận thủ công, chỉ gọi message.acknowledge(), thông điệp sẽ bị lặp lại.
- Khi người tiêu thụ sử dụng giao dịch, xác nhận thủ công, chỉ gọi commit(), thông điệp sẽ không bị lặp lại.
- Khi người tiêu thụ sử dụng giao dịch, xác nhận thủ công, gọi cả commit() và acknowledge(), thông điệp sẽ không bị lặp lại.
Tóm tắt:
- Nhà sản xuất chỉ quan tâm đến giao dịch, cơ chế xác nhận thông điệp không quan trọng.
- Nếu nhà sản xuất không sử dụng giao dịch, đặt xác nhận là Session.AUTO_ACKNOWLEDGE.
- Nếu nhà sản xuất sử dụng giao dịch, đặt xác nhận là AUTO_ACKNOWLEDGE và gọi session.commit().
- Người tiêu thụ quan tâm đến cơ chế xác nhận, thường không sử dụng giao dịch. Nếu tự động xác nhận, không cần làm gì, nếu xác nhận thủ công, gọi message.acknowledge().
- Nếu người tiêu thụ sử dụng giao dịch, cần gọi session.commit().
- Nếu người tiêu thụ sử dụng giao dịch và xác nhận thủ công, chỉ cần mở giao dịch để tránh lặp lại thông điệp.
- Để tránh lỗi, khi người tiêu thụ sử dụng giao dịch, gọi session.commit(), tự động xác nhận gọi acknowledge.