- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的应用程序将向我的 tomcat 服务器(启用了 http/2)发送大约 1000 个 POST 请求/分钟,这将轮询给定的 url 并返回 html 和响应时间,我想实现真正的 http/2 多路复用在我的应用程序和 tomcat 服务器之间重用 tcp 连接。我的客户端使用 okhttp,我可以成功建立连接并长时间重用它,但是当请求计数增加时(例如,排队:50,运行:50),响应时间也会增加(它达到 2000 毫秒 - 15000ms 甚至更糟,通常需要 300ms-500ms)。我可以理解这是因为 tcp 连接因请求过多而过载,因此我决定打开多个 tcp 连接并允许它在 tcp 连接之间分配请求负载。我强制客户端使用
打开多个连接Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(100);
dispatcher.setMaxRequestsPerHost(5);
ConnectionPool cp = new ConnectionPool(5, 5, TimeUnit.MINUTES);
在 wireshark 的帮助下,我可以看到打开了 5 个连接,还看到在第一次握手成功后立即关闭了 4 个请求,我不知道这是否是 http/2 多路复用的预期行为。
如果这是预期的行为,我该如何优化它以减少峰值加载时间每个请求的响应时间?
或者是否可以在高峰负载时间使用多个连接来分配负载?
我的示例程序如下,
Security.insertProviderAt(Conscrypt.newProvider(), 1);
sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
}, new java.security.SecureRandom());
sslSocketFactory = sslContext.getSocketFactory();
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(100);
dispatcher.setMaxRequestsPerHost(5);
ConnectionPool cp = new ConnectionPool(5, 1, TimeUnit.DAYS);
okHttpClient = new OkHttpClient().newBuilder()
.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustManager[0])
.dispatcher(dispatcher)
.connectionPool(cp)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
我们使用 conscryt 在 jdk8 本身中启用 ALPN,
try {
String url = "https://localhost:8081/myAent/getOutput?1000000004286_1520339351002_"+System.currentTimeMillis();
String json = "<?xml version=\"1.0\" standalone=\"no\"?><UC mid=\"1000000005011\" pollNow=\"true\" use_ipv6=\"false\" rca=\"0\" rcaFN=\"P|TA|D|J|M\" pFtct=\"\" sFtct=\"\" issecondarydc=\"false\" ssDc=\"false\" nocache=\"1\" storeHtmlResp=\"true\" storeTroubleScrnSht=\"false\" moConfig=\"false\" xconlen=\"8265\" noScreenshotRecheckForSSLErrors=\"true\" avgDnsTime=\"null\" isProxyRequired=\"false\" userroles=\"EVAL_USER\" uid=\"102030230293029021\" retryDelay=\"2\" retry=\"true\" idcLocUrl=\"http://localhost:8080/app/receivemultipartdata\" isRemoteAgent=\"true\" sendHeaders=\"false\" api=\"ab_345nnn4l4lj4lk23nl4k23342lk4l23j4\" ut=\""+(System.currentTimeMillis()+"")+"\" mt=\"URL\" dctimeout=\"70\" pollinterval=\"1440\" locid=\"48\" log=\"1\" currentstatus=\"1\" postUrl=\"https://example.com\"><Url acc=\"\" forced_ips=\"\" use_ipv6=\"false\" client_cert=\"\" mid=\"1000000005011\" sotimeout=\"60\" ua=\"\" ds=\"117.20.43.94\" ucc=\"\" md=\"false\" client_cert_pass=\"\" context=\"default\" unavail_alert=\"\" ssl_protocol=\"\" avail_alert=\"\" enabledns=\"false\" enableBouncyCastle=\"false\" cc=\"false\" a=\"https://www.example.com/tools.html\" upStatusCodes=\"\" regex_alert=\"\" probeproxy=\"false\" m=\"G\" keyword_case=\"0\" regex=\"\" rbc=\"\" t=\"30\" lc=\"English\"><PD></PD><CH hn=\"\" hd=\"_sep_\" hv=\"\"/><AI ps=\"\" un=\"\"/></Url></UC>";
RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"), json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
long nanoStartTime = System.nanoTime();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("okhttp3:: Request failed"+ e);
}
@Override
public void onResponse(Call call, okhttp3.Response responseObj) throws IOException {
try (ResponseBody body = responseObj.body()) {
long nanoEndTime = System.nanoTime();
long nanoDiffTime = TimeUnit.NANOSECONDS.toMillis(nanoEndTime - nanoStartTime);
System.out.println("okhttp3:: Succeded response ***"+body+"$$$");
System.out.println("okhttp3:: Request Succeded protocol ***"+responseObj.protocol()+"$$$, time is "+nanoDiffTime);
}
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
如何优化 okhttpclient 以使用多个 tcp 套接字/连接来实现 http/2 多路复用以分配请求负载。
客户:Tomcat Apache - 9.0.x,JDK-8,Http 库 - Okhttp3,操作系统-Ubuntu/Centos,安全提供程序 - Conscrypt(用于在 jdk 8 中支持 ALPN)。
服务器:Tomcat Apache - 9.0.16,JDK -10.0.1,操作系统-Ubuntu/Centos,OpenSSL - 1.1.1a 用于 TLSv1.3 支持
最佳答案
您看到的是 OkHttp 中连接合并的结果。 OkHttp 事先不知道是否会建立 HTTP/2 连接(与 HTTP/1.1 相比),因此允许连接的 setMaxRequestsPerHost 值继续进行。目前* 没有客户端负载平衡,因此它们会快速合并到一个连接,这就是您所看到的。
目前,您可以通过多个客户端或仔细管理完全不同的主机和连接来实现这一点。 n.b OkHttp 将在这里对你不利,并针对单个连接优于多个连接的典型情况进行优化,例如SSL 证书指定了重叠的主题备用名称
* 关注此问题以获得支持https://github.com/square/okhttp/issues/4530
关于java - Okhttp3、http2多路复用POST请求在负载高峰期响应时间高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54849941/
我正在实现 Server-Sent Events使用 OkHttp 的库。服务器发送事件的工作原理是与服务器保持开放的 HTTP 连接,在该服务器上,“事件”可以流式传输回客户端。连接只会在错误或客户
我需要用 OkHttp 重现错误,这样我就可以提交错误或在 StackOverflow 上提问。 无需大量设置即可执行此操作的最简单方法是什么? 我读过 https://stackoverflow.c
我需要用 OkHttp 重现错误,这样我就可以提交错误或在 StackOverflow 上提问。 无需大量设置即可执行此操作的最简单方法是什么? 我读过 https://stackoverflow.c
我正在尝试使用 OkHttp 与 HTTP/2 服务器进行通信客户端。 添加到 Maven POM: com.squareup.okhttp3 okhttp 3.2.0 这是我的
我在使用我的应用程序时不断在 Logcat 中看到以下日志行: 19098-19147/ W/OkHttpClient: A connection to was leaked. Did you fo
我的团队正受此困扰issue使用 slack 集成来上传文件,因此根据该问题中的评论,我想限制我们的 Kotlin 实现中的请求。 我正在尝试集成 Okio Throttler在 OkHttp 拦截器
如何验证 okhttp 是否成功协商了 http/2 而没有使用 https/1.1?我可以检查回复中的一些信息吗? 谢谢, -托尼 最佳答案 仅供引用,因为 okhttp 3.0 左右 OkHttp
我想提出一个请求并强制它使用 Protocol.HTTP_2。 我尝试了下面的代码: import okhttp3.{OkHttpClient, Protocol, Request} import s
我不太熟悉 OkHttp 库,我对它应该如何用于异步请求有一些疑问。 对于 Android 编程,我将 android 库用于 http,并将 asyncTask 用于某些请求。 但是因为我想尝试 O
我在我的项目中使用 Retrofit-1.6.0 + okhttp-2.0.0-RC1 。当我运行项目时出现错误。 java.lang.RuntimeException: Retrofit detec
OkHttpClient 的默认行为是将 keep-alive 设置为 true。对于我们的特定用例,我需要将其设置为 false。 我没有在 Java 源代码中找到任何设置来执行此操作。 有人遇到过
我试图让 OkHttp 在我的 Android Studio 项目中工作,我创建了一个类并从这里粘贴以下代码:https://github.com/square/okhttp/blob/master/
我注意到 OkHttp 在 Android 5.0+ 中通过 ALPN 支持 h2。 来自 some article ,我了解到我们可以对 http/2 请求使用 NPN 协商。 我可以通过 NPN
我知道,Retrofit 在内部使用 OkHttp。但是,我可以看到一些开发人员提供了以下方法的应用 return new Retrofit.Builder() .baseUrl(Bu
我正在努力让 Android 上的 OkHttpClient 使用自定义证书发出 HTTPS 请求,同时绑定(bind)到特定网络接口(interface)的本地地址。我目前对此的尝试使用以下 OkH
我有一个用于 https 连接演示的 native android 应用程序,我遇到了这样的异常:: 我的连接代码很简单: URL url = new URL("https://192.168.1.5
我正在重写 EventListener 中的 dnsEnd() 函数: @Override public void dnsEnd(Call call, String domainName, L
我有okhttp的android多项目设置,作为多个项目的一部分 在项目A中,okhttp包含在源代码中。 在项目B中,okhttp带有库依赖项的一部分。 构建时,出现以下错误。 Execution
我正在尝试使用pesapal向我的应用程序添加付款但遇到问题,我将它们的依赖实现'com.pesapal.android:pesapalandroid:1.0.5'添加到我的应用程序中,从那时起我就一
我只是尝试使用 OkHttp但是当我将我的 gradle 文件与 Android Studio 同步时,我遇到了以下问题: Error:Failed to find: com.squareup.okh
我是一名优秀的程序员,十分优秀!