MassTransit和服务结构有状态服务?
我一直在尝试制作一个网站的演示,该网站使用MassTransit和RabbitMQ将消息作为有状态服务发布到服务结构上运行的服务 一切都很顺利,我的客户会发布一条消息:MassTransit和服务结构有状态服务?,masstransit,service-fabric-stateful,Masstransit,Service Fabric Stateful,我一直在尝试制作一个网站的演示,该网站使用MassTransit和RabbitMQ将消息作为有状态服务发布到服务结构上运行的服务 一切都很顺利,我的客户会发布一条消息: IBusControl bus = BusConfigurator.ConfigureBus(); Uri sendToUri = new Uri($"{RabbitMqConstants.RabbitMqUri}" + $"{RabbitMqConstants.PeopleServiceQueue}"); ISendEndpo
IBusControl bus = BusConfigurator.ConfigureBus();
Uri sendToUri = new Uri($"{RabbitMqConstants.RabbitMqUri}" + $"{RabbitMqConstants.PeopleServiceQueue}");
ISendEndpoint endPoint = await bus.GetSendEndpoint(sendToUri);
await endPoint.Send<ICompanyRequest>(new {CompanyId = id });
然后,在我的消息消费者类中,我可以执行以下操作:
internal sealed class PersonInformationConsumer : StatefulService, IConsumer<ICompanyRequest>
{
private static StatefulServiceContext _currentContext;
#region Constructors
public PersonInformationConsumer(StatefulServiceContext serviceContext) : base(serviceContext)
{
_currentContext = serviceContext;
}
public PersonInformationConsumer() : base(_currentContext)
{
}
我现在遇到的问题是试图在IReliableDictionary上存储一些内容,这样做会导致“对象引用未设置为对象实例”错误:(…任何想法都将受到欢迎(尽管可能直到新年才阅读!)
公共异步任务使用(consumercontext)
{
ServiceEventSource.Current.ServiceMessage(this.Context,“消息已被使用,请求Id:{0}”,Context.Message.CompanyId);
使用(ITransaction tx=StateManager.CreateTransaction())
{
尝试
{
var myDictionary=await StateManager.GetOrAddAsync(“myDictionary”);
这是导致错误的原因。…帮助!:)要使MassTransit和有状态服务协同工作,您需要做更多的工作,这里有几个问题需要您自己考虑 只有一个有状态分区内的主机(n个分区内的n个主机)将能够写入/更新有状态服务,所有副本在尝试写回任何状态时都会抛出异常。因此,您需要处理此问题,表面上看,这听起来很容易,直到您考虑到由于重新平衡群集(通用服务结构appli的默认设置),主机可以在群集周围移动这就是关闭副本上的处理,只在主机上运行工作。这都是通过RunAsync方法完成的(尝试一下,在RunAsync方法中使用noddy运行3个有状态服务,然后终止主机)
还有你的数据分区要考虑,由于有分区服务的状态服务规模,你需要创建一种分配数据到你的服务总线上的端点的方法,也许有一个单独的队列只侦听一个给定的分区范围?比如说你有一个<代码>用户创建的消息,你可以把它拆分在<代码> C上。国家
英国
转到分区1,美国
转到分区2等
如果您只是想让一些基本的东西启动并运行,我会将它限制在一个分区内,然后尝试将您的总线创建放在RunAsync中,并在取消令牌上请求取消后关闭总线
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host(new Uri(RabbitMqConstants.RabbitMqUri), h =>
{
h.Username(RabbitMqConstants.UserName);
h.Password(RabbitMqConstants.Password);
});
cfg.ReceiveEndpoint(host, RabbitMqConstants.PeopleServiceQueue, e =>
{
// Pass in the stateful service context
e.Consumer(c => new PersonInformationConsumer(Context));
});
});
busControl.Start();
while (true)
{
if(cancellationToken.CancellationRequested)
{
//Service Fabric wants us to stop
busControl.Stop();
cancellationToken.ThrowIfCancellationRequested();
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
我没有安装service fabric SDK,但是看到在异步方法中访问静态类会让我停顿,当然还有另一种方法可以访问可靠的字典实例。我使用服务侦听器对其进行了一些POC,请查看此示例-
internal sealed class PersonInformationConsumer : StatefulService, IConsumer<ICompanyRequest>
{
private static StatefulServiceContext _currentContext;
#region Constructors
public PersonInformationConsumer(StatefulServiceContext serviceContext) : base(serviceContext)
{
_currentContext = serviceContext;
}
public PersonInformationConsumer() : base(_currentContext)
{
}
ServiceEventSource.Current.ServiceMessage(this.Context, "Message has been consumed, request Id: {0}", context.Message.CompanyId);
public async Task Consume(ConsumeContext<ICompanyRequest> context)
{
ServiceEventSource.Current.ServiceMessage(this.Context, "Message has been consumed, request Id: {0}", context.Message.CompanyId);
using (ITransaction tx = StateManager.CreateTransaction())
{
try
{
var myDictionary = await StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary");
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host(new Uri(RabbitMqConstants.RabbitMqUri), h =>
{
h.Username(RabbitMqConstants.UserName);
h.Password(RabbitMqConstants.Password);
});
cfg.ReceiveEndpoint(host, RabbitMqConstants.PeopleServiceQueue, e =>
{
// Pass in the stateful service context
e.Consumer(c => new PersonInformationConsumer(Context));
});
});
busControl.Start();
while (true)
{
if(cancellationToken.CancellationRequested)
{
//Service Fabric wants us to stop
busControl.Stop();
cancellationToken.ThrowIfCancellationRequested();
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
}