Erlang全局PID - 如何在MySQL中保存它

时间:2015-04-01 10:00:08

标签: erlang

问题:我有多个Erlang服务,每个服务都由Erlang PID识别。我希望在我的数据库(MySQL)中保存{PID,ServiceName},以便我的集群中需要访问任何服务的任何Erlang进程只需要SELECT来获取服务名称以获取其PID和然后对它进行gen_server调用。

  1. 我将PID转换为" global"带有term_to_binary的PID(self()) - 基本上,想象一下Node1上的Erlang进程A将自身保存为< 0.45.0>在db中:这意味着Node2上的进程B试图访问由< 0.45.0>表示的服务。不会成功,因为"< 0.45.0>"仅在Node1上有效;将它保存为PID = term_to_binary(self())将正确解码为全局PID,如果我们在从Node读取它时在Node2上运行binary_to_term(PID)
  2. MySQL查询的格式为" INSERT INTO ServiceTable ..." ++ io_lib:format(" ServicePID =' ~p'," [binary_to_list(term_to_binary(self()))])++
  3. 当我从数据库中读回PID时,我得到类似<<<<<<<<<<<&#;; [131,103,100,0,23,115" ...>>这就是我的问题所在:我可以将这个二进制文件转换回类似<<<<<<<<<<<<<<<> ???
  4. (我知道我可以通过例如注册我的服务等解决这个问题 - 但我有理由不这样做)。

    谢谢。

3 个答案:

答案 0 :(得分:1)

您应该使用预先存在的解决方案,例如gproc(由Ulf Wiger提供)。

我最近在ErlangFactory 2015上看到了一个类似的解决方案,martinsk他说可能很快就会被称为“行业”。它做的不仅仅是gproc,包括像raft共识协议支持这样的功能,以确定最好的服务器带头......我猜想与他的用例更相关。

Gproc可能是您迈出的最好的第一步。如果您使用的MySQL不仅仅是全球注册的知识库,那么配置和缓存选项可能会为您提供物理存储数据所需的支持。

但是,也要回答你的具体问题,如果你真的想自己这样做,也许atom_to_list(node()) ++ pid_to_list(self()).也可以。

e.g:

(foo@lankhmar)6> atom_to_list(node()) ++ pid_to_list(self()). "foo@lankhmar<0.43.0>"

答案 1 :(得分:0)

最简单的方法是使用pid_to_list/1list_to_pid/1函数。

答案 2 :(得分:0)

根据你所展示的内容,我猜你可以避免从二进制到列表的转换,所以io_lib:format会将二进制转换为它的字符串表示。

稍后您可以使用erl_parse和erl_eval模块检索pid:

1> Pid = self(). 
<0.32.0>
2> 
2> String = lists:flatten(io_lib:format("~p.~n",[term_to_binary(Pid)])).
"<<131,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,32,\n  0,0,0,0,0>>.\n"
3> %% to get an equivalent form of what you get from sql.
3> {done,{ok,T,_},[]} = erl_scan:tokens([],String,1).
{done,{ok,[{'<<',1},
           {integer,1,131},
           {',',1},
           {integer,1,103},
           {',',1},
           {integer,1,100},
           {',',1},
           {integer,1,0},
           {',',1},
           {integer,1,13},
           {',',1},
           {integer,1,110},
           {',',1},
           {integer,1,111},
           {',',1},
           {integer,1,110},
           {',',1},
           {integer,1,111},
           {',',1},
           {integer,1,100},
           {',',1},
           {integer,1,101},
           {',',1},
           {integer,...},
           {...}|...],
          3},
      []}
4> {ok,Tree} = erl_parse:parse_exprs(T).
{ok,[{bin,1,
          [{bin_element,1,{integer,1,131},default,default},
           {bin_element,1,{integer,1,103},default,default},
           {bin_element,1,{integer,1,100},default,default},
           {bin_element,1,{integer,1,0},default,default},
           {bin_element,1,{integer,1,13},default,default},
           {bin_element,1,{integer,1,110},default,default},
           {bin_element,1,{integer,1,111},default,default},
           {bin_element,1,{integer,1,110},default,default},
           {bin_element,1,{integer,1,111},default,default},
           {bin_element,1,{integer,1,100},default,default},
           {bin_element,1,{integer,1,101},default,default},
           {bin_element,1,{integer,1,64},default,default},
           {bin_element,1,{integer,1,110},default,default},
           {bin_element,1,{integer,1,111},default,default},
           {bin_element,1,{integer,1,104},default,default},
           {bin_element,1,{integer,1,111},default,default},
           {bin_element,1,{integer,1,115},default,default},
           {bin_element,1,{integer,1,...},default,default},
           {bin_element,1,{integer,...},default,...},
           {bin_element,1,{...},...},
           {bin_element,1,...},
           {bin_element,...},
           {...}|...]}]}
5> {value,Res,[]} = erl_eval:exprs(Tree,[]).
{value,<<131,103,100,0,13,110,111,110,111,100,101,64,110,
         111,104,111,115,116,0,0,0,32,0,0,0,0,0>>,
       []}
6> Pid =  binary_to_term(Res).  %% that's it :o)
<0.32.0>