Привет, я хочу реализовать распределенные кэши в качестве упражнения. Модуль кеша основан на gen_server. Кэши запускаются модулем CacheSupervisor. Сначала я попытался запустить все это на одном узле, который работал хорошо. Теперь я пытаюсь распространять свои кеши на двух узлах, которые живут в двух открытых консольных окнах на моем ноутбуке.Как распределить контролируемых сотрудников gen_server?
PS:
Во время написания этого вопроса, я понял, что я забыл подключить третье окно к другим узлам. Я исправил его, но у меня все еще есть оригинальная ошибка.
консоль:
После подключения моих узлов я называю CacheSupervisor.start_link()
в третьем окне, это приводит к сообщению об ошибке follwing.
Ошибка:
** (EXIT from #PID<0.112.0>) shutdown: failed to start child: :de
** (EXIT) an exception was raised:
** (ArgumentError) argument error
erlang.erl:2619: :erlang.spawn(:[email protected]_XPS, {:ok, #PID<0.128.0>})
(stdlib) supervisor.erl:365: :supervisor.do_start_child/2
(stdlib) supervisor.erl:348: :supervisor.start_children/3
(stdlib) supervisor.erl:314: :supervisor.init_children/2
(stdlib) gen_server.erl:328: :gen_server.init_it/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Я предполагаю, что ошибка указывает на то, что :gen_server.start_link(..)
внутри start_link(name)
моего модуля Cache решает {:ok, #PID<0.128.0>}
который, кажется, неправильно, но я не имею ни малейшего представления, куда поставить Node.spawn()
еще
Модуль Cache:
defmodule Cache do
use GenServer
def handle_cast({:put, url, page}, {pages, size}) do
new_pages = Dict.put(pages, url, page)
new_size = size + byte_size(page)
{:noreply, {new_pages, new_size}}
end
def handle_call({:get, url}, _from, {pages, size}) do
{:reply, pages[url], {pages, size}}
end
def handle_call({:size}, _from, {pages, size}) do
{:reply, size, {pages, size}}
end
def start_link(name) do
IO.puts(elem(name,0))
Node.spawn(String.to_atom(elem(name, 0)), :gen_server.start_link({:local,elem(name, 1)}, __MODULE__, {HashDict.new, 0}, []))
end
def put(name, url, page) do
:gen_server.cast(name, {:put, url, page})
end
def get(name, url) do
:gen_server.call(name, {:get, url})
end
def size(name) do
:gen_server.call(name, {:size})
end
end
Модуль CacheSupervisor:
defmodule CacheSupervisor do
use Supervisor
def init(_args) do
workers = Enum.map([{"[email protected]_XPS", :de},{"[email protected]_XPS", :edu}, {"[email protected]_XPS", :com} ,{"[email protected]_XPS", :it}, {"[email protected]_XPS", :rest}],
fn(n)-> worker(Cache, [n], id: elem(n, 1)) end)
supervise(workers, strategy: :one_for_one)
end
def start_link() do
:supervisor.start_link(__MODULE__, [])
end
end
Спасибо, ваш ответ был полезен. Я решил пересмотреть программную логику. Теперь каждый рабочий получает свой собственный руководитель –