Elixir监督多名RabbitMQ消费者工作者

时间:2017-04-05 07:11:17

标签: rabbitmq elixir otp supervisor

我一直在关注Elixir(Elixir Work Queues)的RabbitMQ工作队列教程,该教程非常有效。最重要的是,我现在正试图让一个主管启动并监控多个消费者。

最后一部分证明有点棘手。如果我在2个独立的iex会话中运行以下代码,那么两者都会得到&处理来自RabbitMQ的消息。

客户(消费者)

defmodule MT.Client do
  require Logger

  @host Application.get_env(:mt, :host)
  @username Application.get_env(:mt, :username)
  @password Application.get_env(:mt, :password)
  @channel Application.get_env(:mt, :channel)

  def start_link do
    MT.Client.connect
  end

  def connect do
    {:ok, connection} = AMQP.Connection.open(host: @host, username: @username, password: @password)
    {:ok, channel} = AMQP.Channel.open(connection)

    AMQP.Queue.declare(channel, @channel, durable: true)
    AMQP.Basic.qos(channel, prefetch_count: 1)

    AMQP.Basic.consume(channel, @channel)

    Logger.info "[*] Waiting for messages"

    MT.Client.loop(channel)
  end

  def loop(channel) do
    receive do
      {:basic_deliver, payload, meta} ->
        Logger.info "[x] Received #{payload}"
        payload
        |> to_char_list
        |> Enum.count(fn x -> x == ?. end)
        |> Kernel.*(1000)
        |> :timer.sleep
        Logger.info "[x] Done."
        AMQP.Basic.ack(channel, meta.delivery_tag)

        MT.Client.loop(channel)
    end
  end
end

defmodule MT.Client.Supervisor do
  use Supervisor
  require Logger

  @name MTClientSupervisor

  def start_link do
    Supervisor.start_link(__MODULE__, :ok, name: @name)
  end

  def init(:ok) do
    children = [
      worker(MT.Client, [], restart: :transient, id: "MTClient01"),
      worker(MT.Client, [], restart: :transient, id: "MTClient02"),
      worker(MT.Client, [], restart: :transient, id: "MTClient03")
    ]
    supervise(children, strategy: :one_for_one)
  end
end

在iex会话中运行时

iex -S mix
MT.Client.Supervisor.start_link

记录以下内容:

08:46:50.746 [info] [*] Waiting for messages
08:46:50.746 [info] [x] Received {"job":"TestMessage","data":{"message":"message........"}}
08:46:58.747 [info] [x] Done.
08:46:58.748 [info] [x] Received {"job":"TestMessage","data":{"message":"last........"}}
08:47:06.749 [info] [x] Done. 

很明显,只有1个消费者活跃,它依次消费消息。

在2个iex会话中运行以下内容:

MT.Client.start_link

我不是在这里添加日志,但在这种情况下我同时处理2个消费消息

我确信我根本没有掌握Agent / GenServer / Supervisor所需的详细信息。任何人都可以指出需要更改为MT.Client&上面的MT.Client.Supervisor实现了让多个消费者在同一个频道上活跃的想法吗?

也;我一直在尝试生成一个消费者代理并在AMQP.Basic.consume(channel, @channel, pid)中使用生成的pid - 但这也失败了。

0 个答案:

没有答案