Bu konuda, ApsaraMQ for RocketMQ HTTP istemci SDK aracılığıyla zamanlanmış veya gecikmeli mesajların nasıl gönderileceği ve tüketileceğine ilişkin Java örnek kodları sunulmaktadır.
Zamanlanmış ve gecikmeli mesajlar arasındaki farklar
API düzeyinde zamanlanmış mesajlar ile gecikmeli mesajlar aynı özelliği kullanır. Her ikisi de teslimatı ertelemek için setStartDeliverTime yöntemini çağırır. Aralarındaki tek fark, zaman damgasının nasıl hesaplandığıdır:
| Tür | Teslimat zamanını ayarlama yöntemi | Örnek |
|---|---|---|
| Gecikmeli mesaj | Geçerli saat + ofset | System.currentTimeMillis() + 10 * 1000 (10 saniyelik gecikme) |
| Zamanlanmış mesaj | Milisaniye cinsinden mutlak Unix zaman damgası | 1654770600000 (2022-06-09 18:30:00) |
Broker, her mesajı belirtilen teslimat zamanına kadar bekletir ve ardından tüketim için serbest bırakır. Bu ayar mesaj başına yapılır; dolayısıyla her mesajın kendi teslimat zamanı olabilir.
Daha fazla bilgi için bkz. Zamanlanmış mesajlar ve gecikmeli mesajlar.
Önkoşullar
Başlamadan önce aşağıdaki adımları tamamladığınızdan emin olun:
ApsaraMQ for RocketMQ konsolunda bir örnek, bir konu ve bir tüketici grubu oluşturun
Alibaba Cloud hesabınız için bir AccessKey çifti oluşturun
Her konu yalnızca bir mesaj türünü destekler. Normal mesajlar için yapılandırdığınız bir konuyu, zamanlanmış veya gecikmeli mesajlar göndermek amacıyla yeniden kullanmayın.
Zamanlanmış veya gecikmeli mesajları gönderme
Bu örnekteki tüm mesajlar, teslimatı 10 saniye ertelemek için setStartDeliverTime yöntemini kullanır. Zamanlanmış bir mesaj göndermek için göreli ofset yerine milisaniye cinsinden mutlak bir Unix zaman damgası belirtin (örneğin, 2022-06-09 18:30:00 için 1654770600000).
import com.aliyun.mq.http.MQClient;
import com.aliyun.mq.http.MQProducer;
import com.aliyun.mq.http.model.TopicMessage;
import java.util.Date;
public class Producer {
public static void main(String[] args) {
MQClient mqClient = new MQClient(
// HTTP endpoint. Find this on the Instance Details page, in the
// Endpoints tab under Basic Information.
"<your-http-endpoint>",
// Load credentials from environment variables to avoid hardcoding secrets.
System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
);
final String topic = "<your-topic>";
// If the instance has a namespace, specify the instance ID.
// If it does not have a namespace, set this to null or "".
final String instanceId = "<your-instance-id>";
MQProducer producer;
if (instanceId != null && instanceId != "") {
producer = mqClient.getProducer(instanceId, topic);
} else {
producer = mqClient.getProducer(topic);
}
try {
for (int i = 0; i < 4; i++) {
TopicMessage pubMsg = new TopicMessage(
"hello mq!".getBytes(), // Message body
"A" // Message tag
);
pubMsg.getProperties().put("a", String.valueOf(i)); // Custom property
pubMsg.setMessageKey("MessageKey");
// Defer delivery by 10 seconds.
// For a scheduled message, use an absolute timestamp instead,
// e.g., pubMsg.setStartDeliverTime(1654770600000L);
pubMsg.setStartDeliverTime(System.currentTimeMillis() + 10 * 1000);
TopicMessage pubResultMsg = producer.publishMessage(pubMsg);
System.out.println(new Date() + " Send mq message success."
+ " Topic is:" + topic
+ ", msgId is: " + pubResultMsg.getMessageId()
+ ", bodyMD5 is: " + pubResultMsg.getMessageBodyMD5());
}
} catch (Throwable e) {
System.out.println(new Date() + " Send mq message failed. Topic is:" + topic);
e.printStackTrace();
}
mqClient.close();
}
}
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Nerede Bulunur |
|---|---|---|
<your-http-endpoint> |
HTTP uç noktası | Örnek Ayrıntıları sayfası > Endpoints sekmesi > HTTP Endpoint |
<your-topic> |
Konu adı | ApsaraMQ for RocketMQ konsolu > Topics |
<your-instance-id> |
Örnek Kimliği veya örneğin ad alanı yoksa null |
Örnek Ayrıntıları sayfası > Basic Information |
Zamanlanmış veya gecikmeli mesajları tüketme
Zamanlanmış ve gecikmeli mesajları normal mesajlarla aynı şekilde tüketin. Broker, teslimat zamanı gelene kadar mesajları bekletir ve ardından bunları tüketim için serbest bırakır.
Aşağıdaki örnekte uzun yoklama (long polling) kullanılarak mesajlar tüketilir ve broker'a onaylar (ACK'ler) gönderilir.
import com.aliyun.mq.http.MQClient;
import com.aliyun.mq.http.MQConsumer;
import com.aliyun.mq.http.common.AckMessageException;
import com.aliyun.mq.http.model.Message;
import java.util.ArrayList;
import java.util.List;
public class Consumer {
public static void main(String[] args) {
MQClient mqClient = new MQClient(
// HTTP endpoint. Find this on the Instance Details page, in the
// Endpoints tab under Basic Information.
"<your-http-endpoint>",
// The AccessKey ID for authentication.
"${ACCESS_KEY}",
// The AccessKey secret for authentication.
"${SECRET_KEY}"
);
final String topic = "<your-topic>";
final String groupId = "<your-group-id>";
// If the instance has a namespace, specify the instance ID.
// If it does not have a namespace, set this to null or "".
final String instanceId = "<your-instance-id>";
final MQConsumer consumer;
if (instanceId != null && instanceId != "") {
consumer = mqClient.getConsumer(instanceId, topic, groupId, null);
} else {
consumer = mqClient.getConsumer(topic, groupId);
}
// Consume messages in a loop. For production use, run multiple threads
// to consume messages concurrently.
do {
List<Message> messages = null;
try {
// Long polling: wait up to 3 seconds for new messages.
// - First parameter: max messages per batch (max: 16).
// - Second parameter: long polling timeout in seconds (max: 30).
messages = consumer.consumeMessage(3, 3);
} catch (Throwable e) {
e.printStackTrace();
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
if (messages == null || messages.isEmpty()) {
System.out.println(Thread.currentThread().getName()
+ ": no new message, continue!");
continue;
}
// Process messages
for (Message message : messages) {
System.out.println("Receive message: " + message);
}
// ACK consumed messages. If the broker does not receive an ACK
// before the retry interval elapses, the message is redelivered.
{
List<String> handles = new ArrayList<String>();
for (Message message : messages) {
handles.add(message.getReceiptHandle());
}
try {
consumer.ackMessage(handles);
} catch (Throwable e) {
if (e instanceof AckMessageException) {
AckMessageException errors = (AckMessageException) e;
System.out.println("Ack message fail, requestId is:"
+ errors.getRequestId() + ", fail handles:");
if (errors.getErrorMessages() != null) {
for (String errorHandle : errors.getErrorMessages().keySet()) {
System.out.println("Handle:" + errorHandle
+ ", ErrorCode:" + errors.getErrorMessages().get(errorHandle).getErrorCode()
+ ", ErrorMsg:" + errors.getErrorMessages().get(errorHandle).getErrorMessage());
}
}
continue;
}
e.printStackTrace();
}
}
} while (true);
}
}
Aşağıdaki yer tutucuları gerçek değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Nerede Bulunur |
|---|---|---|
<your-http-endpoint> |
HTTP uç noktası | Örnek Ayrıntıları sayfası > Endpoints sekmesi > HTTP Endpoint |
${ACCESS_KEY} |
Kimlik doğrulama için AccessKey kimliği | Bkz. AccessKey çifti oluşturma |
${SECRET_KEY} |
Kimlik doğrulama için AccessKey gizli anahtarı | Bkz. AccessKey çifti oluşturma |
<your-topic> |
Konu adı | ApsaraMQ for RocketMQ konsolu > Topics |
<your-group-id> |
Tüketici grubu kimliği | ApsaraMQ for RocketMQ konsolu > Groups |
<your-instance-id> |
Örnek Kimliği veya örneğin ad alanı yoksa null |
Örnek Ayrıntıları sayfası > Basic Information |
Sonraki adımlar
Zamanlanmış mesajlar ve gecikmeli mesajlar: Zamanlanmış ve gecikmeli mesajların yaşam döngüsünü, teslimat kurallarını ve sınırlamalarını öğrenin.
Normal mesajları gönderme ve alma: Herhangi bir gecikme olmadan hemen teslim edilen mesajlar gönderin.