【问题标题】:OkHttpClient with Mobile Carrier issueOkHttpClient 与移动运营商问题
【发布时间】:2020-12-17 09:19:43
【问题描述】:

我的应用程序 API 执行奇怪的行为。我的一个实时应用程序的 api 预期响应时间为 2 到 3 秒,但响应时间很长!

测试用例:

  1. 适用于 WIFI =
  2. 与 Airtel 运营商合作 =
  3. 与 Jio 运营商合作 =
  4. 在其他国家网络工作 =
  5. 在移动浏览器中使用 Vodafone Idea 运营商 =
  6. 使用 Vodafone Idea 载体的 IOS 应用程序使用相同的 API =

主要问题:Vodafone Idea 运营商 使用 App = 非常慢

案例 1。

 URL url = new URL("https://example.com");
                urlConnection = (HttpsURLConnection) url.openConnection();
                urlConnection.setReadTimeout(10000);
                urlConnection.setConnectTimeout(10000);
                int code = urlConnection.getResponseCode();
                if (code !=  200) {
                    throw new IOException("Invalid response from server: " + code);
                }

                BufferedReader rd = new BufferedReader(new InputStreamReader(
                        urlConnection.getInputStream()));
                String line;
                while ((line = rd.readLine()) != null) {
                    Log.e("data", line);
                }

结果:

  • 第一次 40 到 50 秒。
  • 在每次下一个连续调用时,它都会按照预期在 2 到 5 秒内返回。

案例 2:

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

        Request.Builder requestBuilder = new Request.Builder()
                .url("https://example.com")
                .addHeader("Content-Type", "application/json");
        Request request = requestBuilder.build();
        Log.e("APi", "REQUEST: "+request.toString());

        Call call1 = okHttpClient.newCall(request);
        call1.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.e("APi", "APi Failed");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Log.e("APi", "APi isSuccessful:" + response.isSuccessful());
                Log.e("APi", "Response:" + response.body().string());
            }
        });

结果:

  • 每次需要 40 到 50 秒。

案例 3:

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.SECONDS).build();
    
            Request.Builder requestBuilder = new Request.Builder()
                    .url("https://example.com")
                    .addHeader("Content-Type", "application/json");
            Request request = requestBuilder.build();
            Log.e("APi", "REQUEST: "+request.toString());
    
            Call call1 = okHttpClient.newCall(request);
            call1.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    Log.e("APi", "APi Failed");
                }
    
                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e("APi", "APi isSuccessful:" + response.isSuccessful());
                    Log.e("APi", "Response:" + response.body().string());
                }
            });

结果:

  • 每次需要 5 到 6 秒。

注意:我害怕在应用程序中使用 .connectTimeout(1, TimeUnit.SECONDS) 作为 1 秒它开始给出更多的 api 失败并且看起来也不是正确的解决方案。

更新案例研究:

https://github.com/square/okhttp OkHttpClient 的详细调试。 它给出了大约 4 次以下错误。
failed to connect to xxx.com/2001:4860:4802:36::15 (port XXX) from /2402:3a80:1b8f:ca21:847:21a8:5ffc:fc30 (port XXX) after 10000ms  

包okhttp3.internal.connection.RealConnection 类。 尝试建立 connectSocket 但出现错误。

-> 将“www”www.example.com 添加到我的域后。 okhttp 库的响应时间大约从 40 秒变为 12 秒。

【问题讨论】:

  • 您应该使用监听器收集一些事件并将它们添加到您的问题square.github.io/okhttp/events
  • @YuriSchimke 谢谢。在调试时添加了异常。请注意,问题仅出现在 1 个特定网络上!
  • 在我的应用程序中,我们还有用于服务器的 Google Cloud Engine 和使用 firebase 存储和云功能@YuriSchimke
  • 有趣的问题,但我担心我们错过了全貌。难道是你在你的应用程序中建立了很多其他的连接?我认为您提供的这段代码无法自行重现您所描述的问题,因此创建一个最小的可重现示例会很有帮助。
  • 您的消息显示 IPv6 地址。运行速度更快的场景是使用 IPv4 还是 IPv6?

标签: android tcp socket.io httpurlconnection okhttp


【解决方案1】:

很难看到全貌,因为您没有解释如何执行后续连接。您完全有可能重用现有连接。默认情况下,HTTP/1.1 使连接保持活动状态。

检查使用 纯文本 HTTP 与 HTTPS 是否有所不同也可能很有趣,因为使用 HTTPS 的连接设置成本更高。您的客户还可以根据返回的证书进行更多验证。

如果更改主机名有很大的不同,那么我肯定会查看名称解析器是如何在系统上配置的

我还会捕获网络流量,看看什么需要很长时间。 tcpdump 是你的 朋友或者你总是可以考虑使用wireshark

正如其他人所建议的那样,您可能还希望在盒子上禁用 IPv6 堆栈以排除问题的根源。

【讨论】:

  • 我和有网络知识的队友一起检查过,我们发现即使是终端中的“traceroute >”也需要太多时间!上结论。我使用了“HttpsURLConnection”,并且第一次将 setConnectTimeout 保持 1 秒。对于任何其他下一次调用,它将定期超时!
  • traceroute 可能会产生误导,尤其是在您使用主机名与 IP 地址时。一些网络设备也可能会阻塞一些流量。最好的选择是网络流量分析器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-01
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多