0

目前,我正在使用 websockets 将图像发送到我的服务器,对其进行处理,然后将其发回。具体来说,我将 Ruby 与 Sinatra 和 sinatra-websocket 一起使用。

在我的开发服务器上,将图像发送到服务器并在不进行处理的情况下检索准确的图像大约需要 2 秒。

在 AWS-EC2 实例上,这大约需要 15 秒。我发送的图像文件约为 500kb。我的上传和下载速度远高于此。

我怎样才能加快这个过程?这是一种来回发送图像的幼稚方式吗?

编辑:要复制我的问题,您可以在 AWS-EC2 免费套餐实例中克隆并运行我的存储库。

4

1 回答 1

0

这更像是一个测试助手而不是一个答案,因为这个问题没有提供足够的细节来缩小问题的范围。


我使用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命令(它将启动iodinePlezi 需要的服务器。


编辑

从 git-repo 的链接(在评论中),我意识到 JSON 由服务器解析,然后重新发出。

为了模拟这一点,我更新了示例代码。

这应该类似于 repo 中的代码似乎在做的事情,并且它增加了往返时间,因为 JSON 解析和重新格式化会创建数据的副本,这需要内存分配以及 CPU 时间。

代码中唯一的变化是在RoundTrip控制器类中,但我将整个内容粘贴为您的复制+粘贴方便。

将以下代码放入您的app.rb文件中(记得编辑install.sh以安装plezigem):

# 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 对象并返回结果(非字符串或哈希结果被忽略)......

...这类似于回购的行为。

于 2017-04-15T20:54:14.860 回答