【问题标题】:Cowboy web server - improve performanceCowboy Web 服务器 - 提高性能
【发布时间】:2014-10-08 09:03:14
【问题描述】:

Cowboy 是用 erlang 编写的网络服务器。它为每个请求生成新进程,而不是使用该进程处理后续请求,如果 HTTP 流水线(一个接一个地在同一个套接字上发送多个请求,而不等待响应,并假设响应将以与发送请求相同的顺序发送回)被客户端使用。

这很好,但是如果你想使用那个 webserver 来构建实时 web 应用程序,它有一个问题,那就是当 socket 因为客户端网络问题而关闭时,代表服务器上那个 socket 的进程被终止.这意味着您不能使用该进程来存储某些会话数据(因为在实时 Web 应用程序中,您可能希望在 http 请求结束后进行(例如,如果使用长轮询)并且将某些状态与连接的客户端相关联即使http请求已经结束,也可以将他视为“他在线”。

在 sock.js 中,它通过为每个客户端(每个会话 id)生成一个多进程来解决。

因此,如果您有 2000 个使用 websockets 的客户端,您将拥有大约 4k 个进程(一个来自牛仔的进程代表该套接字,另一个用于保持会话状态以防牛仔进程将被终止(例如,由于网络问题)。

问题是:我在 erlang 中相对较新,所以我不知道它在性能改进问题上是否有意义,但我正在考虑稍微重写那个 Cowboy 网络服务器表示实时连接的进程在我想要它之前不会结束(即使底层的 websocket 套接字将被终止,该进程也将处于活动状态)。

这将消除为每个客户端增加一个会话进程的需要。因此,您将只有 2000 个进程,而不是 4000 个进程。它可以成为 erlang 中巨大的性能提升器吗?

【问题讨论】:

  • 请记住,Erlang 进程与 OS 进程完全不同。 Erlang 进程并不昂贵,最好将其视为结构化计算的工具。牛仔重写很可能对性能没有帮助。如果您的唯一目标是减少进程数量,甚至可能会受到伤害。
  • 你为什么用 Elixir 标记这个问题?
  • @OnorioCatenacci: 好吧,它们都在 erlang vm 上运行,而且这个问题即使对于长生不老药也是有效的,但如果你愿意...
  • 你误会我了。我问你为什么用 Elixir 标记这个问题,因为我认为你可能忘记添加一些额外的 Elixir 特定细节。
  • 也许您可以尝试将会话数据存储在 ETS 中,看看这是否足以满足您的需求。我觉得这将是一种常见的方法。

标签: erlang cowboy


【解决方案1】:

Erlang 非常擅长处理进程,但是,太多的东西都不好。使用进程作为会话的直接映射不是一个好主意。为什么不按逻辑去做呢?我假设你可以拥有一些内存存储空间,比如ETS,甚至是mnesia

如果使用Web Sockets 进行通信,则每个用户都通过一个这样的进程连接,但是,您只需将某个随机唯一的Session Key 映射到每个单独的进程,从而映射到每个单独的用户。

-记录(客户端,{web_sock_pid,session_key,用户名})。

如果进程退出,并且客户端有办法重新连接,一旦它重新识别自己为同一用户,那么,会话密钥仍然保持,但附加进程的pid已经改变。没关系。

如果不是 web 套接字,而只是 HTTP REST/JSON/JSONP/XML services ,那么它甚至非常简单。在 RAM 中使用 ETS 表。存储一个新会话,定义该会话的参数存储在 RAM 中,然后对于每个请求,会话密钥可以连同其他参数一起出现。消息传递是通过彗星或客户端的频繁检查。

【讨论】:

    【解决方案2】:

    如果你问我,听起来你正在做一些过早的优化。

    Erlang 进程非常便宜。您不必担心会产生太多进程。

    每个 websocket 使用两个进程编写它,然后进行一些测量以查看它在哪里使用最多的内存并浪费最多的 cpu 周期。

    【讨论】:

      猜你喜欢
      • 2013-04-18
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-05
      • 2021-04-18
      • 1970-01-01
      相关资源
      最近更新 更多