ApsaraMQ for RocketMQ'deki producer ve consumer nesneleri iş parçacığı güvenlidir. Her iş parçacığı için ayrı bir örnek oluşturmak yerine, tek bir örneği iş parçacıkları arasında paylaşın.
Örnekleri neden paylaşmalısınız?
Bir veya daha fazla broker üzerinde birden çok producer ve consumer örneği dağıtabilirsiniz. Ayrıca, bir producer veya consumer örneğinde mesaj göndermek veya almak için birden çok iş parçacığı çalıştırabilirsiniz. Her iş parçacığı için ayrı bir örnek oluşturmak kaynakları boşa harcar ve aktarım hızını düşürebilir.
Tek bir producer veya consumer'ı birden çok iş parçacığında paylaşmak:
Hem istemci hem de broker tarafındaki kaynak yükünü azaltır
Mesaj gönderme ve alma için saniye başına işlem sayısını (TPS) artırır
Kullanım notları
Her iş parçacığı için ayrı bir producer veya consumer örneği oluşturmayın. Tek bir örnek oluşturun ve bunu iş parçacıkları arasında paylaşın.
Sıralı mesajları birden çok iş parçacığından göndermekten kaçının. Broker, mesaj sırasını tek bir producer'dan aldığı mesajların geliş sırasına göre belirler. Birden çok iş parçacığı eşzamanlı olarak gönderim yaptığında, broker'a ulaşma sırası uygulama mantığınızdaki gönderim sırasından farklı olabilir.
Paylaşılan ve iş parçacığı başına producer karşılaştırması
Doğru -- Producer'ı bir kez oluşturun ve iş parçacıkları arasında paylaşın:
Producer producer = ONSFactory.createProducer(properties);
producer.start();
// Thread 1 and Thread 2 share the same producer
Thread t1 = new Thread(() -> producer.send(msg1));
Thread t2 = new Thread(() -> producer.send(msg2));
t1.start();
t2.start();
Yanlış -- Her iş parçacığı için ayrı bir producer oluşturun:
// Each thread creates its own producer -- wastes resources
Thread t1 = new Thread(() -> {
Producer p = ONSFactory.createProducer(properties);
p.start();
p.send(msg);
p.shutdown();
});
Örnek kod
Aşağıdaki örnek, paylaşılan bir producer oluşturur ve iki iş parçacığından eşzamanlı olarak mesaj gönderir.
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.SendResult;
import java.util.Properties;
public class SharedProducer {
public static void main(String[] args) {
Properties properties = new Properties();
// The ID of the consumer group created in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.GROUP_ID, "<your-group-id>");
// Make sure the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID
// and ALIBABA_CLOUD_ACCESS_KEY_SECRET are configured.
properties.put(PropertyKeyConst.AccessKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"));
properties.put(PropertyKeyConst.SecretKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// Message send timeout in milliseconds.
properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000");
// TCP endpoint. Get this value from the TCP endpoint section on the Instance Details
// page in the ApsaraMQ for RocketMQ console.
properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");
final Producer producer = ONSFactory.createProducer(properties);
// Call start() once before sending any messages.
producer.start();
// Both threads share the same producer instance.
Thread thread1 = new Thread(() -> {
try {
Message msg = new Message(
"TopicTestMQ", // Topic for normal messages
"TagA", // Message tag for consumer-side filtering
"Hello MQ".getBytes() // Message body in binary format
);
SendResult result = producer.send(msg);
if (result != null) {
System.out.println("Sent successfully. Message ID: " + result.getMessageId());
}
} catch (Exception e) {
// Handle failures: retry or persist the message for later processing.
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
Message msg = new Message("TopicTestMQ", "TagA", "Hello MQ".getBytes());
SendResult result = producer.send(msg);
if (result != null) {
System.out.println("Sent successfully. Message ID: " + result.getMessageId());
}
} catch (Exception e) {
e.printStackTrace();
}
});
thread1.start();
thread2.start();
// Call shutdown() when the producer is no longer needed to release resources.
// producer.shutdown();
}
}
Aşağıdaki yer tutucuları kendi değerlerinizle değiştirin:
| Yer Tutucu | Açıklama | Nereden Bulunur |
|---|---|---|
<your-group-id> |
Consumer grubu kimliği | ApsaraMQ for RocketMQ konsolu |
<your-tcp-endpoint> |
TCP uç noktası | Örnek Ayrıntıları sayfasındaki TCP uç noktası bölümü |
Önemli noktalar:
send()yöntemi senkron iletim kullanır. Herhangi bir özel durum oluşmazsa mesaj başarıyla gönderilmiş demektir.Mesaj etiketi, consumer'ların broker üzerindeki mesajları filtrelemek için kullandığı bir etikettir (Gmail etiketine benzer).
Mesaj gövdesi ikili veridir. ApsaraMQ for RocketMQ mesaj gövdelerini işlemez. Producer ve consumer, serileştirme ve serileştirmeyi kaldırma yöntemleri konusunda anlaşmalıdır.
Normal mesajlar için kullanılan bir konu, diğer mesaj türleri için kullanılamaz.
Tek bir örneğin ötesinde ölçeklendirme
Daha yüksek aktarım hızı elde etmek için, bir veya daha fazla broker üzerinde birden çok producer veya consumer örneği dağıtın. Her örnek, bir iş parçacığı havuzu tarafından paylaşılır; ölçek ne olursa olsun iş parçacığı başına örnek oluşturmayın.
| Ölçek | Yaklaşım |
|---|---|
| Birkaç iş parçacığı | Tek bir producer'ı paylaşan özel iş parçacıkları oluşturun (yukarıda gösterildiği gibi) |
| Çok sayıda eşzamanlı gönderici | Tek bir producer'ı paylaşan bir iş parçacığı havuzu kullanın |
| Çok yüksek aktarım hızı | Her biri bir iş parçacığı havuzu tarafından paylaşılan birden çok producer örneği dağıtın |