现象
业务中用到了阿里云的ONS服务,开发中相同配置的情况下,在外网环境(mac开发机)上与阿里云ecs服务器上,服务启动时间相差巨大 (11.124 seconds与23.863 seconds的差距,相差接近10秒),查看日志并没有发现任何error出现,但是有一个奇怪的现象是,就是在外网环境启动时,两条日志记录的间隔时间也差不多是10秒左右。
解决思路
此时考虑,可能是main线程在这两条日志记录中间有耗时操作。于是打开VisualVM对java进程进行了thread dump。dump结果如下:
可以看到,调用栈在sun.net.www.http.HttpClient
处锁住了,调用方是com.aliyun.openservices.shade.com.alibaba.rocketmq.common.utils.HttpTinyClient.httpGet
既然找到了位置,那么就可以加断点调试了。
加断点后调试查询发现,ons启动时会默认连接两个地址http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet
与http://onsaddr-internal.aliyun.com:8080/rocketmq/nsaddr4client-internal
,前一个地址从url中可以看出就是个外网访问地址,但是后一个地址是一个内网地址。这样在外网环境下连接时会因为连接不上而超时,超时时间默认设置又是5秒,这也与项目中使用了两个队列相吻合。
解决方式
既然是默认连接两个地址,那么自然应该会有配置来设置只连内网或者只连外网。
private fun initProperties(): Properties {
val properties = Properties()
properties.setProperty(PropertyKeyConst.AccessKey, messageQueueProperties.accessKey)
properties.setProperty(PropertyKeyConst.SecretKey, messageQueueProperties.secretKey)
// 注意,一定要传这个值,否则外网启动会慢到死
//properties.setProperty(PropertyKeyConst.ONSAddr, messageQueueProperties.onsAddr)
return properties
}
这是我们配置ons的函数,可以看到默认是,是不设置PropertyKeyConst.ONSAddr
这个配置的,这样ons启动时就会内网地址与外网地址同时连接。但是配置后,就只会连接设置的messageQueueProperties.onsAddr
地址了。搭配spring的profile进行环境区分,不同环境配置不同的onsAddr就可以完美解决这个问题了。