这更像是一个测试助手而不是一个答案,因为这个问题没有提供足够的细节来缩小问题的范围。
我使用Plezi编写了一个简单的测试应用程序。因为我是 plezi 的作者,所以对我来说比学习你的堆栈更容易。
它在我的电脑上完美运行,大约 3Mb 文件需要 79 毫秒。
到 Heroku 的 ~3Mb 往返花费了我的系统 3 秒,在 TCP/IP 预热完成后下降到 ~2.5 秒......
...但是我的网速可能会影响测试(目前我的接收率很低,所以我可能会很慢)。
我不确定我是否可以复制该问题,但您可以使用此答案中的代码来测试您的服务器。
如果往返时间仍然超过 10 秒,则可能是 EC2 堆栈。我认为 10 秒对于 ~500Kb 来说是不合理的。
另一方面,如果往返时间较短,则可能是您测试应用程序或 Ruby 堆栈的方式……在这种情况下,解决方案可能是切换到 plezi (或碘原生 websocket 设计)。
您可以将以下代码粘贴到config.ru
(请记住,您还需要一个带有 gem 的 gem 文件,plezi
可能还需要一个Gemfile.lock
):
# The roundtrip html client
ROUNDTRIP_CLIENT = <<CLIENT_EFO
<html>
<head>
<script src = '/client.js'></script>
</head>
<body>
<input type='file' id='test_f' lable='file to upload'></input>
<button id='test_b'>run test</button>
<div id='output'></div>
<script>
var client;
window.onload = function (e) {
client = new PleziClient();
client.autoreconnect = true;
client.roundtrip = (e) => {
var d = new Date();
e.completed_at = d.getTime();
console.log(e);
document.getElementById('output').innerHTML += "<p>Test for " +
"<a href='" + e.data + "' target='_blank'>" + Math.round(e.data.length / 1024)+ "Kb encoded file</a>" +
" completed in " + (e.completed_at - e.time) + "ms</p>";
}
client.onopen = (e) => console.log("Websocket client open", e);
}
function run_test(e) {
console.log("File submitted.");
reader = new FileReader();
reader.onloadend = function(e)
{
console.log("File loaded, " + e.target.result.length + "bytes... starting test.")
var d = new Date();
client.emit({event: "roundtrip", data: e.target.result, time: d.getTime() });
}
reader.readAsDataURL(document.getElementById('test_f').files[0]);
return false;
}
document.getElementById('test_b').onclick = run_test;
</script>
</body>
</html>
CLIENT_EFO
# require plezi
require 'plezi'
# For security, Iodine limists websocket messages.
# We update the default limit from ~250Kb to ~4Mb.
# This replaces the commandline option: iodine -v -maxms 4194304
Iodine::Rack.max_msg_size = 4194304
# the roundtrip controller... quite simple.
class RoundTrip
# return the roundtrip client.
def index
ROUNDTRIP_CLIENT
end
# echo back the websocket message - we're just testing the round trip.
def on_message data
write data
end
end
# Set the plezi root route to the RoundTrip controller
Plezi.route '/', RoundTrip
# Set the client javascript route - I'm using it as a heler.
Plezi.route '/client.js', :client
# Set Rack to run the Plezi application
run Plezi.app
要从终端运行代码,请使用iodine
命令(它将启动iodine
Plezi 需要的服务器。
编辑
从 git-repo 的链接(在评论中),我意识到 JSON 由服务器解析,然后重新发出。
为了模拟这一点,我更新了示例代码。
这应该类似于 repo 中的代码似乎在做的事情,并且它增加了往返时间,因为 JSON 解析和重新格式化会创建数据的副本,这需要内存分配以及 CPU 时间。
代码中唯一的变化是在RoundTrip
控制器类中,但我将整个内容粘贴为您的复制+粘贴方便。
将以下代码放入您的app.rb
文件中(记得编辑install.sh
以安装plezi
gem):
# The roundtrip html client
ROUNDTRIP_CLIENT = <<CLIENT_EFO
<html>
<head>
<script src = '/client.js'></script>
</head>
<body>
<input type='file' id='test_f' lable='file to upload'></input>
<button id='test_b'>run test</button>
<div id='output'></div>
<script>
var client;
window.onload = function (e) {
client = new PleziClient();
client.autoreconnect = true;
client.roundtrip = (e) => {
var d = new Date();
e.completed_at = d.getTime();
console.log(e);
document.getElementById('output').innerHTML += "<p>Test for " +
"<a href='" + e.data + "' target='_blank'>" + Math.round(e.data.length / 1024)+ "Kb encoded file</a>" +
" completed in " + (e.completed_at - e.time) + "ms</p>";
}
client.onopen = (e) => console.log("Websocket client open", e);
}
function run_test(e) {
console.log("File submitted.");
reader = new FileReader();
reader.onloadend = function(e)
{
console.log("File loaded, " + e.target.result.length + "bytes... starting test.")
var d = new Date();
client.emit({event: "roundtrip", data: e.target.result, time: d.getTime() });
}
reader.readAsDataURL(document.getElementById('test_f').files[0]);
return false;
}
document.getElementById('test_b').onclick = run_test;
</script>
</body>
</html>
CLIENT_EFO
# require plezi
require 'plezi'
# For security, Iodine limists websocket messages.
# We update the default limit from ~250Kb to ~4Mb.
# This replaces the commandline option: iodine -v -maxms 4194304
Iodine::Rack.max_msg_size = 4194304
# the roundtirp controller... quite simple.
class RoundTrip
@auto_dispatch = true
# return the roundtrip client.
def index
ROUNDTRIP_CLIENT
end
# Using Auto-Dispatch, the JSON is parsed and this event is invoked.
def roundtrip msg
# Hash results are automatically converted into JSON and emitted
msg
end
end
# Set the plezi root route to the RoundTrip controller
Plezi.route '/', RoundTrip
# Set the client javascript route - I'm using it as a heler.
Plezi.route '/client.js', :client
# Plezi will start automatically when the script exits
要从终端运行代码,请使用ruby app.rb
命令,就像您的存储库对现有应用程序所做的一样。
虽然旧代码只是提供并“回显”响应,但新代码(看起来几乎相同)还有几个步骤:
使用 Auto-Dispatch,Plezi 框架现在自动解析 JSON 并将事件(“往返”)路由到控制器的方法(roundtrip
)。
该方法接收带有解析数据的哈希并将该哈希返回给 Plezi。
该框架收集哈希,格式化一个 JSON 对象并返回结果(非字符串或哈希结果被忽略)......
...这类似于回购的行为。