Sıralı mesajlar kesin ilk giren ilk çıkar (FIFO) düzeninde iletilir ve tüketilir. Bu konu, Apache RocketMQ Java SDK kullanarak TCP üzerinden sıralı mesaj göndermek ve almak için Java örnek kodları sunar.
Sıralı mesajların çalışma mantığı
Sıralı mesajlar parça anahtarı ile bölümlere ayrılır. Her parça anahtarı özel bir parçaya eşlenir ve bu parça içindeki mesajlar gönderildikleri sırayla iletilir.
Bu davranışı yöneten üç kural şunlardır:
Parça bazında sıralama -- Aynı parça anahtarını paylaşan mesajlar her zaman FIFO düzeninde iletilir.
Parçalar arasında sıralama yok -- Farklı parça anahtarlarına sahip mesajlar birbirlerine göre herhangi bir sırada gelebilir.
Parça anahtarı zorunludur -- Her sıralı mesaj bir parça anahtarı içermelidir. Bu anahtar, aramalar için kullanılan genel mesaj anahtarından bağımsızdır.
İş gereksinimlerinize uygun sıralama modeli oluşturmak için parça anahtarlarını kullanın. Örneğin, parça anahtarını sipariş kimliği olarak ayarlayarak aynı siparişe ait tüm mesajların sırayla işlenmesini, farklı siparişlere ait mesajların ise paralel olarak işlenmesini sağlayabilirsiniz.
Sıralama semantiği ve kısıtlamaları hakkında daha fazla bilgi için bkz. Sıralı mesajlar.
Ön koşullar
Başlamadan önce aşağıdakilere sahip olduğunuzdan emin olun:
Java 1.2.7 veya sonraki bir sürüm için SDK. Bkz. Sürüm notları
Hazırlanmış bir ortam. Bkz. Ortamı hazırlama
(İsteğe bağlı) Yapılandırılmış günlük kaydı ayarları. Bkz. Günlük kaydı ayarları
ApsaraMQ for RocketMQ konusunda yeniyseniz, mesaj gönderip almadan önce çalışan bir proje kurmak için demo projesi ile başlayın.
Sıralı mesaj gönderme
Sıralama garantisi
Broker, gönderenin mesajları göndermek için tek bir üretici veya iş parçacığı kullandığı sıraya göre mesaj sırasını belirler. Birden çok üretici veya iş parçacığı eş zamanlı olarak mesaj gönderirse broker bunları varış zamanına göre sıralar; bu sıra, amaçlanan iş sırasından farklı olabilir.
Örnek kod
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Örnek |
|---|---|---|
<your-group-id> |
ApsaraMQ for RocketMQ konsolunda oluşturulan Grup Kimliği | GID_order_group |
<your-access-key> |
Kimlik doğrulama için AccessKey ID | LTAI5tXxx |
<your-secret-key> |
Kimlik doğrulama için AccessKey secret | xXxXxXx |
<your-tcp-endpoint> |
Instance Details sayfasındaki TCP Endpoint bölümünden alınan TCP uç noktası | http://MQ_INST_xxx.mq-internet-access.mq-internet.aliyuncs.com:80 |
Tam kod için bkz. ApsaraMQ for RocketMQ kod deposu.
package com.aliyun.openservices.ons.example.order;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.order.OrderProducer;
import java.util.Date;
import java.util.Properties;
public class ProducerClient {
public static void main(String[] args) {
Properties properties = new Properties();
// Group ID created in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.GROUP_ID, "<your-group-id>");
// AccessKey ID for authentication.
properties.put(PropertyKeyConst.AccessKey, "<your-access-key>");
// AccessKey secret for authentication.
properties.put(PropertyKeyConst.SecretKey, "<your-secret-key>");
// TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");
OrderProducer producer = ONSFactory.createOrderProducer(properties);
// Call start() once before sending any messages.
producer.start();
for (int i = 0; i < 1000; i++) {
String orderId = "biz_" + i % 10;
Message msg = new Message(
// Topic for ordered messages.
"Order_global_topic",
// Tag for filtering on the broker side.
"TagA",
// Message body in binary format.
// Producer and consumer must agree on serialization and deserialization.
"send order global msg".getBytes()
);
// Message key -- a business identifier, ideally globally unique.
// Use this key to look up the message in the ApsaraMQ for RocketMQ console.
msg.setKey(orderId);
// Sharding key -- determines the partition for ordered delivery.
// Messages with the same sharding key are delivered in FIFO order.
String shardingKey = String.valueOf(orderId);
try {
SendResult sendResult = producer.send(msg, shardingKey);
if (sendResult != null) {
System.out.println(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMessageId());
}
} catch (Exception e) {
// Handle failure: retry or persist the message for later resend.
System.out.println(new Date() + " Send mq message failed. Topic is:" + msg.getTopic());
e.printStackTrace();
}
}
// Shut down the producer before exiting.
// Skip this if the producer sends messages frequently.
producer.shutdown();
}
}
Sıralı mesaj alma
Yeniden deneme davranışı
Bir sıralı mesaj tüketilemediğinde broker, mevcut mesaj başarıyla işlenene veya maksimum yeniden deneme sayısına ulaşana kadar aynı parçadaki sonraki tüm mesajları engeller. Bu engelleme davranışı FIFO sıralamasını korur ancak parçadaki diğer mesajların işlenmesini geciktirebilir.
Yeniden deneme davranışını iki parametre kontrol eder:
| Parametre | Açıklama | Geçerli değerler |
|---|---|---|
SuspendTimeMillis |
Başarısız olan bir sıralı mesaj için yeniden denemeler arasındaki bekleme süresi (milisaniye) | 10 -- 30.000 |
MaxReconsumeTimes |
Mesaj atlanmadan önceki maksimum yeniden deneme sayısı | Tamsayı (örneğin, 20) |
Bu değerleri işleme gecikmelerine karşı toleransınıza göre ayarlayın. Daha düşük bir SuspendTimeMillis değeri daha hızlı yeniden deneme yapar ancak broker yükünü artırır. Daha düşük bir MaxReconsumeTimes değeri parçanın engellemesini daha erken kaldırır ancak daha fazla deneme ile başarılı olabilecek mesajların atlanmasına neden olabilir.
Örnek kod
Aşağıdaki örnek kod, üretici örneği ile aynı yer tutucuları kullanır. Kodu çalıştırmadan önce bunları gerçek değerlerinizle değiştirin.
package com.aliyun.openservices.ons.example.order;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.order.ConsumeOrderContext;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import com.aliyun.openservices.ons.api.order.OrderAction;
import com.aliyun.openservices.ons.api.order.OrderConsumer;
import java.util.Properties;
public class ConsumerClient {
public static void main(String[] args) {
Properties properties = new Properties();
// Consumer group ID created in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.GROUP_ID, "<your-group-id>");
// AccessKey ID for authentication.
properties.put(PropertyKeyConst.AccessKey, "<your-access-key>");
// AccessKey secret for authentication.
properties.put(PropertyKeyConst.SecretKey, "<your-secret-key>");
// TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");
// Wait time (ms) before retrying a failed ordered message. Valid values: 10 to 30,000.
properties.put(PropertyKeyConst.SuspendTimeMillis, "100");
// Maximum retry attempts for a failed message.
properties.put(PropertyKeyConst.MaxReconsumeTimes, "20");
OrderConsumer consumer = ONSFactory.createOrderedConsumer(properties);
consumer.subscribe(
// Topic to subscribe to.
"Order_global_topic",
// Tag filter expression:
// "*" -- subscribe to all tags
// "TagA || TagB || TagC" -- subscribe to TagA, TagB, or TagC only
"*",
new MessageOrderListener() {
/**
* Return OrderAction.Success after processing the message.
* Return OrderAction.Suspend if processing fails or throws
* an exception -- the broker will retry after SuspendTimeMillis.
*/
@Override
public OrderAction consume(Message message, ConsumeOrderContext context) {
System.out.println(message);
return OrderAction.Success;
}
});
// Call start() once to begin consuming.
consumer.start();
}
}
Sonraki adımlar
Sıralı mesajlar kavramları ve kısıtlamaları hakkında bilgi edinin.
Ek örnekler için ApsaraMQ for RocketMQ kod deposunu inceleyin.