You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir应用启动后立即退出,如何使其持续运行?

Elixir WebSocket客户端启动后立即退出的解决办法

我编写了一个简单的Elixir应用,用于启动WebSocket客户端并监听消息。期望它能持续运行,但使用mix app.start启动后,应用会立即退出。以下是相关代码,请问需要如何修改才能让应用一直运行?

defmodule Example.WsClient do
  use WebSockex

  def start_link(state) do
    IO.puts "Starting WS Client"
    WebSockex.start_link("ws://example.com/ws", __MODULE__, state)
  end

  def handle_frame({type, msg}, state) do
    IO.puts "Received Message - Type: #{inspect type} -- Message: #{inspect msg}"
    {:ok, state}
  end

  def handle_cast({:send, {type, msg} = frame}, state) do
    IO.puts "Sending #{type} frame with payload: #{msg}"
    {:reply, frame, state}
  end
end
defmodule Example.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    children = [
      # Starts a worker by calling: Example.Worker.start_link(arg)
      {Example.WsClient, []}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Example.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

解决办法

问题核心是WebSocket客户端进程没有被正确维持运行,或者启动方式没有让应用保持活跃。可以从以下几个方面修改:

1. 确保进程异常时自动重启

给Supervisor的子进程配置明确的重启策略,保证客户端进程意外退出后能被自动拉起:

修改后的Example.Application代码:

defmodule Example.Application do
  @moduledoc false
  use Application

  @impl true
  def start(_type, _args) do
    children = [
      # 明确设置重启策略为:permanent,进程退出时自动重启
      {Example.WsClient, [restart: :permanent]}
    ]

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

2. 使用正确的启动命令保持应用运行

  • 若要前台运行并保持不退出,使用:
    mix run --no-halt
    
  • 若要后台运行,先构建发布包再启动:
    mix release
    _build/prod/rel/example/bin/example start
    

mix app.start默认是启动后立即返回当前终端,不会阻塞进程,看起来像是退出,但如果客户端进程正常运行,应用其实在后台。但如果连接失败导致进程退出,上面的重启策略会自动重试连接。

3. 可选:添加断连重连逻辑

在客户端模块中添加handle_disconnect回调,处理断开连接的情况,实现自动重连:

修改后的Example.WsClient代码:

defmodule Example.WsClient do
  use WebSockex

  def start_link(state) do
    IO.puts "Starting WS Client"
    WebSockex.start_link("ws://example.com/ws", __MODULE__, state)
  end

  def handle_frame({type, msg}, state) do
    IO.puts "Received Message - Type: #{inspect type} -- Message: #{inspect msg}"
    {:ok, state}
  end

  def handle_cast({:send, {type, msg} = frame}, state) do
    IO.puts "Sending #{type} frame with payload: #{msg}"
    {:reply, frame, state}
  end

  # 处理断连,触发自动重连
  def handle_disconnect(_reason, state) do
    IO.puts "Disconnected, attempting to reconnect..."
    {:reconnect, state}
  end
end

内容的提问来源于stack exchange,提问作者Pavan Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:05:14