ZeroMQ经销商插座在Elixir下无法使用(使用Erlang' chumak)

时间:2017-09-19 20:27:11

标签: erlang elixir zeromq chumak

我想在Elixir和Python之间进行交流。我不想使用NIF和东西 - 我更喜欢使用zeroMQ松散耦合,因为这将允许我以后使用其他语言而不是Python。我正在使用chumak库,它是Erlang中zeromq的本机实现,并且似乎维护得很好。我过去曾成功使用过pub sub。

除了pub-sub之外,我发现req-rep和req-router套接字工作正常。然而,经销商 - 路由器没有。这非常重要,因为只有经销商和路由器才能在zeromq中为您提供真正的异步。

这是路由器端的python代码:

import zmq
context = zmq.Context()
rout = context.socket(zmq.ROUTER)
rout.bind("tcp://192.168.1.192:8760")

这是Elixir req代码,工作正常......

iex(1)> {ok, sock1} = :chumak.socket(:req, 'reqid')
{:ok, #PID<0.162.0>}
iex(2)> {ok, _peer} = :chumak.connect(sock1, :tcp, '192.168.1.192', 8760)
{:ok, #PID<0.164.0>}
iex(3)> :chumak.send(sock1, 'hello from req socket')
:ok

....因为我在Python方面得到它:

In [5]: xx = rout.recv_multipart()
In [6]: xx
Out[6]: ['reqid', '', 'hello from req socket']

然而,如果我在Elixir方面试用经销商插​​座,我就会得到这些:

iex(4)> {ok, sock2} = :chumak.socket(:dealer, 'dealid')                  
{:ok, #PID<0.170.0>}
iex(5)> {ok, _peer} = :chumak.connect(sock2, :tcp, '192.168.1.192', 8760)
{:ok, #PID<0.172.0>}
iex(6)> :chumak.send(sock2, 'hello from dealer socket')
{:error, :not_implemented_yet}
iex(7)> :chumak.send_multipart(sock2, ['a', 'b', 'hello from dealer socket'])

22:13:38.705 [error] GenServer #PID<0.172.0> terminating
** (FunctionClauseError) no function clause matching in :chumak_protocol.encode_more_message/3
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl:676: :chumak_protocol.encode_more_message('a', :null, %{})
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl:664: :chumak_protocol.encode_message_multipart/3
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_peer.erl:159: :chumak_peer.handle_cast/2
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:send, ['a', 'b', 'hello from dealer socket'], {#PID<0.160.0>, #Reference<0.79795089.2401763329.172383>}}}
State: {:state, :ready, '192.168.1.192', 8760, :client, [], :dealer, 'dealid', [], {3, 0}, #Port<0.4968>, {:decoder, :ready, 0, nil, nil, {:some, 3}, {:some, 0}, %{}, :null, false}, #PID<0.170.0>, {[], []}, [], false, false, false, :null, %{}}

22:13:38.710 [info]  [:unhandled_handle_info, {:module, :chumak_socket}, {:msg, {:EXIT, #PID<0.172.0>, {:function_clause, [{:chumak_protocol, :encode_more_message, ['a', :null, %{}], [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl', line: 676]}, {:lists, :mapfoldl, 3, [file: 'lists.erl', line: 1354]}, {:chumak_protocol, :encode_message_multipart, 3, [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl', line: 664]}, {:chumak_peer, :handle_cast, 2, [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_peer.erl', line: 159]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 616]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 686]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}}]

正如你所看到的那样,我在chumak.send_multipart上得到了这个巨大的错误,而chumak.send甚至无法工作。这里发生了什么?

经销商套接字在Python方面正常工作:

import zmq
context = zmq.Context()
deal = context.socket(zmq.DEALER)
deal.setsockopt_string(zmq.IDENTITY, u"Thomas")
deal.connect("tcp://192.168.1.192:8760")
deal.send("hello from python deal")

现在在路由器方面:

In [5]: xx = rout.recv_multipart()
In [6]: xx
Out[6]: ['reqid', '', 'hello from req socket']
In [7]: dd = rout.recv_multipart()
In [8]: dd
Out[8]: ['Thomas', 'hello from python deal']

所以我想知道我的Elixir chumak经销商套件中是否有语法或类型错误,或者它只是一个错误。我在amd64和armv7l架构上都尝试了这个,问题是相同的。

所有elixir代码都基于经销商路由器的chumak example中的Erlang版本。

我的mix.exs deps看起来像这样:

 [
      {:chumak, "~> 1.2"},
      {:msgpack, "~> 0.7.0"}

 ]

1 个答案:

答案 0 :(得分:2)

我看到的唯一明显的事情是你使用send_multipart。它的来源签名:

-spec send_multipart(SocketPid::pid(), [Data::binary()]) -> ok.
你正在这样做:

:chumak.send_multipart(sock2, ['a', 'b', 'hello from dealer socket'])

------------
iex(2)> is_binary('a')
false
iex(3)> is_binary('hello from dealer socket')
false

否则,我看不出您的代码与chumak的repo中的示例代码之间存在很大差异。