Creating a message consumer

A message consumer is a class that consumes one or more message types, specified by theIConsumer<T> interface, where T is the message type.

public class UpdateCustomerConsumer :
IConsumer<UpdateCustomerAddress>
{
public async Task Consume(ConsumeContext<UpdateCustomerAddress> context)
{
await Console.Out.WriteLineAsync($"Updating customer: {context.Message.CustomerId}"); // update the customer address
}
}

When a consumer is subscribed to a receive endpoint, and a message consumed by the consumer is received by the endpoint, an instance of the consumer is created (using a consumer factory, which is covered –> here <–). The message (wrapped in a ConsumeContext) is then delivered to the consumer via the Consume method.

The Consume method is asynchronous, and returns a Task. The task is awaited by MassTransit, during which time the message is unavailable to other receive endpoints. If the consume method completes successfuly (a task status of RanToCompletion), the message is acknowledged and removed from the queue.

Note

If the consumer faults (such as throwing an exception, resulting in a task status of Faulted), or is somehow cancelled (TaskStatus of Canceled), the exception is propagated back up the pipeline where it can ultimately be retried or moved to an error queue.

Connecting a message consumer

For a consumer to receive messages, the consumer must be connected to a receive endpoint. This is done during bus configuration, particularly within the configuration of a receive endpoint.

An example of connecting a consumer to a receive endpoint is shown below.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
{
h.Username("guest");
h.Password("guest");
}); cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
e.Consumer<UpdateCustomerConsumer>();
});
});

The example creates a bus, which connects to the RabbitMQ running on the local machine, using the default username and password (guest/guest). On that bus. a single receive endpoint is created with the name customer_update_queue. The consumer is connected using the simplest method, which accepts a consumer class with a default constructor.

Note

When a consumer is connected to a receive endpoint, the combined set of message types consumed by all of the consumers connected to the same receive endpoint are subscribed to the queue. The subscription method varies by broker, in the case of RabbitMQ exchange bindings are created for the message types to the exchange/queue for the receive endpoint.

These subscriptions are persistent, and remain in place after the process exits. This ensures that messages published or sent that would be delivered to one of the receive endpoint consumers are saved even is the process is terminated. When the process is started, messages waiting in the queue will be delivered to the consumer(s).

The above example connects the consumer using a default constructor consumer factory. There are several other consumer factories supported, as shown below.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = ...; cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
// an anonymous factory method
e.Consumer(() => new YourConsumer()); // an existing consumer factory for the consumer type
e.Consumer(consumerFactory); // a type-based factory that returns an object (container friendly)
e.Consumer(consumerType, type => container.Resolve(type)); // an anonymous factory method, with some middleware goodness
e.Consumer(() => new YourConsumer(), x =>
{
// add middleware to the consumer pipeline
x.UseLog(ConsoleOut, async context => "Consumer created");
});
});
});

Connecting to an existing bus

Once a bus has been created, the receive endpoints have been created and cannot be modified. The bus itself, however, provides a temporary (auto-delete) queue which can be used to receive messages. To connect a consumer to the bus temporary queue, a series of Connect methods can be used.

Warning

Published messages will not be received by the temporary queue. Because the queue is temporary, when consumers are connected no bindings or subscriptions are created. This makes it very fast for transient consumers, and avoid thrashing the message broker with temporary bindings.

The temporary queue is useful to receive request responses and faults (via the response/fault address header) and routing slip events (via an event subscription in the routing slip).

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = ...;
}); busControl.Start(); ConnectHandle handle = busControl.ConnectConsumer<FaultConsumer>();
...
handle.Disconnect(); // disconnect the consumer from the bus pipeline

In addition to the `ConnectConsumer` method, methods for each consumer type are also included (`ConnectHandler``ConnectInstance``ConnectSaga`, and `ConnectStateMachineSaga`).

Connecting an existing consumer instance

While using a consumer instance per message is highly suggested, it is possible to connect an existing consumer instance which will be called for every message. The consumer must be thread-safe, as the`Consume` method will be called from multiple threads simultaneously. To connect an existing instance, see the example below.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = ...; cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
e.Instance(existingConsumer);
});
});

Handling undeliverable messages

If the configuration of an endpoint changes, or if a message is mistakenly sent to an endpoint, it is possible that a message type is received that does not have any connected consumers. If this occurs, the message is moved to a _skipped queue (prefixed by the original queue name). The original message content is retained, and additional headers are added to indicate the host which moved the message.

Handling messages without a consumer

While creating a consumer is the preferred way to consume messages, it is also possible to create a simple message handler. By specifying a method, anonymous method, or lambda method, a message can be consumed on a receive endpoint.

To configure a simple message handler, refer to the example below.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = ...; cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
e.Handler<UpdateCustomerAddress>(context =>
return Console.Out.WriteLineAsync($"Update customer address received: {context.Message.CustomerId}"));
});
});

In this case, the method is called for each message received. No consumer is created, and no lifecycle management is performed.

Observing messages via IObserver

With the addition of the IObserver interface, the concept of an observer was added to the .NET framework. MassTransit supports the direct connection of observers to receive endpoints.

Note

Unfortunately, observers are not asynchronous. Because of this, it is not possible to play nice with the async support provided by the compiler when using an observer.

An observer is defined using the built-in IObserver<T> interface, as shown below.

public class CustomerAddressUpdatedObserver :
IObserver<ConsumeContext<CustomerAddressUpdated>>
{
public void OnNext(ConsumeContext<CustomerAddressUpdated> context)
{
Console.WriteLine("Customer address was updated: {0}", context.Message.CustomerId);
} public void OnError(Exception error)
{
} public void OnCompleted()
{
}
}

Once created, the observer is connected to the receive endpoint similar to a consumer.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = ...; cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
e.Observer<CustomerAddressUpdatedObserver>();
});
});

MassTransit_消费者的创建的更多相关文章

  1. MassTransit_契约的创建

    消息契约的命名规范 命令模式:动词+对象 事件模式:对象+动词 不同模式下要求不同的主键 Creating a message contract In MassTransit, a message c ...

  2. springcloud-Netflix创建服务消费者

    目录 springcloud-Netflix创建服务消费者 Ribbon 创建服务消费者-Ribbon方式 ribbon的架构 Feign 创建包和基本项目结构 创建Feign访问服务的接口和访问co ...

  3. 161130、Dubbo+SpringMVC工程创建详解

    Dubbo出现的目的是为了应对现在高并发,高数据量请求的问题.目前的垂直应用架构已经无法满足现在大数据的冲击,SOA就应运而生,而Dubbo在国内使用的还是比较多,稳定性也比较不错. 架构 节点角色说 ...

  4. Linux多线程之同步2 —— 生产者消费者模型

    思路 生产者和消费者(互斥与同步).资源用队列模拟(要上锁,一个时间只能有一个线程操作队列). m个生产者.拿到锁,且产品不满,才能生产.当产品满,则等待,等待消费者唤醒.当产品由空到不空,通知消费者 ...

  5. 翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2

    翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2 原文地址:http://onehungrymind.com/build-better-angular-2-application- ...

  6. nopCommerce 3.9 大波浪系列 之 事件机制(生产者、消费者)

    一.nop事件机制简介 应用场景:客户支付成功后,需要发送短信.邮件告知客户订单支付成功(短信.邮件由不同模块实现) 实现方法: 1.定义支付成功OrderPaidEvent事件. 2.定义短信,邮箱 ...

  7. Springboot+ActiveMQ(ActiveMQ消息持久化,保证JMS的可靠性,消费者幂等性)

    ActiveMQ 持久化设置: 在redis中提供了两种持久化机制:RDB和AOF 两种持久化方式,避免redis宕机以后,能数据恢复,所以持久化的功能 对高可用程序来说 很重要. 同样在Active ...

  8. Kafka技术内幕 读书笔记之(五) 协调者——消费者加入消费组

    消费者客户端轮询的3个步骤:发送拉取请求,客户端轮询,获取拉取结果 . 消费者在发送拉取请求之前,必须首先满足下面的两个条件.- 确保消费者已经连接协调者, 即找到服务端中管理这个消费者的协调者节点 ...

  9. Redux 和 ngrx 创建更佳的 Angular 2

    Redux 和 ngrx 创建更佳的 Angular 2 翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2 原文地址:http://onehungrymind.com/build- ...

随机推荐

  1. SQL语句汇总(三)——聚合函数、分组、子查询及组合查询

    聚合函数: SQL中提供的聚合函数可以用来统计.求和.求最值等等. 分类: –COUNT:统计行数量 –SUM:获取单个列的合计值 –AVG:计算某个列的平均值 –MAX:计算列的最大值 –MIN:计 ...

  2. 使用cocos2d-x 3.0 beta开发的小游戏

    主要是参考了http://philon.cn/post/cocos2d-x-3.0-zhi-zuo-heng-ban-ge-dou-you-xi 这篇文章,只是移植到了3.0 beta版. 代码地址: ...

  3. [ucgui] 对话框1——创建对话框

    >_<" 小工具和对话框的区别: 小工具可以创建并独立使用,因为它们本质上就是窗口.但是,通常需要使用对话框,它是包含一个或多个小工具的窗口. 对话框通常是一个窗口,它在出现时会 ...

  4. Java-认识字符集-转载

    问题起源 对于计算机而言,它仅认识两个0和1,不管是在内存中还是外部存储设备上,我们所看到的文字.图片.视频等等“数据”在计算机中都是已二进制形式存在的.不同字符对应二进制数的规则,就是字符的编码.字 ...

  5. paip.抓取网页内容--java php python

    paip.抓取网页内容--java php python.txt 作者Attilax  艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog ...

  6. 使用Alcatraz来管理Xcode插件

    Alcatraz 是一个帮你管理 Xcode 插件.模版以及颜色配置的工具.它可以直接集成到 Xcode 的图形界面中,让你感觉就像在使用 Xcode 自带的功能一样. 安装和删除 使用如下的命令行来 ...

  7. Html+css 练习写页面发现的错误及解决办法。

    最近开始模仿写一些静态页面,今天模仿的是中华咨询网.写了一个简单的js(功能:当鼠标hover一级菜单的时候,设置二级菜单为显示,当鼠标hover二级菜单的选项时候,二级菜单不收回.当鼠标移出菜单一级 ...

  8. javaweb回顾第一篇servlet的学习和理解

    前言:关于servlet相信学过java的都不会陌生,我最近又把这些基础知识整理一遍,便于自已能更好的理解ssm或者ssh,下面开始 1:Servlet接口 servlet有5个方法下面分别简单的介绍 ...

  9. Activiti 查询最新版本的流程定义

    package com.mycom.processDefinition; import java.io.File; import java.io.IOException; import java.io ...

  10. 如何向Openstack社区提交一个新项目

    前几天有个朋友问我:自己有一个idea不错的项目,也把基本的框架写好了,想贡献到Openstack社区,却不知道应该怎么做.正好之前我有过类似的经历,那么来分享一下我是如何向Openstack社区提交 ...