C# 与服务结构中的两个或多个有状态服务共享队列
是否可以在两个或多个有状态服务之间共享队列,或者我是否需要通过tcp/http直接调用它以将消息放入其自身的内部队列 比如,;假设我有我的第一个服务,它根据一个条件向队列下订单:C# 与服务结构中的两个或多个有状态服务共享队列,c#,azure-service-fabric,service-fabric-stateful,C#,Azure Service Fabric,Service Fabric Stateful,是否可以在两个或多个有状态服务之间共享队列,或者我是否需要通过tcp/http直接调用它以将消息放入其自身的内部队列 比如,;假设我有我的第一个服务,它根据一个条件向队列下订单: public sealed class Service1 : StatefulService { public Service1(StatefulServiceContext context, IReliableStateManagerReplica reliableStateManagerReplica)
public sealed class Service1 : StatefulService
{
public Service1(StatefulServiceContext context, IReliableStateManagerReplica reliableStateManagerReplica)
: base(context, reliableStateManagerReplica)
{ }
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var customerQueue = await this.StateManager.GetOrAddAsync<IReliableQueue<Order>>("orders");
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
using (var tx = this.StateManager.CreateTransaction())
{
if (true /* some logic here */)
{
await customerQueue.EnqueueAsync(tx, new Order());
}
await tx.CommitAsync();
}
}
}
}
公共密封类服务1:StatefulService
{
公共服务1(StatefulServiceContext上下文,IReliableStateManagerReplica reliableStateManagerReplica)
:base(上下文,reliableStateManagerReplica)
{ }
受保护的覆盖异步任务RunAsync(CancellationToken CancellationToken)
{
var customerQueue=wait this.StateManager.GetOrAddAsync(“订单”);
while(true)
{
cancellationToken.ThrowIfCancellationRequested();
使用(var tx=this.StateManager.CreateTransaction())
{
if(true/*此处有一些逻辑*/)
{
等待customerQueue.EnqueueAsync(tx,neworder());
}
wait tx.CommitAsync();
}
}
}
}
然后,我的第二个服务从该队列读取数据,然后继续处理
public sealed class Service2 : StatefulService
{
public Service2(StatefulServiceContext context, IReliableStateManagerReplica reliableStateManagerReplica)
: base(context, reliableStateManagerReplica)
{ }
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var customerQueue = await this.StateManager.GetOrAddAsync<IReliableQueue<Order>>("orders");
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
using (var tx = this.StateManager.CreateTransaction())
{
var value = await customerQueue.TryDequeueAsync(tx);
if (value.HasValue)
{
// Continue processing the order.
}
await tx.CommitAsync();
}
}
}
}
公共密封类服务2:StatefulService
{
公共服务2(StatefulServiceContext上下文,IReliableStateManagerReplica reliableStateManagerReplica)
:base(上下文,reliableStateManagerReplica)
{ }
受保护的覆盖异步任务RunAsync(CancellationToken CancellationToken)
{
var customerQueue=wait this.StateManager.GetOrAddAsync(“订单”);
while(true)
{
cancellationToken.ThrowIfCancellationRequested();
使用(var tx=this.StateManager.CreateTransaction())
{
var value=wait customerQueue.TryDequeueAsync(tx);
if(value.HasValue)
{
//继续处理订单。
}
wait tx.CommitAsync();
}
}
}
}
我在文档中看不到太多关于此的内容,我可以看到GetOrAddAsync
方法可以接受uri,但我没有看到关于此方法如何工作的示例,或者您是否可以执行跨服务
这背后的想法是将处理拆分为单独的队列,以便在尝试重试消息时不会处于不一致的状态。无法跨服务共享状态。作用于服务分区级别 为此,您可以使用外部队列,如服务总线
您还可以使用一种方法来反转控制。服务1将引发一个事件,服务2将该事件用作继续处理的触发器。要处理的数据可能在事件内部,或者存储在另一个位置的数据,从事件中引用。无法跨服务共享状态。作用于服务分区级别 为此,您可以使用外部队列,如服务总线
您还可以使用一种方法来反转控制。服务1将引发一个事件,服务2将该事件用作继续处理的触发器。要处理的数据可能在事件内部,或者存储在另一个位置的数据,从事件中引用。是的,看起来是这样,与基于命令的方法相比,非常类似于发布/订阅方式。感谢您的澄清。是的,看起来是这样的,与基于命令的方法相比,非常像pub/sub方法。谢谢你的澄清。