Mesaj filtreleme, ApsaraMQ for RocketMQ broker'ının yalnızca belirli koşulları karşılayan mesajları tüketicilere iletmesini sağlar. Üreticiler nitelikler ayarlayarak mesajları sınıflandırır; tüketiciler ise abone olurken filtre koşullarını belirtir. Broker her mesajı bu koşullara göre değerlendirir ve yalnızca eşleşen mesajları iletir.
Bir tüketici bir konuya filtre koşulu belirtmeden abone olursa, o konudaki tüm mesajları alır; bu mesajlara atanmış niteliklerin ne olduğu önemli değildir.
Filtreleme yöntemleri
ApsaraMQ for RocketMQ iki filtreleme yöntemi destekler.
| Yöntem | Açıklama | Ne zaman kullanılır? | Örnek gereksinimi | Protokol gereksinimi |
|---|---|---|---|---|
| Etiket tabanlı filtreleme (varsayılan) | Üretici tarafında her mesaja bir etiket atayın. Tüketici tarafında hangi etiketlerin alınacağını belirtin. Broker, etiketi abonelikle eşleşen mesajları iletir. | Tek bir niteliğe göre filtreleme gerektiğinde. Her mesaj için yalnızca bir etiket. | Yok | Yok |
| Nitelik tabanlı SQL filtreleme | Her mesaja birden fazla özel nitelik atayın. Tüketici tarafında nitelik değerlerine göre filtrelemek için SQL ifadeleri tanımlayın. | Karmaşık koşullarla birden fazla niteliğe göre filtreleme gerektiğinde. | Yalnızca Enterprise Platinum Edition | Yalnızca TCP istemci SDK'sı |
Etiket tabanlı filtreleme
Etiket, bir konu içindeki mesajları sınıflandıran bir etikettir. Üretici, göndermeden önce her mesaja bir etiket atar. Tüketici ise belirli etiketlere dayalı olarak mesajlara abone olur.
Örnek senaryo
Bir e-ticaret işlem sisteminde üç tür mesaj üretilir:
Sipariş mesajları
Ödeme mesajları
Lojistik mesajları
Bu mesajlar Trade_Topic adlı bir konuya gönderilir. Dört alt sistem bu konuya abonedir:
Ödeme sistemi: yalnızca ödeme mesajlarına abone olur.
Lojistik sistemi: yalnızca lojistik mesajlarına abone olur.
İşlem başarı oranı analiz sistemi: sipariş ve ödeme mesajlarına abone olur.
Gerçek zamanlı hesaplama sistemi: tüm mesajlara abone olur.

Etiket tabanlı filtrelemeyi yapılandırma
Filtreleme mantığını ApsaraMQ for RocketMQ istemci SDK'sında tanımlayın. Göndermeden önce mesajlarda etiketleri ayarlayın ve tüketici tarafında hangi etiketlere abone olunacağını belirtin. SDK ayrıntıları için bkz. Genel Bakış.
Etiketli mesaj gönderme
Her mesajı göndermeden önce bir etiket belirtin:
Message msg = new Message("MQ_TOPIC","TagA","Hello MQ".getBytes());
Tüm mesajlara abone olma
Bir konudaki tüm mesajlara abone olmak için yıldız işareti (*) kullanın:
consumer.subscribe("MQ_TOPIC", "*", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
Belirli bir etikete sahip mesajlara abone olma
Yalnızca eşleşen mesajları almak için etiketi belirtin:
consumer.subscribe("MQ_TOPIC", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
Birden çok etikete sahip mesajlara abone olma
Birden çok etiketi iki dikey çubukla (||) ayırın:
consumer.subscribe("MQ_TOPIC", "TagA||TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
Yanlış: Aynı konuya birden çok abonelik
Bir tüketici aynı konu için farklı etiketlerle birden çok kez consumer.subscribe() çağrısı yaparsa yalnızca son abonelik geçerli olur. Önceki abonelikler geçersiz kılınır.
// The consumer receives only messages with TagB. Messages with TagA are NOT received.
consumer.subscribe("MQ_TOPIC", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
consumer.subscribe("MQ_TOPIC", "TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
Nitelik tabanlı SQL filtreleme
Nitelik tabanlı SQL filtreleme, üreticilerin her mesaja birden fazla özel nitelik atamasına olanak tanır. Tüketiciler, bu niteliklere göre mesajları filtrelemek için SQL ifadeleri tanımlar. Broker her mesajı SQL ifadesine göre değerlendirir ve yalnızca eşleşen mesajları iletir.
Etiket, özel bir mesaj niteliği türüdür. Nitelik tabanlı SQL filtreleme, etiket tabanlı filtreleme ile uyumludur. SQL sözdiziminde etiket niteliğine TAGS olarak başvurun.
Sınırlamalar
Yalnızca Enterprise Platinum Edition örnekleri nitelik tabanlı SQL filtrelemeyi destekler.
Bu yöntemi yalnızca TCP istemci SDK'ları destekler.
Broker nitelik tabanlı SQL filtrelemeyi desteklemiyorsa ve bir tüketici bir filtre ifadesi tanımlarsa, tüketici başlatıldığında hata bildirilir veya tüketici mesaj almayabilir.
Örnek senaryo
Bir e-ticaret işlem sisteminde mesajlar sipariş mesajları ve lojistik mesajları olarak sınıflandırılır. Lojistik mesajlarında Hangzhou veya Shanghai değerlerini alan bir region niteliği bulunur.
Sipariş mesajları
-
Lojistik mesajları
region= Hangzhou olan lojistik mesajlarıregion= Shanghai olan lojistik mesajları
Bu mesajlar Trade_Topic adlı bir konuya gönderilir. Dört alt sistem abone olur:
Lojistik sistemi 1: yalnızca
regiondeğeri Hangzhou olan lojistik mesajlarına abone olur.Lojistik sistemi 2: tüm lojistik mesajlarına abone olur.
Sipariş izleme sistemi: yalnızca sipariş mesajlarına abone olur.
Gerçek zamanlı hesaplama sistemi: tüm mesajlara abone olur.

SQL filtrelemeyi yapılandırma
Filtreleme mantığını ApsaraMQ for RocketMQ istemci SDK'sında tanımlayın. Üretici kodunda özel mesaj niteliklerini ayarlayın ve tüketici kodunda bir SQL filtre ifadesi tanımlayın. SDK ayrıntıları için bkz. Genel Bakış.
Nitelik anahtarı kuralları
Her özel nitelik bir anahtar-değer çiftidir. Anahtar şu kurallara uymalıdır:
Harf, rakam ve alt çizgi (
_) içerebilir.Bir harf veya alt çizgiyle (
_) başlamalıdır.
Her mesaja birden fazla nitelik atanabilir.
Üretici: Özel nitelikleri ayarlama
Message msg = new Message("topic", "tagA", "Hello MQ".getBytes());
// Set custom attribute A to 1.
msg.putUserProperties("A", "1");
Tüketici: Filtre ifadesi tanımlama
SQL filtre ifadesi tanımlamak için MessageSelector.bySql() kullanın.
Filtre ifadesindeki her özel nitelik için her zaman bir IS NOT NULL denetimi ekleyin. Nitelik bir mesajda yoksa ifade NULL olarak değerlendirilir ve mesaj iletilmez.
// Subscribe to messages where attribute A exists and equals 1.
consumer.subscribe("topic", MessageSelector.bySql("A IS NOT NULL AND TAGS IS NOT NULL AND A = '1'"), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
SQL sözdizimi referansı
| Sözdizimi | Açıklama | Örnek |
|---|---|---|
IS NULL |
Nitelik mevcut değil. | a IS NULL -- a niteliği mevcut değil. |
IS NOT NULL |
Nitelik mevcut. | a IS NOT NULL -- a niteliği mevcut. |
>, >=, <, <= |
Sayısal karşılaştırma. Dizeler karşılaştırılamaz. Dizelerle kullanılırsa tüketici başlatıldığında hata bildirilir. Sayılara dönüştürülebilen dizeler sayısal değer olarak işlenir. | a IS NOT NULL AND a > 100 -- a niteliği mevcut ve 100'den büyük. a IS NOT NULL AND a > 'abc' -- Hata. a ile abc dizesi karşılaştırılamaz. |
BETWEEN xxx AND xxx |
Dahil olmak üzere sayısal aralık. >= xxx AND <= xxx ifadesine eşdeğerdir. Dizeler karşılaştırılamaz. |
a IS NOT NULL AND (a BETWEEN 10 AND 100) -- a niteliği mevcut ve 10 ile 100 arasında (dahil). |
NOT BETWEEN xxx AND xxx |
Sayısal aralığın dışında. < xxx OR > xxx ifadesine eşdeğerdir. Dizeler karşılaştırılamaz. |
a IS NOT NULL AND (a NOT BETWEEN 10 AND 100) -- a niteliği mevcut ve 10'dan küçük veya 100'den büyük. |
IN (xxx, xxx) |
Değer bir küme içinde. Küme öğeleri dize olmalıdır. | a IS NOT NULL AND (a IN ('abc', 'def')) -- a niteliği mevcut ve abc veya def değerine eşit. |
=, <> |
Eşittir ve eşit değildir. Hem sayılar hem de dizelerle çalışır. | a IS NOT NULL AND (a = 'abc' OR a<>'def') -- a niteliği mevcut ve abc değerine eşit veya def değerine eşit değil. |
AND, OR |
Mantıksal operatörler. Her koşulu parantez içine alın. | a IS NOT NULL AND (a > 100) OR (b IS NULL) -- a niteliği mevcut ve 100'den büyük veya b niteliği mevcut değil. |
Filtre ifadesi hata yönetimi
Bir filtre ifadesi geçerli bir sonuç üretemediğinde broker mesajı iletmez. Bu durum şu durumlarda gerçekleşir:
Hesaplama hatası: İfade değerlendirilmesi sırasında bir özel durum oluşur; örneğin sayısal ve sayısal olmayan değerler karşılaştırılır.
NULL veya Boolean olmayan sonuç: İfade NULL veya Boolean olmayan bir değer döndürür. Örneğin, tüketici üreticinin ayarlamadığı bir niteliğe göre filtreleme yapar.
Tür uyuşmazlığı: Özel nitelik değeri kayan noktalı bir sayıdır ancak filtre ifadesi karşılaştırma için tamsayı kullanır.
Örnek kod
Bu örneklerde farklı filtreleme sonuçlarını göstermek için tek bir üretici mesajı ve birden çok tüketici aboneliği kullanılmıştır.
Etiketli ve özel nitelikli mesaj gönderme
Producer producer = ONSFactory.createProducer(properties);
// Set the tag to tagA.
Message msg = new Message("topicA", "tagA", "Hello MQ".getBytes());
// Set custom attribute region to hangzhou.
msg.putUserProperties("region", "hangzhou");
// Set custom attribute price to 50.
msg.putUserProperties("price", "50");
SendResult sendResult = producer.send(msg);
Özel niteliğe göre filtreleme
Consumer consumer = ONSFactory.createConsumer(properties);
// Subscribe only to messages where region is hangzhou.
// Messages without the region attribute or with a different value are not delivered.
consumer.subscribe("topicA", MessageSelector.bySql("region IS NOT NULL AND region = 'hangzhou'"), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
Beklenen sonuç: Mesaj iletilir. region niteliği hangzhou olarak ayarlanmıştır ve bu değer filtre koşuluyla eşleşir.
Etikete ve özel niteliğe göre filtreleme
Consumer consumer = ONSFactory.createConsumer(properties);
// Subscribe only to messages with tagA and price greater than 30.
consumer.subscribe("topicA", MessageSelector.bySql("TAGS IS NOT NULL AND price IS NOT NULL AND TAGS = 'tagA' AND price > 30 "), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
Beklenen sonuç: Mesaj iletilir. Mesajda tagA bulunur ve price niteliği 50 değerindedir; bu değer 30'dan büyüktür.
Birden çok özel niteliğe göre filtreleme
Consumer consumer = ONSFactory.createConsumer(properties);
// Subscribe only to messages where region is hangzhou and price is less than 20.
consumer.subscribe("topicA", MessageSelector.bySql("region IS NOT NULL AND price IS NOT NULL AND region = 'hangzhou' AND price < 20"), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
Beklenen sonuç: Mesaj iletilmez. Tüketici price değerinin 20'den küçük olmasını gerektirir ancak mesajda price değeri 50 olarak ayarlanmıştır.
SQL ile tüm mesajlara abone olma
Consumer consumer = ONSFactory.createConsumer(properties);
// Set the SQL expression to TRUE to receive all messages.
consumer.subscribe("topicA", MessageSelector.bySql("TRUE"), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
Beklenen sonuç: Konudaki tüm mesajlar iletilir.
Yanlış: Eksik nitelik ve null denetimi
Üretici bir mesaja özel bir nitelik atmazsa ve tüketicinin filtre ifadesi o niteliğe IS NOT NULL denetimi olmadan başvurursa ifade NULL olarak değerlendirilir. Mesaj iletilmez.
Consumer consumer = ONSFactory.createConsumer(properties);
// The product attribute was not set when the message was sent.
// The filter fails and the message is not delivered.
consumer.subscribe("topicA", MessageSelector.bySql("product = 'MQ'"), new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.printf("Receive New Messages: %s %n", message);
return Action.CommitMessage;
}
});
Başvurular
Aynı grup kimliğini kullanan tüketici örnekleri aynı konulara abone olmalıdır. Daha fazla bilgi için bkz. Abonelik tutarlılığı.
Farklı hizmetler için mesajları sınıflandırmak amacıyla konuları ve etiketleri kullanın. Daha fazla bilgi için bkz. Konu ve etiket en iyi uygulamaları.