ActiveMQ简介
MQ是消息中间件,是一种在分布式系统中应用程序借以传递消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的开源项目,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现。消息类型包括点对点(queue),一对多(topic),本次生产环境用的是queue。
1、部署环境
三个ActiveMQ实例+MySQL数据数据库持久化,三台ActiveMQ采用failover方式,MQ数据持久化在MySQL数据库中,MySQL采用主备方式,该架构保证数据高可用性。目前线上压测TPS为1200,满足实际生产需求。
实际TPS到2、3千没问题。
2、Producer优化
采用spring+activemq实现,采用PooledConnectionFactory连接池,用于缓存session和producter,在高并发情况下不要采用CachingConnectionFactory,CachingConnectionFactory共享一个connection,TPS上不去。
对发送TPS有直接影响的参数如下
1.ActiveMQConnectionFactory调优
connectionFactory.setUseAsyncSend(activeMqProperties.isAsyncSend()); // 同步\异步发送消息,如果是异步需要设置 connectionFactory.setProducerWindowSize(10240);
connectionFactory.setMaxThreadPoolSize(activeMqProperties.getMaxThreadPoolSize()); // session线程池 2.PooledConnectionFactory调优
pooledConnectionFactory.setMaxConnections(10); // 最大connection数量,和生产者TPS直接相关
pooledConnectionFactory.setMaximumActiveSessionPerConnection(5); // 每个connection的最大session数
3、consumer优化
对消费TPS有直接影响的参数如下
asyncSend=true //设置为true,异步方式,如果是false和生产者有关系,严重影响消费TPS
queuePrefetch=1 // 实际测试为1效率高,设置比较大时,严重影响消费TPS
concurrentConsumers=100 // 消费者线程总量,和消费TPS直接相关
4、MQ数据持久化数据库配置
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activemq?characterEncoding=utf-8&relaxAutoCommit=true" />
<property name="username" value="root" />
<property name="password" value="123" />
<property name="initialSize" value="100" />
<property name="maxTotal" value="500" />
<property name="maxIdle" value="30" />
<property name="maxWaitMillis" value="10000" />
<property name="minIdle" value="1" />
<property name="poolPreparedStatements" value="true"/>
<property name="connectionProperties" value="connectTimeout=60000;socketTimeout=60000"/> // 特别注意,当数据库发生主从切换时,
需要断开数据库链接,不然会卡死当前主MQ实例
</bean>
特别注意:
对于mq在mysql发生主从切换时卡死20分钟问题的解决方案如下
1.运维写了个脚本监控,当数据库主服务宕机后,监控3306端口连接情况,当3306端口没有连接后在漂移到从数据库
经过验证,大概20s mq恢复正常工作,不丢弃数据;
2.mq配置文件配置jdbc连接时加上connectTimeout=60000;socketTimeout=60000,当数据库主宕机后,1分钟左右mq恢复正常工作,不丢弃数据;
PS:当mysql主服务实例挂了,方案1起作用;如果mysql主服务器重启这种机器故障,方案2起作用。