问题
使用 YouTube Data Api v3 将视频从我的树莓派上传到 YouTube 速度太慢。我得到的最大速率是 120 KB/s。我希望能够实现高达 1MB/s 的速率。
为什么我认为 SSL 是问题所在
为了将视频上传到 YouTube,我曾经运行一个小的 java 程序,我可以在 Raspberry Pie 上运行一整夜以节省电量。它连接到 YouTube 数据 API v2。我有三个互联网连接,最快的是 LTE 移动连接。有了那个我的旧应用程序可以以 1 兆字节/秒的速度上传(它非常可靠,直到我的 30GB 数据用完为止,这就是为什么我只在紧急情况下使用它) .
现在我已经为我的应用程序创建了一个后续应用程序,它使用 API v3。与 v2 API 相比,现在上传也使用 HTTPS 连接。但是现在我无法以超过 120 KB/s 的速度上传。
经过数小时令人沮丧的调试后,我认为问题出在 SSL 造成的 CPU 负载上。为了验证这一点,我在我的计算机上启动了一个企业级 caugh HTTPS 服务器(通过以太网连接到树莓派):
# create a self signed certificate (answer all the question it asks with default)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 100 -nodes
# Run the server on port 5454:
openssl s_server -accept 5454 -key key.pem -cert cert.pem > /dev/null
我组装了一个使用 Apache HttpClient 4.3 的小型 Java 程序(就像我的应用程序一样)并执行了视频“上传”:
final ProgressReportingHttpEntity entity = new ProgressReportingHttpEntity(new FileEntity(SOME_VIDEO_FILE, ContentType.APPLICATION_OCTET_STREAM));
request.setEntity(entity);
HttpClientBuilder
.create()
.setSSLSocketFactory(
new SSLConnectionSocketFactory(
new SSLContextBuilder()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build(),
new AllowAllHostnameVerifier()
)
)
.build().execute(request);
使用此设置,我的笔记本电脑可以向自身传输 60MB/s(12% 的 CPU 用于 Java(我的 i7 的一个内核),8% 用于 OpenSSL)。
树莓派仍然可以传输 1MB/s(这已经足够快了)。然而据我了解this page here ,googleapis-Server 将首选密码 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
。因此,我像这样重新启动了本地服务器:
openssl s_server -accept 5454 -key key.pem -cert cert.pem -cipher ECDHE-RSA-AES128-GCM-SHA256 > /dev/null
宾果游戏!我不会得到比 120KB/s 更好的传输速率。
我尝试使用不同的密码,在 apache HTTP 客户端中明确设置支持的密码,例如密码 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
表现非常好,达到了 1.3MB/s。
问题
我该怎么办?哪种密码可以在性能和安全性之间提供良好的平衡?在比较支持的密码图表和盲目猜测后,我认为 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
可能是一个不错的选择,并且会得到 google 的支持。但实际上它看起来不是(在 apache http 客户端中设置此密码可以与我的测试服务器通信,但与 google 中断)。
或者我还能做些什么来加快 SSL 吞吐量?例如。是否有一个 ARM 优化的 SSL 库,我可以以某种方式将其注入(inject) JRE(以防 Java 8 ARM JRE 尚未包含此类内容)?
最佳答案
你一定是在某个时候误读了什么。当您尝试密码 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
时,您可能真的想尝试 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
(它们看起来确实很相似)。
像这样初始化您的 http 客户端:
return HttpClientBuilder.create()
.disableAutomaticRetries()
.setSSLSocketFactory(
new SSLConnectionSocketFactory(
new SSLContextBuilder().build(),
null,
new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" },
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
)
)
.build();
根据我的测试,这将足够快,可以在你的树莓派上以 1MB/s 的速度上传。
很遗憾,我不是安全专家,我无法告诉您这个选择对您的安全意味着什么。另外,如果您仅支持单个密码,我不知道它会使您的应用程序变得多么脆弱。
关于java - Raspberry Pi 上的 HTTPS 太慢了。我该怎么办?我应该选择哪种密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25207648/