执行器 JMS 健康检查 Return 配置 Java 误报
Actuator JMS Health Check Return False Positive With Java Configuration
我遇到了 运行 一个问题,即使我的路由可以连接并向 JMS 生成消息,执行器探测仍无法检测 JMS 健康状况。所以简而言之,执行器说它已关闭但它正在工作。
技术堆栈和技术说明:
- Spring-引导:2.3.1.RELEASE
- 骆驼:3.4.1
- 阿尔忒弥斯:2.11.0
- Artemis 已设置为使用用户名和密码(artemis/artemis)。
- 使用
org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
作为连接工厂。
我的路线很简单:
<route id="timer-cluster-producer-route">
<from uri="timer:producer-ticker?delay=5000"/>
<setBody>
<groovy>
result = ["Name":"Johnny"]
</groovy>
</setBody>
<marshal>
<json library="Jackson"/>
</marshal>
<to uri="ref:jms-producer-cluster-event" />
</route>
XML 基于 Artemis 配置
使用 Spring-boot 支持基于 java 的配置我正忙于迁移我们的 XML beans accordingly.Thus 我将工作 beans.xml 文件粘贴到项目并启动路由,我可以发送消息流,健康检查返回正常。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jmsConnectionFactory"
class="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="user" value="artemis"/>
<property name="password" value="artemis"/>
<property name="connectionLoadBalancingPolicyClassName" value="org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy"/>
</bean>
<!--org.messaginghub.pooled.jms.JmsPoolConnectionFactory-->
<!--org.apache.activemq.jms.pool.PooledConnectionFactory-->
<bean id="jmsPooledConnectionFactory"
class="org.apache.activemq.jms.pool.PooledConnectionFactory"
init-method="start" destroy-method="stop">
<property name="maxConnections" value="64" />
<property name="MaximumActiveSessionPerConnection"
value="500" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory"
ref="jmsPooledConnectionFactory" />
<property name="concurrentConsumers" value="1" />
<property name="artemisStreamingEnabled" value="true"/>
</bean>
<bean id="jms"
class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
<!-- <bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>-->
</beans>
Spring-启动自动(黑色)魔法配置
然后我使用 application.yaml 文件通过 this method 配置 artemis 连接,如 Spring-boot 文档中所述。当我的 application.yaml 文件包含以下配置时,这也有效:
artemis:
user: artemis
host: localhost
password: artemis
pool:
max-sessions-per-connection: 500
enabled: true
max-connections: 16
这很有效。
勇敢尝试 Java 配置。
所以我开始寻找黄金并尝试了基于 Java 的配置,如下所述:
@SpringBootApplication
@ImportResource("classpath:/camel/camel.xml")
public class ClusterProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ClusterProducerApplication.class, args);
}
@Bean
public JmsComponent jms() throws JMSException {
// Create the connectionfactory which will be used to connect to Artemis
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
cf.setBrokerURL("tcp://localhost:61616");
cf.setUser("artemis");
cf.setPassword("artemis");
//Create connection pool using connection factory
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
pooledConnectionFactory.setMaxConnections(2);
pooledConnectionFactory.setConnectionFactory(cf);
//Create configuration which uses connection factory
JmsConfiguration jmsConfiguration = new JmsConfiguration();
jmsConfiguration.setConcurrentConsumers(2);
jmsConfiguration.setArtemisStreamingEnabled(true);
jmsConfiguration.setConnectionFactory(pooledConnectionFactory);
// Create the Camel JMS component and wire it to our Artemis configuration
JmsComponent jms = new JmsComponent();
jms.setConfiguration(jmsConfiguration);
return jms;
}
}
所以当 camel 启动时,我在启动时看到以下警告:
020-07-28 12:33:38.631 WARN 25329 --- [)-192.168.1.158] o.s.boot.actuate.jms.JmsHealthIndicator : JMS health check failed
javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from /127.0.0.1:42028. Username: null; SSL certificate subject DN: unavailable
5 秒延迟后,计时器启动并生成消息。我登录到 Artemis 控制台,我可以浏览消息并可以看到它们正在创建。但是,当我 运行 获取执行器运行状况时,我看到以下内容:
"jms": {
"status": "DOWN",
"details": {
"error": "javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from /127.0.0.1:42816. Username: null; SSL certificate subject DN: unavailable"
}
},
这对我来说是个大错误。
关于连接池实现的观察。
我注意到 AMQ 连接池已移至以下 Maven 依赖项中:
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
</dependency>
我想我也试试看。它显示了与上面概述的相同的行为以及一件更有趣的事情。当使用 org.messaginghub.pooled-jms
作为连接池时(spring-boot 文档也推荐),启动时会记录以下内容。
2020-07-28 12:41:37.255 INFO 26668 --- [ main] o.m.pooled.jms.JmsPoolConnectionFactory : JMS ConnectionFactory on classpath is not a JMS 2.0+ version.
这很奇怪,因为根据 the official repo 连接器是 JMS 2.0 兼容的。
快速总结:
在通过 Java 配置 JMS 组件时,执行器似乎没有获取连接工厂的凭据。虽然目前通过使用 spring-boot application.yaml 配置存在变通方法,但它限制了您在 Camel 上配置 JMS 客户端的方式。
所以经过一些挖掘和 reaching out to the Spring-boot people on GitHub,我发现了问题所在。使用 Java 配置时,我正在使用连接工厂配置 Camel 的 JMS 组件。然而 Spring-boot 完全不知道这一点,因为它是一个 Camel 组件。因此,JMS 使用的连接工厂需要暴露给 Spring-boot 才能工作。
修复相对简单。请参阅下面的代码:
@Configuration
public class ApplicationConfiguration {
private ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
@Bean
public JmsComponent jms() throws JMSException {
// Create the connectionfactory which will be used to connect to Artemis
cf.setBrokerURL("tcp://localhost:61616");
cf.setUser("artemis");
cf.setPassword("artemis");
// Setup Connection pooling
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
pooledConnectionFactory.setMaxConnections(2);
pooledConnectionFactory.setConnectionFactory(cf);
JmsConfiguration jmsConfiguration = new JmsConfiguration();
jmsConfiguration.setConcurrentConsumers(2);
jmsConfiguration.setArtemisStreamingEnabled(true);
jmsConfiguration.setConnectionFactory(pooledConnectionFactory);
// Create the Camel JMS component and wire it to our Artemis connectionfactory
JmsComponent jms = new JmsComponent();
jms.setConfiguration(jmsConfiguration);
return jms;
}
/*
This line will expose the connection factory to Spring-boot.
*/
@Bean
public ConnectionFactory jmsConnectionFactory() {
return cf;
}
}
我遇到了 运行 一个问题,即使我的路由可以连接并向 JMS 生成消息,执行器探测仍无法检测 JMS 健康状况。所以简而言之,执行器说它已关闭但它正在工作。
技术堆栈和技术说明:
- Spring-引导:2.3.1.RELEASE
- 骆驼:3.4.1
- 阿尔忒弥斯:2.11.0
- Artemis 已设置为使用用户名和密码(artemis/artemis)。
- 使用
org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
作为连接工厂。
我的路线很简单:
<route id="timer-cluster-producer-route">
<from uri="timer:producer-ticker?delay=5000"/>
<setBody>
<groovy>
result = ["Name":"Johnny"]
</groovy>
</setBody>
<marshal>
<json library="Jackson"/>
</marshal>
<to uri="ref:jms-producer-cluster-event" />
</route>
XML 基于 Artemis 配置
使用 Spring-boot 支持基于 java 的配置我正忙于迁移我们的 XML beans accordingly.Thus 我将工作 beans.xml 文件粘贴到项目并启动路由,我可以发送消息流,健康检查返回正常。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jmsConnectionFactory"
class="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="user" value="artemis"/>
<property name="password" value="artemis"/>
<property name="connectionLoadBalancingPolicyClassName" value="org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy"/>
</bean>
<!--org.messaginghub.pooled.jms.JmsPoolConnectionFactory-->
<!--org.apache.activemq.jms.pool.PooledConnectionFactory-->
<bean id="jmsPooledConnectionFactory"
class="org.apache.activemq.jms.pool.PooledConnectionFactory"
init-method="start" destroy-method="stop">
<property name="maxConnections" value="64" />
<property name="MaximumActiveSessionPerConnection"
value="500" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory"
ref="jmsPooledConnectionFactory" />
<property name="concurrentConsumers" value="1" />
<property name="artemisStreamingEnabled" value="true"/>
</bean>
<bean id="jms"
class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
<!-- <bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>-->
</beans>
Spring-启动自动(黑色)魔法配置
然后我使用 application.yaml 文件通过 this method 配置 artemis 连接,如 Spring-boot 文档中所述。当我的 application.yaml 文件包含以下配置时,这也有效:
artemis:
user: artemis
host: localhost
password: artemis
pool:
max-sessions-per-connection: 500
enabled: true
max-connections: 16
这很有效。
勇敢尝试 Java 配置。
所以我开始寻找黄金并尝试了基于 Java 的配置,如下所述:
@SpringBootApplication
@ImportResource("classpath:/camel/camel.xml")
public class ClusterProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ClusterProducerApplication.class, args);
}
@Bean
public JmsComponent jms() throws JMSException {
// Create the connectionfactory which will be used to connect to Artemis
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
cf.setBrokerURL("tcp://localhost:61616");
cf.setUser("artemis");
cf.setPassword("artemis");
//Create connection pool using connection factory
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
pooledConnectionFactory.setMaxConnections(2);
pooledConnectionFactory.setConnectionFactory(cf);
//Create configuration which uses connection factory
JmsConfiguration jmsConfiguration = new JmsConfiguration();
jmsConfiguration.setConcurrentConsumers(2);
jmsConfiguration.setArtemisStreamingEnabled(true);
jmsConfiguration.setConnectionFactory(pooledConnectionFactory);
// Create the Camel JMS component and wire it to our Artemis configuration
JmsComponent jms = new JmsComponent();
jms.setConfiguration(jmsConfiguration);
return jms;
}
}
所以当 camel 启动时,我在启动时看到以下警告:
020-07-28 12:33:38.631 WARN 25329 --- [)-192.168.1.158] o.s.boot.actuate.jms.JmsHealthIndicator : JMS health check failed
javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from /127.0.0.1:42028. Username: null; SSL certificate subject DN: unavailable
5 秒延迟后,计时器启动并生成消息。我登录到 Artemis 控制台,我可以浏览消息并可以看到它们正在创建。但是,当我 运行 获取执行器运行状况时,我看到以下内容:
"jms": {
"status": "DOWN",
"details": {
"error": "javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from /127.0.0.1:42816. Username: null; SSL certificate subject DN: unavailable"
}
},
这对我来说是个大错误。
关于连接池实现的观察。
我注意到 AMQ 连接池已移至以下 Maven 依赖项中:
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
</dependency>
我想我也试试看。它显示了与上面概述的相同的行为以及一件更有趣的事情。当使用 org.messaginghub.pooled-jms
作为连接池时(spring-boot 文档也推荐),启动时会记录以下内容。
2020-07-28 12:41:37.255 INFO 26668 --- [ main] o.m.pooled.jms.JmsPoolConnectionFactory : JMS ConnectionFactory on classpath is not a JMS 2.0+ version.
这很奇怪,因为根据 the official repo 连接器是 JMS 2.0 兼容的。
快速总结: 在通过 Java 配置 JMS 组件时,执行器似乎没有获取连接工厂的凭据。虽然目前通过使用 spring-boot application.yaml 配置存在变通方法,但它限制了您在 Camel 上配置 JMS 客户端的方式。
所以经过一些挖掘和 reaching out to the Spring-boot people on GitHub,我发现了问题所在。使用 Java 配置时,我正在使用连接工厂配置 Camel 的 JMS 组件。然而 Spring-boot 完全不知道这一点,因为它是一个 Camel 组件。因此,JMS 使用的连接工厂需要暴露给 Spring-boot 才能工作。
修复相对简单。请参阅下面的代码:
@Configuration
public class ApplicationConfiguration {
private ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
@Bean
public JmsComponent jms() throws JMSException {
// Create the connectionfactory which will be used to connect to Artemis
cf.setBrokerURL("tcp://localhost:61616");
cf.setUser("artemis");
cf.setPassword("artemis");
// Setup Connection pooling
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
pooledConnectionFactory.setMaxConnections(2);
pooledConnectionFactory.setConnectionFactory(cf);
JmsConfiguration jmsConfiguration = new JmsConfiguration();
jmsConfiguration.setConcurrentConsumers(2);
jmsConfiguration.setArtemisStreamingEnabled(true);
jmsConfiguration.setConnectionFactory(pooledConnectionFactory);
// Create the Camel JMS component and wire it to our Artemis connectionfactory
JmsComponent jms = new JmsComponent();
jms.setConfiguration(jmsConfiguration);
return jms;
}
/*
This line will expose the connection factory to Spring-boot.
*/
@Bean
public ConnectionFactory jmsConnectionFactory() {
return cf;
}
}