【问题标题】:Memory leak/constant high CPU usage when running Phoenix in IIS on Windows在 Windows 上的 IIS 中运行 Phoenix 时内存泄漏/持续高 CPU 使用率
【发布时间】:2017-08-02 21:13:46
【问题描述】:

我正在尝试制作一个小型 Web 应用程序的原型,看看是否可以使用 Phoenix 和 Elixir 构建一些内部网 Web 应用程序,供我公司的同事使用。我们一直是典型的 Microsoft .NET 商店,但我对使用其他一些技术很感兴趣,Elixir 和 Phoenix 就是其中的两个。

我有一个运行Windows 10IIS 8 的虚拟机。我还在 VM 上安装了 HttpPlatformHandler 以运行 Phoenix 应用程序并从 IIS 向它传递请求(这是有原因的,我稍后会谈到)。

当我在 Windows 上独立运行我的 Phoenix 应用程序时,它运行良好。我没有看到任何问题。当我使用HttpPlatformHandler 和 IIS 运行我的 Phoenix 应用程序时,我看到 erl.exe 进程不断运行并消耗大约 35-40% 的 CPU(我运行的是 2 个内核和 8GB RAM在虚拟机上)。我还看到记忆不断增长,没有停止。几分钟后,它会超过 1GB 并移动到 2GB(我正在使用 Process Explorer 观察内存使用情况)。 Phoenix 应用程序上没有负载或活动请求。这在开发和生产环境中都会发生。

我想在 IIS 后面运行 Phoenix,因为它是一个 Intranet 应用程序,它将在 Windows 域上运行,并且大多数用户将是 Windows 用户。我创建了一个插件,它将从HttpPlatformHandler 添加到转发到 Phoenix 进程的请求中的X-IIS-WindowsAuthToken HTTP 标头读取 Windows 用户令牌,并且我正在使用一组 NIFS 调用 Windows API 以获取已验证用户的 Windows SID 和域\用户名,以便建立会话并授权用户。

有没有人尝试过这个并看到同样的问题?我对 Elixir 和 Phoenix 调试比较陌生,希望能得到一些提示,了解我可以做些什么来尝试弄清楚 Erlang 运行时为什么这样做,或者如何确定它是否是我在代码中正在做的事情。

我不确定是不是我,因为我在一个使用 mix phoenix.new 新生成的普通 Phoenix 应用程序上看到了这种情况。

作为参考,这是我的 Phoenix 应用程序的 web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
    </handlers>
    <httpPlatform processPath="C:\Projects\neucode\run.bat"
        arguments=""
        stdoutLogEnabled="true"
        forwardWindowsAuthToken="true">
      <environmentVariables>
        <environmentVariable name="MIX_ENV" value="prod"/>
      </environmentVariables>
    </httpPlatform>
  </system.webServer>
</configuration>

我的run.bat 文件:

mix phoenix.server

我非常感谢任何人可以提供的任何帮助或建议。如果我能提供任何其他有助于诊断问题的信息,请告诉我。

提前谢谢你。

更新

感谢this gist,我知道如何使用 Observer 连接到我在 IIS 中运行的 Phoenix 应用程序。看起来问题进程是用户进程:

我开始跟踪这个进程和它所链接的端口,我看到一个连续的流,我猜是接收带有空数据的事件:

我猜测这是内核用户进程。有谁知道我如何弄清楚那个端口是什么以及为什么它会发送连续的事件流?

【问题讨论】:

  • 如果这种组合能够奏效,我会有点惊讶,因为 Phoenix 和 IIS 一样是 Web 服务器。
  • @OnorioCatenacci 为什么它不能工作?这就像使用 NGINX 或 Apache 作为代理服务器一样。不过它确实有效。我唯一看到的是奇怪的 CPU 和内存问题。但是 Web 应用程序本身可以正常工作。
  • 我只想说,将 Phoenix 与 IIS 包装在一起,这样您就可以获得 AD 身份验证(这听起来像是您正在尝试做的事情)让我觉得像是一个杂物——不管可行性或缺乏。
  • @OnorioCatenacci 这是原因之一,但肯定不是唯一的原因,我不会批评它是一个杂物。在我看来,这有点不合适。这是一个公平的用例,尤其是在目标平台中的 Windows 和 Phoenix 不应该像这样运行任何问题的情况下。我要指出,他们在指南here 中记录了使用 NGINX 和 Apache 的这种配置。在 Windows 身份验证方面,如果您有任何替代方法,我会非常开放。
  • 我认为在这种情况下唯一的非 hacky/non-kludgy 解决方案是为 AD 身份验证编写一个 NIF。 IIS 和 Phoenix 似乎都服务于相同的目的(就像 Nginx 和 Apache 一样),因此将它们结合起来似乎有点笨拙。

标签: iis elixir phoenix-framework


【解决方案1】:

我想出了解决办法。这就是我对 Elixir 和 Erlang 的新手身份发挥作用的地方。当您运行 Elixir/Erlang 应用程序时,Erlang 用户服务器开始处理应用程序的标准 I/O。在我的问题更新的第二张图片中,您可以看到端口 控制“0/1”。我现在的理解是这基本上意味着 0 == 标准输入和 1 == 标准输出。

使用HttpPlatformHandler 运行时的问题是 Phoenix 应用程序在没有 shell 的情况下运行,并且永远不会通过标准输入进入任何内容。因此,当您使用默认设置运行时,标准输入基本上会用一堆空数据消息淹没用户服务器。

解决方案是告诉 Erlang VM 和用户服务器忽略标准输入。在我的 run.bat 脚本中,我正在运行 mix phoenix.server,但基于我用来命名节点以便我可以将 Observer 附加到它的要点,我将我的 run.bat 脚本更改为:

elixir --name phoenix@127.0.0.1 --cookie PUT_COOKIE_HERE --erl "-noinput" -S mix phoenix.server

-noinput 标志似乎告诉 Erlang VM 永远不要从标准输入中读取。将-noinput 传递到命令行后,内存问题就消失了,空闲时 CPU 使用率通常低于 0.2%。 CPU 和内存似乎与 Phoenix 应用程序从 IIS 之外的控制台运行一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    相关资源
    最近更新 更多