elixir - Elixir shell 中的 Application.stop(...)

标签 elixir erlang-otp cowboy

我正在 Elixir 中使用 Plug 和 Cowboy 和 mix 编写一个简单的应用程序。执行后:

$ iex -S mix

应用程序启动。如果我执行

iex(1)> Application.start(:web)
{:error, {:already_started, :web}}

我得到了预期的输出。但是,当我尝试使用以下命令停止应用程序时:

iex(2)> Application.stop(:web)
:ok

我得到了 :ok 但随后我收到了很多消息,包括以下内容:

iex(3)>
09:36:43.689 [info]  Application web exited: :stopped

09:36:43.691 [error] GenServer #PID<0.189.0> terminating
** (stop) killed
Last message: {:EXIT, #PID<0.187.0>, :killed}
State: {:state, {#PID<0.189.0>, :ranch_acceptors_sup}


:undefined, 1, 5, [], 0, :ranch_acceptors_sup, [ServeRequests.HTTP, 100, 
:ranch_tcp, [port: 4000]]}
09:36:43.691 [error] Failed to start Ranch listener ServeRequests.HTTP in :ranch_tcp:listen([port: 4000]) for reason :eaddrinuse (address already in use)
09:36:43.691 [info]  Application ranch exited: shutdown
nil

我在代码中做错了什么吗?这是正常行为吗?

mix.exs 文件的内容如下:

defmodule Web.Mixfile do
  use Mix.Project

  def project do
    [app: :web,
     version: "0.1.1",
     elixir: "~> 1.2",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  def application do
    [applications:
        [:logger, :cowboy, :plug],
        mod: {Web, []}
    ]
  end

  defp deps do
  [{:cowboy, "~> 1.0.3"},
  {:plug, "~> 1.1.2"}]
  end
end

lib/web.ex 的内容如下:

defmodule Web do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(Web.Router, [])
    ]

    opts = [strategy: :one_for_one, name: Web.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

谢谢, 米哈里斯。

最佳答案

这在文档中有点子记录,我现在也看到我应该在 EiA 中解释这一点(我的错)。要点是您应该使用 Plug.Adapters.Cowboy.child_spec将服务器正确插入监管树中。然后,服务器将随应用程序一起正确停止。

以下是您的示例中的外观(在 web.ex 中):

children = [
  Plug.Adapters.Cowboy.child_spec(:http, Web.Router, [])
]

这样,您就可以完全摆脱 my_web_startWeb.Router.start_server 函数。

在 shell 中尝试它会给我:

iex(1)> Application.stop(:web)
:ok
16:44:29.929 [info]  Application web exited: :stopped

iex(2)> Application.start(:web)
:ok

之后我可以再次访问该页面。

关于elixir - Elixir shell 中的 Application.stop(...),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36907239/

相关文章:

arrays - 在 Elixir 中从列表中查找索引

erlang - 在 erlang 中采用 gen_server 架构有困难

routes - 有约束的牛仔路由不断失败

elixir - Phoenix 混合任务上的 HTTPoison ArgumentError

javascript - javascript 和 Elixir 中的 Y 组合器实现

postgresql - Elixir : check if postgresql map column has key

erlang - 节点未运行,氮

web-services - Elixir - Simple Plug 示例在每次请求时两次调用调用方法

erlang - 使用 websocket(Erlang、RabbitMQ、Websocket、Gen_bunny、Cowboy)向所有连接的用户广播消息

javascript - 使用 Cowboy 作为 Express JS 的 HTTP 网络服务器