如何连接到部署到 OpenShift 的 IBM MQ?
How to connect to IBM MQ deployed to OpenShift?
我有一个带有 IBM MQ 的容器(Docker 映像 ibmcom/mq/9.2.2.0-r1
)公开了两个端口(9443 - 管理员,1414 - 应用程序)。
OpenShift 中所有必需的设置已完成(Pod、服务、路由)。
有两条路线,每个港口一条。
相应地指向端口(外部端口默认为http=80、https=443)。
可以通过第一个路径访问管理控制台,因此,MQ 已启动并且 运行。
我尝试使用标准方法作为客户端(JMS 2.0,com.ibm.mq.allclient:9.2.2.0
)连接:
var fctFactory = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
var conFactory = fctFactory.createConnectionFactory();
// ... other props
conFactory.setObjectProperty(WMQConstants.WMQ_HOST_NAME, "route-app.my.domain");
conFactory.setObjectProperty(WMQConstants.WMQ_PORT, 443);
连接失败。还尝试将路由重新定义为 HTTP 并使用端口 80,但仍然没有成功。
如果有帮助,让我们假设我们使用最新版本的 MQ Explorer 作为客户端。
每次出现相同的连接错误:
...
Caused by: com.ibm.mq.MQException: JMSCMQ0001:
IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
...
Caused by: com.ibm.mq.jmqi.JmqiException:
CC=2;RC=2009;AMQ9204: Connection to host 'route-app.my.domain(443)' rejected.
[1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009;AMQ9208:
Error on receive from host 'route-app.my.domain/10.227.248.2:443 (route-app.my.domain)'.
[1=-1,2=ffffffff,3=route-app.my.domain/10.227.248.2:443 (route-app.my.domain),4=TCP]],
3=route-app.my.domain(443),5=RemoteConnection.receiveTSH]
...
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9208:
Error on receive from host 'route-app.my.domain/10.227.248.2:443
也许,这个 article 可以提供一些关于错误代码 2009 的提示,但仍然不确定是什么影响了 OpenShift 端的连接错误。
以前,我连接到 IBM MQ 时总是明确指定一个端口值,但这里的情况有点不同。
如何通过TCP连接到OpenShift集群中的IBM MQ?
OpenShift中配置如下:
kind: Pod
apiVersion: v1
metadata:
name: ibm-mq
labels:
app: ibm-mq
spec:
containers:
- resources:
limits:
cpu: '1'
memory: 600Mi
requests:
cpu: '1'
memory: 600Mi
name: ibm-mq
ports:
- containerPort: 1414
protocol: TCP
- containerPort: 9443
protocol: TCP
containerStatuses:
image: 'nexus-ci/docker-lib/ibm_mq:latest'
---
kind: Service
apiVersion: v1
metadata:
name: ibm-mq
spec:
ports:
- name: admin
protocol: TCP
port: 9443
targetPort: 9443
- name: application
protocol: TCP
port: 1414
targetPort: 1414
selector:
app: ibm-mq
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: ibm-mq-admin
spec:
host: ibm-mq-admin.my-domain.com
to:
kind: Service
name: ibm-mq
weight: 100
port:
targetPort: admin
tls:
termination: passthrough
insecureEdgeTerminationPolicy: None
wildcardPolicy: None
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: ibm-mq-app
spec:
host: ibm-mq-app.my-domain.com
to:
kind: Service
name: ibm-mq
weight: 100
port:
targetPort: application
tls:
termination: passthrough
insecureEdgeTerminationPolicy: None
wildcardPolicy: None
---
更新: 最终创建并部署到 OpenShift 一个接收 HTTP 请求并通过 JMS(put/get 文本消息)与 MQ 交互的小型 Web 应用程序,例如:
POST /queue/{queueName}/send + <body>
;
GET /queue/{queueName}/receive
.
它使用 TCP 与 OpenShift 集群内部的 MQ 交互,并作为常规 Web 应用程序接受外部 HTTP 连接。
其他解决方案似乎太费力了,但我接受了其中一种,因为它在理论上是正确且简单的。
我不确定是否完全理解您的设置,但是"Routes"
仅路由 HTTP 流量(在端口 80 或 443 onyl 上),而不是 TCP 流量。
如果你想从集群外部访问你的 MQ 服务器,有几种解决方案,一种是创建一个类型的服务:"NodePort"
您的服务不是 NodePort 服务。在您的情况下,它应该类似于
kind: Service
apiVersion: v1
metadata:
name: ibm-mq
spec:
type: NodePort
ports:
- port: 1414
targetPort: 1414
nodePort: 30001
selector:
app: ibm-mq
然后从外部使用任何名称访问。:30001
并删除无用的对应路由。如前所述,我假设您在我指给您的文档中读到了该路由仅在端口 80 或 443 上路由 HTTP 流量。
文档:https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
以下 Java 系统 属性 将由 IBM MQ 类 for JMS 在 9.2.1 及更高版本中读取,以告知其将 SNI header 设置为启动 TLS 连接时远程系统的主机名:
com.ibm.mq.cfg.SSL.OutboundSNI=HOSTNAME
要以编程方式设置它,只需使用 System.setProperty
方法,例如:
System.setProperty("com.ibm.mq.cfg.SSL.OutboundSNI","HOSTNAME");
注意: 字符串 HOSTNAME
是字面意思,不应替换为实际的主机名。
如果您不能从 9.2.1 或更高版本移动到 com.ibm.mq.allclient.jar
,那么在 9.2.0.0 和更高版本中您可以改用 com.ibm.mq.cfg.SSL.AllowOutboundSNI=NO
,但这在 9.2.1 和更高版本中已弃用稍后。
我有一个带有 IBM MQ 的容器(Docker 映像 ibmcom/mq/9.2.2.0-r1
)公开了两个端口(9443 - 管理员,1414 - 应用程序)。
OpenShift 中所有必需的设置已完成(Pod、服务、路由)。
有两条路线,每个港口一条。
相应地指向端口(外部端口默认为http=80、https=443)。
可以通过第一个路径访问管理控制台,因此,MQ 已启动并且 运行。
我尝试使用标准方法作为客户端(JMS 2.0,com.ibm.mq.allclient:9.2.2.0
)连接:
var fctFactory = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
var conFactory = fctFactory.createConnectionFactory();
// ... other props
conFactory.setObjectProperty(WMQConstants.WMQ_HOST_NAME, "route-app.my.domain");
conFactory.setObjectProperty(WMQConstants.WMQ_PORT, 443);
连接失败。还尝试将路由重新定义为 HTTP 并使用端口 80,但仍然没有成功。
如果有帮助,让我们假设我们使用最新版本的 MQ Explorer 作为客户端。
每次出现相同的连接错误:
...
Caused by: com.ibm.mq.MQException: JMSCMQ0001:
IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
...
Caused by: com.ibm.mq.jmqi.JmqiException:
CC=2;RC=2009;AMQ9204: Connection to host 'route-app.my.domain(443)' rejected.
[1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009;AMQ9208:
Error on receive from host 'route-app.my.domain/10.227.248.2:443 (route-app.my.domain)'.
[1=-1,2=ffffffff,3=route-app.my.domain/10.227.248.2:443 (route-app.my.domain),4=TCP]],
3=route-app.my.domain(443),5=RemoteConnection.receiveTSH]
...
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9208:
Error on receive from host 'route-app.my.domain/10.227.248.2:443
也许,这个 article 可以提供一些关于错误代码 2009 的提示,但仍然不确定是什么影响了 OpenShift 端的连接错误。
以前,我连接到 IBM MQ 时总是明确指定一个端口值,但这里的情况有点不同。
如何通过TCP连接到OpenShift集群中的IBM MQ?
OpenShift中配置如下:
kind: Pod
apiVersion: v1
metadata:
name: ibm-mq
labels:
app: ibm-mq
spec:
containers:
- resources:
limits:
cpu: '1'
memory: 600Mi
requests:
cpu: '1'
memory: 600Mi
name: ibm-mq
ports:
- containerPort: 1414
protocol: TCP
- containerPort: 9443
protocol: TCP
containerStatuses:
image: 'nexus-ci/docker-lib/ibm_mq:latest'
---
kind: Service
apiVersion: v1
metadata:
name: ibm-mq
spec:
ports:
- name: admin
protocol: TCP
port: 9443
targetPort: 9443
- name: application
protocol: TCP
port: 1414
targetPort: 1414
selector:
app: ibm-mq
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: ibm-mq-admin
spec:
host: ibm-mq-admin.my-domain.com
to:
kind: Service
name: ibm-mq
weight: 100
port:
targetPort: admin
tls:
termination: passthrough
insecureEdgeTerminationPolicy: None
wildcardPolicy: None
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: ibm-mq-app
spec:
host: ibm-mq-app.my-domain.com
to:
kind: Service
name: ibm-mq
weight: 100
port:
targetPort: application
tls:
termination: passthrough
insecureEdgeTerminationPolicy: None
wildcardPolicy: None
---
更新: 最终创建并部署到 OpenShift 一个接收 HTTP 请求并通过 JMS(put/get 文本消息)与 MQ 交互的小型 Web 应用程序,例如:
POST /queue/{queueName}/send + <body>
;GET /queue/{queueName}/receive
.
它使用 TCP 与 OpenShift 集群内部的 MQ 交互,并作为常规 Web 应用程序接受外部 HTTP 连接。
其他解决方案似乎太费力了,但我接受了其中一种,因为它在理论上是正确且简单的。
我不确定是否完全理解您的设置,但是"Routes"
仅路由 HTTP 流量(在端口 80 或 443 onyl 上),而不是 TCP 流量。
如果你想从集群外部访问你的 MQ 服务器,有几种解决方案,一种是创建一个类型的服务:"NodePort"
您的服务不是 NodePort 服务。在您的情况下,它应该类似于
kind: Service
apiVersion: v1
metadata:
name: ibm-mq
spec:
type: NodePort
ports:
- port: 1414
targetPort: 1414
nodePort: 30001
selector:
app: ibm-mq
然后从外部使用任何名称访问。
并删除无用的对应路由。如前所述,我假设您在我指给您的文档中读到了该路由仅在端口 80 或 443 上路由 HTTP 流量。
文档:https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
以下 Java 系统 属性 将由 IBM MQ 类 for JMS 在 9.2.1 及更高版本中读取,以告知其将 SNI header 设置为启动 TLS 连接时远程系统的主机名:
com.ibm.mq.cfg.SSL.OutboundSNI=HOSTNAME
要以编程方式设置它,只需使用 System.setProperty
方法,例如:
System.setProperty("com.ibm.mq.cfg.SSL.OutboundSNI","HOSTNAME");
注意: 字符串 HOSTNAME
是字面意思,不应替换为实际的主机名。
如果您不能从 9.2.1 或更高版本移动到 com.ibm.mq.allclient.jar
,那么在 9.2.0.0 和更高版本中您可以改用 com.ibm.mq.cfg.SSL.AllowOutboundSNI=NO
,但这在 9.2.1 和更高版本中已弃用稍后。