我一直在关注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 - 但这也失败了。