简体   繁体   English

AMQP 连接丢失不会杀死父进程,因此重新连接永远不会发生

[英]AMQP connection lost doesn't kill parent process, so reconnection never happens

I have init function of my GenServer.我有我的 GenServer 的 init 功能。 Supervisor is looking after it, and should restart it on exit.主管正在照顾它,应该在退出时重新启动它。

  def init(_opts) do
    username = get_conf(:username)
    password = get_conf(:password)
    host = get_conf(:host)
    port = get_conf(:port)
    vhost = String.replace(get_conf(:vhost), "/", "%2f")
    {:ok, conn} = Connection.open("amqp://#{username}:#{password}@#{host}:#{port}/#{vhost}")
    {:ok, chan} = Channel.open(conn)
    state = %State{
      exchange: get_conf(:exchange),
      channel: chan,
      routing_key: get_conf(:routing_key)
    }
    {:ok, state}
  end

When I restart RabbitMQ with sudo service rabbitmq-server restart new connection isn't established.当我使用sudo service rabbitmq-server restart重新启动 RabbitMQ 时,未建立新连接。

In debug bar I see following:在调试栏中,我看到以下内容: 在此处输入图片说明 When I click on connection pid <0.417.0> I get message that process doesn't exist any more.当我单击连接 pid <0.417.0> 时,我收到该进程不再存在的消息。 It seems that process is dead and parent AmqpTransport know nothing about that.似乎进程已经死了,父AmqpTransport一无所知。 How can I make AmqpTransport die together with it's child Connection ?我怎样才能让AmqpTransport和它的子Connection一起死?

Fixed it with adding trapping exits and linking to Connection process.通过添加trapping exits并链接到Connection进程来修复它。 Also I pattern match errors during connection to avoid reached_max_restart_intensity .此外,我在连接期间模式匹配错误,以避免reached_max_restart_intensity

  @restart_delay 2000 # 2 seconds

  def init(_opts) do
    Process.flag(:trap_exit, true)
    send(self(), :connect)
    {:ok, nil}
  end

  def handle_info(:connect, state) do
    #...
    case Connection.open("amqp://#{username}:#{password}@#{host}:#{port}/#{vhost}") do
      {:ok, conn} ->
        Process.link(conn.pid)
        # ...
        {:noreply, state}
      {:error, :econnrefused} ->
        Logger.error("amqp transport failed with connection refused")
        Process.send_after(self(), :connect, @restart_delay)
        {:noreply, nil}
    end

  end

  def handle_info({:EXIT, pid, reason}, state) do
    Logger.error("amqp transport failed with #{inspect(reason)}")
    Process.unlink(pid)
    Process.send_after(self(), :connect, @restart_delay)
    {:noreply, nil}
  end  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM