【发布时间】:2018-10-18 15:48:35
【问题描述】:
背景
我有一个 web api 服务器(asp.net core v2.1),它提供一些基本的操作,比如管理服务器上的实体。这是界面:
[HttpPost]
[Route("create")]
public async Task<ActionResult<NewEntityResponse>> Create(CreateEntityModel model)
{
// 1) Validate the request.
// 2) Create a new row on the database
// 3) Return the new entity in response.
}
以这种方式运行此 REST 方法的用户:
POST https://example.com/create
Content-Type: application/json
{
"firstName": "Michael",
"lastName": "Jorden"
}
得到这样的回应:
Status 200
{
"id": "123456" // The newly created entity id
}
问题
当发送数千个这样的请求时,在某些时候它会因为网络连接而失败。当连接失败时,它会导致我们进入两种不同的情况:
- 网络调用在前往服务器的途中结束 - 在这种情况下,服务器不知道此请求。因此,没有创建实体。用户只需再次发送相同的消息。
- 网络调用已从服务器发送回客户端,但从未丰富目的地 - 在这种情况下,请求已完全满足,但客户端不知道这一点。预期的解决方案是再次发送相同的请求。在这种情况下,它将两次创建相同的实体 - 这就是问题所在。
请求的解决方案
我想为 web-api 创建一个通用解决方案,它“remmeber”命令它已经完成。如果他两次收到相同的请求,则返回 HTTP 状态码Conflict。
到目前为止我在哪里
我想给客户端添加一个选项来为请求添加一个唯一的id,这样:
POST https://example.com/create?call-id=XXX
向我的服务器添加一个新的过滤器,检查密钥 XXX 是否已经完成。如果是,请返回Conflict。否则 - 继续。
添加另一个服务器过滤器来检查方法的响应并将其标记为“已完成”以供进一步检查。
这个解决方案在并发调用上的问题。如果我的方法需要 5 秒才能返回并且客户端在 1 秒后再次发送相同的消息 - 它将创建两个具有相同数据的实体。
问题:
- 您认为这是解决此问题的好方法吗?
- 您是否熟悉执行此操作的即用型解决方案?
- 如何解决我的“并发”问题?
- 任何其他提示都会很棒!
谢谢。
【问题讨论】:
-
好问题,但是,听起来您正在发明一种新的 WS-transation。
-
并不是说这是完整或最佳的解决方案。但是您是否研究过 dbcontext 池?
标签: c# asp.net asp.net-web-api asp.net-core