我有一个查询来回答远程客户端的标准请求。标准,从服务器外部不占用任何参数。每当
任何人都向URL提交请求,比如http://www.example.com/query,他/她会在响应正文中获取reply.xml
的内容,
取决于数据库当时提供的内容。
reply.xml
的内容仅在服务器上的数据库内容中更改,并且在外部任何内容上都不会更改
比如谁查询,输入等等,因此不会从客户端获取参数。我甚至没有检查任何身份验证 - 我们将所有内容都留给了防火墙。
所以我写了一个@POST
方法,比如说query()
来调用发布到http://www.example.com/query的请求,然后传递结果。我使用了Jersey
,除了
请求应该是跨时间的。
也就是说,一次应该提供一个请求 - 后续的用户点击应该是获取HTTP状态为309的消息,除非服务器没有运行我的方法query()
调用的查询过程。
如何实现这一目标?我尝试了query()
发送@PUT
而不是@POST
回复,并得到了相同的结果。
关于这个话题也许是一个天真的问题。但是,不太熟悉Restful服务。
我可以通过线程化令牌来控制一次只运行一个查询并使同时请求接收HTTP 309。但是必须有更好,更简单的方法在服务器上实现这一点。
我正在使用Tomcat 8,Jersey 1.19。
TIA。
注意:我在其他一些有用的讨论中读过PUT vs POST in REST。
// =====================
编辑:
哪个用户提交查询在任何时候都没有任何区别。
假设userA
提交了一个查询。当该查询仍在运行时,即在query()
将响应返回userA
之前,userB
提交了查询。 userB
应该得到309--因为当时正在处理查询。
userA
= userB
或userA
<> userB
在这里是无关紧要的,应该只返回309,因为当一个已经在运行时有一个查询请求。这就是用户获得309的唯一时间。
// ============================================= =
EDIT-2:
我知道有并发控制的解决方案。我猜测有一个使用Restful功能。这是一个学术问答。
答案 0 :(得分:2)
@Koos Gadellaa说客户端应该阻止是正确的 第二个请求,直到响应到来。让我解释为什么这是最好的事情。 建筑,它涉及到问题。服务器没有关于两个请求并行到达的原因的上下文感知。因此,依靠带外知识来了解并行请求是不好的。任何带外知识都会产生耦合,这意味着如果您更改系统的一部分工作方式,则必须更改另一部分。 RESTful架构很受欢迎,因为它们减少了耦合。如果同一用户登录到两个客户端,则系统会中断。您永远不想构建具有此类客户端 - 服务器耦合的系统。
关于服务器的责任,良好的编码实践发挥作用,最好的办法是确保服务不受用户的多个并行请求的阻碍。缓存可能是你的朋友。根据查询参数,可以将响应写入磁盘上的缓存文件。客户端将始终使用HTTP 303重定向到缓存文件URL。可以使用304 Not Modified,因此客户端不必两次下载答案。在这种情况下,唯一的带外知识是正确实施HTTP规范,这是明确规定和健全的。
如果服务过载,则相应的响应代码似乎为503。
10.5.4 503 Service Unavailable
由于服务器临时过载或维护,服务器当前无法处理请求。这意味着这是一个暂时的条件,经过一段时间的延迟后会得到缓解。如果已知,则可以在Retry-After报头中指示延迟的长度。如果没有给出Retry-After,客户端应该像处理500响应一样处理响应。
Note: The existence of the 503 status code does not imply that a server must use it when becoming overloaded. Some servers may wish to simply refuse the connection.
由于您从my response here指示我,因此您似乎想知道正确的RESTful方法。这将比上面的解决方案更复杂,我的猜测是你不想采取这条路线,但现在就是。
如果服务器需要与客户端通信正在执行请求以及何时完成请求,则需要为这些概念创建资源。这感觉很奇怪,因为它们存在于HTTP中,并且在更高级别(建筑气味)重新实现它们很奇怪。
- 客户端会将
Request
或Query
资源发布到服务器。此资源的Response
属性为空且{{1}属性为空。服务器将使用Status
属性设置为"处理"的主体进行响应。- 然后,客户端将对此资源执行GET(可能在此处使用长轮询)来检查更新。
- 创建响应后,
醇>Status
属性将链接到响应资源或嵌入响应。
此方法使用资源传达正在发生的事情。因此,唯一的带外知识是资源的有效状态。
答案 1 :(得分:0)
我认为你错了。多次单击的用户是使用前端客户端连接到服务器的用户。因此,客户应确保不会发生多次点击。 Javascript可以完美地抵御这些请求。
根据你的要求说:应该退回309。这是一个并发问题 如果我正确读取您的规范,则与正在执行的数据库查询有关。 请考虑以下代码:
result = do_database_thing();
out = make_up_result(result);
return out;
根据这些规范,唯一的请求是critical section位于do_database_thing上。如果make_up_results很慢,则允许多个请求。所以自然的解决方案是在数据库上使用锁定。如果它应该包含整个query()方法(即不是数据库查询本身),请尽早请求锁定,最后释放锁定。 然后代码变为:
boolean locked = get_lock();
if(!locked) return 302;
result = do_database_thing();
release_lock();
out = make_up_result(result);
return out;