解决ActiveMQ的“Invalid broker URI”异常的历程

000

最近碰到一个问题,把解决的过程记录下来。

故障原因

同事的应用上线,Tomcat无法正常启动。抛出这样的异常:

org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:|PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'brokerURL' threw exception; nested exception is java.lang.IllegalArgumentException: Invalid broker URI: nio://10.0.0.0:91616
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1504)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1216)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

据同事说,在线下环境,可以正常运行,在线上环境就出错了,非常的诡异。

程序有一个env.properties的配置文件:

broker.producer  = failover://(nio://10.0.0.3:91615?connectionTimeout=3000,nio://10.0.0.4:91615?connectionTimeout=3000)

线上和线下加载的是不同的env.properties。

在Spring xml配置文件里有这样的配置:

	<!-- ActiveMQ 连接工厂 -->
	<amq:connectionFactory id="jmsConnectionFactory" brokerURL="${broker.producer}" />

Spring在运行时,会自动替换${}表达式里的值。

首先检查网络的连通性:

在线上机器上,执行

telnet 10.0.0.3 91616

可以正常连接,再到ActiveMQ的Web Console上查看Connection,发现的确没有这个IP的连接。

检查配置是否正常:

线上的配置的brokerURI是这个:

failover://(nio://10.0.0.3:91616?connectionTimeout=3000,nio://10.0.0.4:91616?connectionTimeout=3000)

直接先改为最简单的,在vim下yy复制了一行,删除多余的,剩下:

nio://10.0.0.3:91616

发现还是报异常。

利用ssh做端口转发,本地测试

在本地跑了个简单程序,用XShell的端口转发,把本地请求转发到线上机器上,发现可以正常发送消息。于是让同事回去检查代码里的其它问题了。

把测试程序放到线上机器运行

但是同事没有找到错误,于是把刚才的简单的程序打成一个fat jar包,放到线上机器上去跑,发现可以正常发送ActiveMQ消息。

程序打包用的是maven的one jar 插件,参考:

http://www.mkyong.com/maven/maven-create-a-fat-jar-file-one-jar-example/

把测试程序集成到同事的代码里,运行

把测试程序放到同事的War包的代码里,放到线上机器,发现可以正常发送消息。

但是同事配置的ActiveMQ还是不能发送消息,还是报“Invalid broker URI”异常。

增加变量,反复测试,对比配置

没办法了,把同事的环境变量${broker.producer},设置到测试代码里,发现测试代码抛异常了。

于是确认是${broker.producer} 这个变量有问题。

但是env.properties文件里的配置看起来是对的。于是怀疑是配置文件格式有问题。

备份旧文件,建了个新配置文件,配置上

broker.producer =nio://10.0.0.3:91615

发现,居然正常了。

于是对比两个配置文件,发现旧的配置文件上,最后多了一个空格。。就是91615后面多了一个空格。

蛋疼无比,ActiveMQ居然不能识别处理配置值后面多出来的一个空格。而且Spring抛出来的异常里也没有这个信息。

搜索关键字"Invalid broker URI",查看ActiveMQ代码,找到原始异常

开始调试时,找不到原始的异常信息在哪里,Spring的函数调用层次太多了。于是采用代码搜索。

在 https://searchcode.com 搜索"Invalid broker URI",终于找到原始的异常信息是下面的代码抛出来的:

URI org.apache.activemq.ActiveMQConnectionFactory.createURI(String brokerURL)
    private static URI createURI(String brokerURL) {
        try {
            return new URI(brokerURL);
        } catch (URISyntaxException e) {
            throw (IllegalArgumentException)new IllegalArgumentException("Invalid broker URI: " + brokerURL).initCause(e);
        }
    }

很奇怪的是,IllegalArgumentException异常里是正确地把URISyntaxException设置到cause里了,后面的Spring却没有把这个信息给打印出来。。

Spring打印异常的工作原理

为什么Spring能把前面的异常信息都打印出来,而原始的异常信息却不能打印出来?比如某个Spring异常信息是这样的:

Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:

Srping会用Caused by,nested exception is,这样的字符把所有的异常都串起来。到底这里面是怎么工作的?

再次搜索"nested exception is"

查找到Spring相关的代码。

原来所有的Spring异常类都继承自NestedRuntimeException,而NestedRuntimeException重写了getMessage()函数,在getMessage()函数里,会把异常的信息全都串起来。

而IllegalArgumentException继承自Throwable类,Throwable类的getMessage()函数只是简单打印了message,并没有把cause也输出。

org.springframework.core.NestedRuntimeException

	/**
	 * Return the detail message, including the message from the nested exception
	 * if there is one.
	 */
	@Override
	public String getMessage() {
		return NestedExceptionUtils.buildMessage(super.getMessage(), getCause());
	}

org.springframework.core.NestedExceptionUtils
	/**
	 * Build a message for the given base message and root cause.
	 * @param message the base message
	 * @param cause the root cause
	 * @return the full exception message
	 */
	public static String buildMessage(String message, Throwable cause) {
		if (cause != null) {
			StringBuilder sb = new StringBuilder();
			if (message != null) {
				sb.append(message).append("; ");
			}
			sb.append("nested exception is ").append(cause);
			return sb.toString();
		}
		else {
			return message;
		}
	}

其它的一些东东:

NestedExceptionUtils这个类是abstract,这样可以防止使用者得到实例,这样使用者不能用错。这个也是一个常见的util类的技巧了。

public abstract class NestedExceptionUtils {

总结:

这个代码搜索网站比较好用:https://searchcode.com

很多流行网站的数据都有,比github上要全。

后来在网上搜索了下“Invalid broker URI”,有10万多条结果。。估计有不少就是因为一些空格而造成的。。

ActiveMQ的开发者只需要加上一点点的trim()的判断处理代码,就可以减少很多人的痛苦了。

所以防御性编程还是有必要的,有的时候并不真的是使用者不会用,而是错误来自想像不到的地方。

URI org.apache.activemq.ActiveMQConnectionFactory.createURI(String brokerURL)
    private static URI createURI(String brokerURL) {
        try {
            if(brokerURL != null)
                brokerURL = brokerURL.trim();
            return new URI(brokerURL);
        } catch (URISyntaxException e) {
            throw (IllegalArgumentException)new IllegalArgumentException("Invalid broker URI: " + brokerURL).initCause(e);
        }
    }
时间: 2024-08-31 06:40:18

解决ActiveMQ的“Invalid broker URI”异常的历程的相关文章

如何解决centos下root运行Elasticsearch异常

  如何解决centos下root运行Elasticsearch异常            在CentOS 6.5 上运行Elasticsearch 2.3,异常如下: ? 1 2 3 4 5 6 Exception in thread "main" java.lang.RuntimeException: don't run elasticsearch as root. at org.elasticsearch.bootstrap.Bootstrap.initializeNatives

activemq集群-activemq 使用network broker集群后,怎样提高AMQ相互之间的通信速度???

问题描述 activemq 使用network broker集群后,怎样提高AMQ相互之间的通信速度??? activemq使用network broker集群之后,消息的处理速度会被拉下来,每秒只有几百个,反复修改配置文件都没有提高上去,我认为主要修改两个地方一个是networkConnectors,另一个是policyEntry,大家都是怎么配置的,配置分布式之后同步传输速度就慢了,可是我感觉两台服务之间使用的是同步传输的:Network connection between vm://13

Android 解决双卡双待手机解析短信异常

http://blog.csdn.net/t12x3456/article/details/17339657 开发中,难免会遇到各种各样的适配问题,尤其是经过深度修改定制过的系统,有的无论是软硬件上都有很大的区别,这里不得不提到一种奇葩的机型,没错,那就是双卡双待的手机(比如XT800, A60, S8600 , Lenovo A750,中兴V889D等).由于是双SIM卡,而且两个卡槽支持的运营商或者网络制式不一定相同,比如一个卡槽支持WCDMA,另一个却只支持GSM ,导致用正常方法解析短信

解决QQ登录提示redirect uri is illegal(100010)办法

大概2015年3月低,腾讯QQ互联开发平台调整了有关QQ登录应用回调地址填写规则,用来修复QQ登录过程因回调地址的漏洞可能导致存在的安全问题.   博主接触这块较多,但也是四月才了解此事,从4月起,所有新申请的QQ互联应用,回调地址都不能只填写根域名,比方:unvs.cn,这样是不允许的.   解决方法:必须要填写你应用QQ登录返回的真实回调地址页面,必须带有HTTP://开头.及页面名称结尾,如:http://www.unvs.cn/oauth/default.aspx.   否则点击QQ登录

解决手机QQ浏览器视频解析异常办法

手机QQ浏览器视频解析异常解决办法 1.在手机中我们打开QQ浏览器,然后点击浏览器右上角的三横(菜单) 2.好了在打开进入之后来我们在菜单界面,点击设置 效果如下图所示 3.在打开进入到界面我们可以向下翻,找到关于与反馈,效果如下图所示. 4.然后会进入这一栏,接着点击版本 5.在我们QQ浏览器检查更新之后看看上不是需要下载最新版,点击是下载最新版,安装上去,当再次打开浏览器就会发现视频可以正常播放了 好了以上就是关于手机QQ浏览器视频解析失败问题的解决办法了,如果还是不行我们重新安装一下浏览器

天天酷跑不能玩的解决方法 卡屏以及进程异常

腾讯的天天酷跑这款游戏,如今不管是IOS平台还是安卓平台,都已经可以玩了,但是肯定有安卓朋友出现了天天酷跑不能玩的问题,因为小狸飞刀这里也出现了,下面就讲解下自己找到的解决方法吧.不能玩的问题主要还是出现在安卓设备上,因为用ipad4设备测试了好几次,游戏都可以完美运行.不能玩的情况一:游戏卡在第一屏第一种就是 如下图所示,游戏打开后,就卡在游戏的第一屏,然后毫无反应了,这种情况真的让人忍不住想要吐槽.解决方法:并没有找到好的解决方法,比较好用的就是按手机HOME键回到手机主菜单,然后点击任务管

该怎么解决-SSH框架整合,出现异常

问题描述 SSH框架整合,出现异常 java.lang.reflect.InvocationTargetException sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(De

怎么解决C#套接字编程异常&amp;amp;quot;以一种访问权限不允许的方式做了一个访问套接字的尝试&amp;amp;quot;

问题描述 我想问一下,我在使用c#套接字编程做了一个ping应用程序.调试的时候出现一个异常,"以一种访问权限不允许的方式做了一个访问套接字的尝试".网上说是端口或ip冲突,但是我的程序里没有明确使用端口号这些,你觉得可能是什么原因? 解决方案 解决方案二:Socket构造函数的参数搭配错误解决方案三:引用1楼Poopaye的回复: Socket构造函数的参数搭配错误 每次执行到socketsocket=newsocket(AddressFamily.InterNetwork,sock

大家谁帮我解决一下连接数据库报System.NullReferenceException异常的错??谢谢

问题描述 privateSqlConnectioncon;privatevoidForm1_Load(objectsender,System.EventArgse){this.con=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=pubs");this.con.Open();}我在窗体加载时只写了这两句,SQLServer服务也开了,但就是报System.NullReferenceException异常啦请求指点谢谢大家