我试图找出一种有效的方法来保证PUT请求在服务器指定资源键的情况下创建新资源时具有幂等性。
据我所知,传统方法是创建一种事务资源类型,例如/CREATE_PERSON。创建新人员资源的客户端-服务器交互将分为两个部分: 步骤1:获取创建新个人资源的唯一事务ID:
**Client request:**
POST /CREATE_PERSON
**Server response:**
200 OK
transaction-id:"as8yfasiob"
步骤2:使用交易ID创建新的人员资源,确保请求是唯一的:
**Client request**
PUT /CREATE_PERSON/{transaction_id}
first_name="Big bubba"
**Server response**
201 Created // (If the request is a duplicate, it would send this
PersonKey="398u4nsdf" // same response without creating a new resource. It
// would perhaps send an error response if the was used
// on a transaction id non-duplicate request, but I have
// control over the client, so I can guarantee that this
// won't happen)
我看到这种方法的问题在于,为了创建一个新的PERSON资源,需要向服务器发送两个请求。这会导致性能问题,增加用户等待客户端完成请求的机会。
我一直在思考消除第一步的想法,比如预先发送每个请求的事务ID,但我的大多数想法都有其他问题或涉及牺牲应用程序的无状态性。
有没有办法做到这一点?
编辑:
我们最终采用的解决方案是让客户端获取UUID并将其与请求一起发送。 UUID是一个非常大的数字,占据16字节(2 ^ 128)的空间。与编程思维相反的是,随机生成UUID并假定它是唯一值是被接受的实践。这是因为可能的值数量如此之大,以至于随机生成两个相同的数字的几率很低,几乎不可能。
一个注意点是,我们让客户端从服务器请求UUID(GET uuid /)。这是因为我们无法保证客户端运行的环境。如果存在问题,例如在客户端上播种随机数生成器,那么很可能会发生UUID冲突。
POST
不是幂等的。两个相同的POST
应该会创建两个新的从属资源。就像HTTP一样。如果你POST
并且新资源成功创建,响应应该包含Location
头部和新资源的URI。没有“丢失的消息”。 - Franci Penov