收到可能需要很长时间的请求响应

receiving a response of a request which may take long time

提问人:VSB 提问时间:10/25/2017 最后编辑:PhantômaxxVSB 更新时间:3/31/2021 访问量:6691

问:

我将开发一个 android 应用程序,它向服务器发送一些请求。这些请求可能需要很长时间才能在服务器端处理;可能是 10 秒、1 分钟甚至更长时间。 我使用HTTP方法将请求发送到服务器(例如get或post)。我想知道以后如何通知我在服务器上的请求结果?换句话说,考虑到这么长的延迟,我如何从服务器收到我的请求的响应。

可以使用哪种方法或技术来处理这种情况?

更新:我的问题不是关于如何长时间保持HTTP连接打开或如何重试。由于第一个HTTP请求可以用确认之类的东西来响应(意味着您的请求正在进行中),但是我想知道我怎样才能收到很久以前的请求的响应。enter image description here

Android HttpRequest 服务器端 请求-响应

评论

0赞 Octavian Mărculescu 10/25/2017
您是否考虑过使用异步任务在后台线程中运行请求?
0赞 VSB 10/25/2017
@OctavianMărculescu 是的,AsynchTask 将在后台运行以发送 HTTP 请求,但如果服务器需要太多时间来响应,HTTP 请求就会超时。

答:

0赞 Kutlu Ozel 10/25/2017 #1

https://github.com/loopj/android-async-http

用于发出异步 http 请求的好库。

你可以使用

 AsyncHttpClient client = new AsyncHttpClient();
client.get("https://www.google.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // called before request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // called when request is retried
    }
});

评论

0赞 VSB 10/25/2017
那么连接将在请求-响应的所有期间都打开吗?
0赞 Kutlu Ozel 10/25/2017
true,并且您不会冻结主线程。如果你的 api 也以异步方式工作,那么当双方都完成并完成时,你会注意到。
0赞 VSB 10/25/2017
如果服务器需要 15 分钟来响应请求,HTTP 连接将超时,因此连接将断开并且不会收到任何响应。
0赞 Kutlu Ozel 10/25/2017
编辑后 ;你的方法和提问方式是不正确的。您应该将工作分成小块,例如视频流,或者您应该使用类似通知的机制。首先发送带有密钥的请求以触发评估。然后使用此键检查上一个请求是否完成的请求,如果完成,则发送结果,如果没有,请再次检查。
0赞 iaindownie 10/25/2017 #2

如果使用 Volley 处理请求和响应,则可以调整默认超时。

myRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 3, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

默认情况下,我认为DEFAULT_TIMEOUT_MS设置为 2.5 秒,因此在我的示例中,我将其保持打开状态,等待响应 7.5 秒。你可以扩展它,但我建议在扩展得太远之前加快服务器速度?

评论

0赞 VSB 10/25/2017
服务器上的处理请求取决于人为。所以不可能加快速度。顺便说一句,重试很长时间,将导致多次向服务器请求单个请求。
2赞 Nabin Bhandari 10/25/2017 #3

保持插座连接打开超过 1 分钟听起来不是一个好主意。

为此,我建议使用 Firebase Cloud Messaging

只需将数据发布到服务器即可。服务器完成任务后,会将结果发回给应用。

正如您所说,FCM 报文无法保证,FCM 报文的投递失败是很少见的。如果在预期时间内设备中未收到消息,则可以再次调用服务器并请求较旧的服务器调用结果。

评论

0赞 VSB 10/25/2017
FCM 消息不保证会传递到 android 客户端。还有其他可靠的解决方案吗?
0赞 VSB 10/25/2017
这提供了一个很好的解决方案,但我保持问题开放,以找到可能更好的答案。
0赞 Nabin Bhandari 10/25/2017
确定。没关系。:)
0赞 Nikolai 10/25/2017 #4

首先,如果您需要长时间运行任务,最好的选择是使用 android 服务。在你的例子中,你需要使用一个只对你的网络操作持续的服务,所以你需要一个IntentService,这里有一个简单的官方文档来设置你的服务。

之后,您需要在活动中设置一个 BroadcastReceiver,以接收您必须在 intentService 结束时发送的数据。

至于你超时的担忧,@iaindownie确实回答了这个问题。

希望这会有所帮助

评论

0赞 VSB 10/25/2017
正如我@iaindowni解释的那样,由于请求的处理时间很长,HTTP 超时在我的应用程序中的可能性很大。因此,多次尝试会毫无理由地给我的服务器带来负载。我面临的挑战是以一对一的关系发送请求和接收响应,并且不会给客户端或服务器增加任何负载。
0赞 Nikolai 10/25/2017
在这种情况下,您必须使用我认为不再包含在 SDK 中的 apache HTTPClient。然后,您可以控制 connectionTimeOut、requestTimeout、socketTimeOut 等,并避免重试。但是,您必须指定一些最长时间(5 分钟?另一方面,我建议您以某种方式将请求的结果存储在服务器端,并尝试通过另一个 Web 服务定期检索该结果。但我想这不是一个选择,是吗?
1赞 Nikolai 10/25/2017
好的,对不起,你想在没有他要求的情况下将数据发送回设备,对吧?好吧,在这种情况下,您需要像所说的那样@NabinBhandari推送通知。否则,您应该将结果存储在某个位置,然后使用另一个 WS 从设备中检索它。很抱歉误会