也许我在这里忽略了一些简单而明显的东西,但是还是让我们来看看吧:
HTTP请求/响应中Etag标头的一个特性是实现并发性,即使多个客户端不能覆盖资源的编辑(通常在进行PUT请求时)。我认为这部分是非常知名的。
我不确定的部分是后端/API实现如何在没有竞争条件的情况下实际实现这一点;例如:
设置:
- 基于ORM的RESTful API位于标准关系数据库之上(SQLAlchemy或Postgres)。 - Etag基于资源的“最后更新时间”。 - Web框架(Flask)位于多线程/进程Web服务器之后(nginx+gunicorn),因此可以同时处理多个请求。
问题:
- 客户端1和2都请求资源(get请求),现在它们有相同的Etag。 - 客户端1和2都同时发送PUT请求以更新资源。API接收到请求,然后使用ORM从数据库获取所需信息,然后将请求Etag与数据库中的“最后更新时间”进行比较...它们匹配,因此每个请求都是有效的。每个请求都继续并提交更新到数据库。 - 每个提交都是同步/阻塞事务,因此一个请求会在另一个请求之前完成,因此一个请求将覆盖其他更改。这不破坏Etag的目的吗?
我能想到的唯一可靠的解决方案是使数据库也执行检查,在更新查询中进行检查。我有什么遗漏的吗?
P.S由于使用的框架,这应该是一个与语言/框架无关的问题。
HTTP请求/响应中Etag标头的一个特性是实现并发性,即使多个客户端不能覆盖资源的编辑(通常在进行PUT请求时)。我认为这部分是非常知名的。
我不确定的部分是后端/API实现如何在没有竞争条件的情况下实际实现这一点;例如:
设置:
- 基于ORM的RESTful API位于标准关系数据库之上(SQLAlchemy或Postgres)。 - Etag基于资源的“最后更新时间”。 - Web框架(Flask)位于多线程/进程Web服务器之后(nginx+gunicorn),因此可以同时处理多个请求。
问题:
- 客户端1和2都请求资源(get请求),现在它们有相同的Etag。 - 客户端1和2都同时发送PUT请求以更新资源。API接收到请求,然后使用ORM从数据库获取所需信息,然后将请求Etag与数据库中的“最后更新时间”进行比较...它们匹配,因此每个请求都是有效的。每个请求都继续并提交更新到数据库。 - 每个提交都是同步/阻塞事务,因此一个请求会在另一个请求之前完成,因此一个请求将覆盖其他更改。这不破坏Etag的目的吗?
我能想到的唯一可靠的解决方案是使数据库也执行检查,在更新查询中进行检查。我有什么遗漏的吗?
P.S由于使用的框架,这应该是一个与语言/框架无关的问题。
and version = xxx
的约束条件。如果没有记录被更新,那么您可以假设该记录在客户端获取数据后已经被更新。在更新的上下文中,您将包括set version = version + 1
。 - Evan