1

我正在尝试在部署在 k8s 中的 2 个 WebSphere Liberty 服务器之间设置远程 EJB 调用。是的,我知道 EJB 不是在 k8s 中部署时想要使用的东西,但我现在必须处理它。

我遇到的问题是如何在 k8s 中公开远程 ORB IP:端口。据我了解,只有在客户端和远程“侦听”同一个 IP 时,它才能使其工作。我不是网络专家,而且我对 k8s 很陌生,所以也许我在这里遗漏了一些东西,这就是我需要帮助的原因。

我让它工作的唯一方法是当我明确地将远程服务器上的主机设置为它自己的 IP 地址,然后从同一个 IP 上的客户端访问它。该测试是在具有 macvlan0 网络的 Docker 主机上完成的(每个容器都有自己的 IP 地址)。

这是远程 server.xml 配置的 ORB 设置:

<iiopEndpoint id="defaultIiopEndpoint" host="172.30.106.227" iiopPort="2809" />

<orb id="defaultOrb" iiopEndpointRef="defaultIiopEndpoint">
    <serverPolicy.csiv2>
        <layers>
            <!-- don't care about security at this point -->
            <authenticationLayer establishTrustInClient="Never"/>
            <transportLayer sslEnabled="false"/>
        </layers>
    </serverPolicy.csiv2>
</orb>

和客户端 server.xml 配置:

    <orb id="defaultOrb">
    <clientPolicy.csiv2>
        <layers>
            <!-- really, I don't care about security -->
            <authenticationLayer establishTrustInClient="Never"/>
            <transportLayer sslEnabled="false"/>
        </layers>
    </clientPolicy.csiv2>
</orb>

从客户端,这是我尝试访问它的 JNDI 名称:

corbaname::172.30.106.227:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

这有效。

由于不想在公开 ORB 端口时设置固定 IP,我必须找到一种基于主机 IP 动态公开它的方法。在 0.0.0.0 上公开不起作用。本地主机也是如此。在这两种情况下,客户端都拒绝连接这种错误:

Error connecting to host=0.0.0.0, port=2809: Connection refused (Connection refused)

在 k8s 中,我通过 LoadBalancer 服务为远程 Pod 暴露了端口 2809,并尝试从客户端 Pod 访问远程服务器,我在 corbaname 定义中设置了远程的服务 IP 地址。这当然行不通。我可以通过 telnet 访问远程 ip:port,所以这不是网络问题。

我已经尝试了远程服务器上的所有设置组合。在 host="0.0.0.0" 上导出结果与上述相同的异常(连接被拒绝)。

我不确定在内部 IP 地址上导出是否可行,但即使可以,在将 pod 部署到 k8s 之前,我也不知道内部 IP。或者有没有办法知道?没有环境。变量,我已经检查过了。

暴露服务 IP 地址(使用 host="${REMOTE_APP_SERVICE_HOST}")失败并出现以下错误:

The server socket could not be opened on 2,809. The exception message is Cannot assign requested address (Bind failed).

同样,我知道用 Rest 替换 EJB 是可行的方法,但现在不是一个选择(不要问为什么)。

请帮忙!


编辑:

我设法取得了一些进展。实际上,我相信我已经成功调用了远程 EJB。我所做的是添加hostAliasespod 定义,它为我的主机添加了别名,如下所示:

hostAliases:
- ip: 0.0.0.0
  hostnames:
  - my.host.name

然后我将此主机名添加到远程 server.xml:

<iiopEndpoint id="defaultIiopEndpoint" host="my.host.name" iiopPort="2809" />

我还在客户端 pod 中添加了主机别名:

hostAliases:
- ip: {remote.server.service.ip.here}
  hostnames:
  - my.host.name

最后,我将 JNDI 名称更改为:

corbaname::my.host.name:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

通过此设置,远程服务器被成功调用!

但是,现在我遇到了另一个在 Docker 主机上测试时没有遇到的问题。查找已完成,但我得到的不是我所期望的。

查找代码几乎是您所期望的:

Object obj = new InitialContext().lookup(jndi);
BeanRemote remote = (BeanRemote) PortableRemoteObject.narrow(obj, BeanRemote.class);

不幸的是,这个狭窄的电话失败了ClassCastException

Caused by: java.lang.ClassCastException: org.example.com.BeanRemote
    at com.ibm.ws.transport.iiop.internal.WSPortableRemoteObjectImpl.narrow(WSPortableRemoteObjectImpl.java:50)
    at [internal classes]
    at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:62)

我收到的对象是org.omg.stub.java.rmi._Remote_Stub. 有任何想法吗?

4

1 回答 1

1

解决了!

所以,第一个问题是解决主机映射问题,正如上面编辑中提到的那样,通过添加主机别名 id pod 定义来解决:

远程吊舱:

hostAliases:
- ip: 0.0.0.0
  hostnames:
  - my.host.name

客户端吊舱:

hostAliases:
- ip: {remote.server.service.ip.here}
  hostnames:
  - my.host.name

然后远程服务器必须在 iiop 主机定义中使用该主机名:

<iiopEndpoint id="defaultIiopEndpoint" host="my.host.name" iiopPort="2809" />

此外,客户端必须通过 JNDI 查找引用该主机名:

corbaname::my.host.name:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

此设置解析远程 EJB 调用。

另一个问题ClassCastException真的很不寻常。我设法在 Docker 主机上重现了该错误,然后一次更改一件事,直到问题得到解决。事实证明,问题出在ldapRegistry-3.0功能上(!?)。将此功能添加到客户的功能列表中解决了我的问题:

<feature>ldapRegistry-3.0</feature>

添加此功能后,远程 EJB 被成功调用。

于 2020-11-09T10:59:35.580 回答