文章转自:https://blog.csdn.net/mycwq/article/details/38448813
我们知道,erlang在开源社区的活跃度远远不及java社区,在java社区中有很多优秀的开源框架,比如struts、hibernate、 spring、hadoop、hbase等,为了让erlang和java社区的众多开源框架相结合,让他们优势互补,可以让erlang来调用java写的中间件。
erlang提供了一个Jinterface代码包,java可以和erlang建立节点通信。通过这种方式,erlang可以将 java构建的节点也当作erlang的一个节点,java可以接收erlang传过来的消息,并且处理之后以异步的方式发送处理结果。
erlang与java构建的节点通讯
安装erlang后,可以在安装目录找到这个Jinterface代码包 OtpErlang.jar,路径是 erl5.10.3\lib\jinterface-1.5.8\priv\OtpErlang.jar
Java代码如下:
package erljava;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.ericsson.otp.erlang.OtpMbox;
import com.ericsson.otp.erlang.OtpNode;
public class ErlJavaNode{
public static void main(String[] args) throws Exception {
String cookie = "123456";
OtpNode node = new OtpNode("java_node@127.0.0.1", cookie);
OtpMbox mbox = node.createMbox();
mbox.registerName("java_node_name");
System.out.println("java node start");
OtpErlangObject o;
OtpErlangTuple msg;
OtpErlangPid from;
while (true) {
try {
o = mbox.receive();
System.out.println("recv:" + o);
if (o instanceof OtpErlangTuple) {
msg = (OtpErlangTuple) o;
from = (OtpErlangPid) (msg.elementAt(0));
mbox.send(from, msg.elementAt(1)); // 原消息返回
}
} catch (Exception e) {
System.out.println("" + e);
}
}
}
}
erlang给Java节点发送消息:
C:\>erl -name erl_node@127.0.0.1 -setcookie 123456
Eshell V5.10.3 (abort with ^G)
(erl_node@127.0.0.1)1> {java_node_name,'java_node@127.0.0.1'} ! {self(),{a,bc,d}}.
{<0.37.0>,{a,bc,d}}
(erl_node@127.0.0.1)2> flush().
Shell got {a,bc,d}
ok
分析erlang与Java节点无法通讯
1、epmd服务未启动
先在本机启动一个erlang节点,没有的话,如果先执行Java代码系统会抛出异常。原因是所有erlang节点之间的通讯都要依赖一个底层的epmd的服务,这个模块的主要功能是提供通过相互通过name来识别机器的机制。这个机制类似dns功能,先通过一个名称服务中间件,使用name获取所对应的ip地址,然后再利用这个ip地址建立连接。
另一种方式是手动启动epmd服务,在erlang安装目录下找到epmd进程,执行命令 epmd -daemon
2、erlang版本不一致
java使用的OtpErlang包和shell使用的erlang版本不一致,erlang是不允许主版本不同的erlang节点进行连接。
3、cookie
cookie 必须一致
erlang与java节点通讯的好处
erlang节点通讯也是依靠socket实现的,虽然erlang和java可以直接用socket连接,但使用节点通讯的有很多好处,和erlang节点通讯一样,支持erlang所有的数据结构,而且还不用定义传输协议,多节点通讯也会变得复杂。做成erlang节点,能极大程度利用到erlang分布式的好处。
Java判断erlang节点是否连接成功
if (node.ping("erl_node@127.0.0.1", 2000)) {
System.out.println("connect ok");
} else {
System.out.println("connect fail");
}
Java主动与erlang节点通讯实例
前面说到是erlang连接java节点的情况,现在讨论java主动连接erlang节点的情况。
erlang建立节点,注册进程名字
C:\>erl -name erl_node@127.0.0.1 -setcookie 123456
Eshell V5.10.3 (abort with ^G)
(erl_node@127.0.0.1)1> register(erl_node_name, self()).
true
Java代码如下
package erljava;
import com.ericsson.otp.erlang.OtpConnection;
import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.ericsson.otp.erlang.OtpPeer;
import com.ericsson.otp.erlang.OtpSelf;
public class ErlJavaNode {
public static void main(String[] args) throws Exception {
String cookie = "123456";
OtpSelf self = new OtpSelf("java_node@127.0.0.1", cookie);
OtpPeer other = new OtpPeer("erl_node@127.0.0.1");
OtpConnection connection = self.connect(other);
System.out.println("java node start");
if (connection.isConnected()) {
System.out.println("connect ok");
OtpErlangObject[] msg = new OtpErlangObject[2];
msg[0] = self.pid();
msg[1] = new OtpErlangAtom("hello, world");
OtpErlangTuple tuple = new OtpErlangTuple(msg);
connection.send("erl_node_name", tuple);
} else {
System.out.println("connect fail");
}
}
}
erlang刷新信箱,就可以看到Java发来的信息
(erl_node@127.0.0.1)2> flush().
Shell got {<6872.1.0>,'hello, world'}
ok