繁体   English   中英

API 用 .NET 核心调用“FIFO”

[英]API calls "FIFO" with .NET Core

我有一个 API 端点,经过身份验证的用户可以使用它来预订活动。 一旦拨打 API 的预订电话成功,该数量的景点将被“消耗”,其他用户将无法预订。

我想要实现的是组织并发调用以避免发生以下情况:

  • 场馆有10个名额
  • 用户A拨打API预约6个名额
  • 用户 B 大约在同一时间(几毫秒后)拨打 API 电话以保留 5 个名额
  • 在用户 A 的调用完成并锁定 6 个位置之前,用户 B 的调用继续进行,就好像它会成功一样,因为它看到 10 个可用位置。

本质上,我正在尝试按顺序组织我的电话。

进一步考虑:

  • 我正在使用 Microsoft Azure - 我应该考虑使用各种队列吗?
  • 我还在为我的后端数据使用 EF Core,如果它能以我无法想到的方式产生影响的话。
  • 有没有我可以用来做这种类似信号量的方法的库?

我完全理解,作为替代方案,我可以一次为每个用户软保留一个位置,并且只有在所有位置都成功软保留后,我才会提前 go 并硬保留它们。 在我 go 沿着这条路走之前,我很好奇是否有一些不那么笨拙的方法。

谢谢

同步

如果您可以在数据库级别使用悲观锁定,那么您可以在没有队列或异步的情况下解决这个问题。 悲观锁本质上是一种序列化的方式。 我不建议使用进程内锁进行锁定,例如lock关键字/mutex 等。 现代 API 有多个实例,因此排除了单机/内存互斥。

您可以立即(同步)调用某种持久性存储(例如专用于保留槽的表)来保留M个槽。 这可能类似于“更新NAvailable - M >= 0的记录”。 “记录”将通过房间 ID 等标准进行识别。

  • 如果该事务成功,则在该记录被锁定以进行更新时它会成功,这意味着其他调用将阻塞,直到您从事务中返回。 然后那些人将能够继续他们的尝试。 这是安全的,因此您可以从 API POST返回201 CREATED (这是一个POST ,因为您要求创建预订)。
  • 如果该事务失败,则仅表示没有足够的槽用于该调用。 可以返回409 CONFLICT ,表示客户端的请求是合法的,但是由于系统的 state(槽位不够)导致无法填充

异步

这必然更复杂,但可能会增加解决方案的并发性。 在这种情况下,您通常会接受来自客户端的所有调用并将它们排入队列。 同样,您可以使用像ConcurrentQueue这样的内存中解决方案来序列化请求,但最好使用使用“真实”排队机制(例如 Azure 队列)的分布式解决方案。

在这种情况下,每个客户端请求都会立即放入队列中,并且 API 返回202 ACCEPTED 。队列的消费者尝试完成请求。 整个工作流程将符合异步请求-回复模式

这需要在服务器(跟踪工作和实现)和客户端(轮询以确定工作是否真正成功,或对推送通知 ala SignalR 做出反应)上做更多工作。

总结

我正在使用 Microsoft Azure - 我应该考虑使用各种队列吗?

是的。 这是合理的,从并发的角度来看是比较乐观的。 使用“软储备”扩展了这种方法,不仅合理,而且很常见; 考虑在飞机上预订座位。 您会在 window 的一小段时间内获得席位,但不会永远如此。 工作流更复杂,但允许在乐观并发失败时补偿事务

我还在为我的后端数据使用 EF Core,如果它能以我无法想到的方式产生影响的话。

我不认为这会有所作为。 它是对数据库的抽象。

有没有我可以用来做这种类似信号量的方法的库?

也许。 其中大部分属于模式领域,这意味着您可能可以使用一些样板代码(我知道我已经这样做过几次。)或将模式编码的框架。

这是多线程系统中的常见问题。 有很多方法可以完成,但如果调用速度很快并且负载不是很大,您可能可以使用 ReaderWriterLockSlim 之类的方法。 我不太熟悉 Azure,但如果我自己编写服务器,那将是我的快速解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM