Jersey客户端向Jersey资源发送重复请求

7
我们最近升级了服务器和客户端的Jersey版本,从1.x升级到了2.22.1版本。现在我们发现Jersey会时不时的发起或接收两个请求。
其中,“时不时的”指的是每几千次请求中就会出现一次。 使用Jersey 1.x时,我们从未遇到过这个问题。 目前还不清楚这是客户端还是服务端的问题。 客户端日志仅显示单个POST请求和响应(如下所示)。 而服务端日志则显示两个POST请求和响应(如下所示)。
我可以通过重复执行客户端的POST请求来复现问题。每个请求都会发送一个独特的“name”,并将其保存在服务器上。当我尝试多次保存相同的“name”时,由于唯一性约束违规,我就知道我们已经收到了重复的请求。因为日志确认了Jersey收到了两个相同“name”的POST请求,所以我排除了代码的其他部分的错误。
我已经在服务器上启用了org.glassfish包的跟踪日志,并在客户端注册了LoggingFilter()。
客户端只显示了一个POST请求和响应:
Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8291 * Sending client request on thread main
8291 > POST http://localhost:9797/my-webapp/v1/data-feeds/
8291 > Accept: application/json
8291 > Content-Type: application/json

Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8291 * Client response received on thread main
8291 < 200
8291 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate
8291 < Content-Length: 181
8291 < Content-Type: application/json
8291 < Date: Wed, 22 Jun 2016 00:02:51 GMT
8291 < Expires: 0
8291 < Pragma: no-cache
8291 < Server: Apache-Coyote/1.1
8291 < Set-Cookie: JSESSIONID=CFF556E7FCDB5B1F644BA04603364DFD; Path=/my-webapp/; HttpOnly
8291 < X-Content-Type-Options: nosniff
8291 < X-Frame-Options: DENY
8291 < X-XSS-Protection: 1; mode=block

服务器显示同一“名称”有两个POSTS:
Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8293 * Server has received a request on thread http-bio-9797-exec-21
8293 > POST http://localhost:9797/my-webapp/v1/data-feeds/
8293 > accept: application/json
8293 > authorization: Basic YWRtaW46bmltZGE=
8293 > connection: keep-alive
8293 > content-length: 181
8293 > content-type: application/json
8293 > host: localhost:9797
8293 > user-agent: Jersey/2.22.1 (HttpUrlConnection 1.8.0_31)

2016-06-21 18:02:51,964 [INFO] [c.m.c.r.r.MyResource] Received POST request /data-feeds with args [FeedData{name='pool4146'}]
Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8294 * Server has received a request on thread http-bio-9797-exec-97
8294 > POST http://localhost:9797/my-webapp/v1/data-feeds/
8294 > accept: application/json
8294 > authorization: Basic YWRtaW46bmltZGE=
8294 > connection: keep-alive
8294 > content-length: 181
8294 > content-type: application/json
8294 > host: localhost:9797
8294 > user-agent: Jersey/2.22.1 (HttpUrlConnection 1.8.0_31)

2016-06-21 18:02:51,978 [INFO] [c.m.c.r.r.MyResource] Received POST request /data-feeds with args [FeedData{name='pool4146'}]
Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log

INFO: 8293 * Server responded with a response on thread http-bio-9797-exec-21
8293 < 200
8293 < Content-Type: application/json

Jun 21, 2016 6:02:51 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8294 * Server responded with a response on thread http-bio-9797-exec-97
8294 < 200
8294 < Content-Type: application/json

如果还有其他相关的配置信息,请告诉我。我们正在使用Tomcat 7.x和Jackson进行序列化/反序列化。


嗨,你有解决这个问题的方法吗?我也遇到了同样的问题,我正在使用jersey 1.4 jar。 - user1397770
@user1397770 没有解决办法,但是Jersey 1.x与2.x非常不同。我正在使用2.x版本。 - Justin
@Justing,我想知道升级jersey jar文件是否有助于解决这个问题...请看一下我的日志http://stackoverflow.com/questions/39386268/jax-rs-rest-servlet-error - user1397770
请问您能否提供服务器函数原型?(包括PUT/POST注释等) - Ebru Yener
3个回答

1
作为Bastian Baist答案的一部分,解决方案未包含在内,我将在此处发布。似乎Jersey bug跟踪器已经移动到GitHub,因此作为参考,这是新的且可用的链接:https://github.com/jersey/jersey/issues/3526 要解决此问题,可以将以下内容添加到jersey/core-client/src/main/java/org/glassfish/jersey/client/authentication/HttpAuthenticationFilter.java中:
static boolean repeatRequest(ClientRequestContext request, ClientResponseContext response, String newAuthorizationHeader) throws IOException {
// If the failed response has an entity stream, close it. We must do this to avoid leaking resources
// when we replace the entity stream of the failed response with that of the repeated response (see below).
// Notice that by closing the entity stream before sending the repeated request we allow resources allocated
// to the failed request (e.g., the HTTP connection) to be reused, if possible, for the repeated request.
if (response.hasEntity()) {
    response.getEntityStream().close();
    response.setEntityStream(null);
}

Client client = request.getClient();

并删除这行代码:

 Client client = ClientBuilder.newClient(request.getConfiguration());

令人烦恼的是,Jersey的维护者似乎没有解决这些问题。


0

这似乎是我们遇到的相似错误。我们花了很多时间来解决它。

我们在https://java.net/jira/browse/JERSEY-3254上发布了此问题并附上了修复程序。它主要位于 HttpAuthenticationFilter 中,导致摘要身份验证出现故障。结果经常会获得一些错误的 401 代码或 StreamClosed 异常。我不会将我的解决方案复制到此帖子中,我认为 JIRA 问题不会被删除。


相反,您必须在此处发布您的解决方案。仅包含链接的答案会受到严厉谴责。请参阅https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers - Peter G
1
很遗憾,链接无效。您能否发布您发现的解决方案? - KeaganFouche

0

我遇到了同样的问题,但是我无法复现这个问题。你尝试过关闭ClientResponse流吗?让我知道这个方法是否有效。

Client client = new Client();
WebResource resource = client.resource(restUrl);
final ClientResponse response = resource.get(ClientResponse.class);
response.close();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接