Commit a2aff61fe3ccbdaa2745868c1334a579bec519f2
1 parent
b2ebdd73
整合阿里云RocketMQ SDK
Showing
14 changed files
with
960 additions
and
1352 deletions
pom.xml
| @@ -60,17 +60,6 @@ | @@ -60,17 +60,6 @@ | ||
| 60 | <artifactId>spring-boot-starter</artifactId> | 60 | <artifactId>spring-boot-starter</artifactId> |
| 61 | </dependency> | 61 | </dependency> |
| 62 | <dependency> | 62 | <dependency> |
| 63 | - <groupId>org.apache.rocketmq</groupId> | ||
| 64 | - <artifactId>rocketmq-client</artifactId> | ||
| 65 | - <version>${rocketmq-version}</version> | ||
| 66 | - <exclusions> | ||
| 67 | - <exclusion> | ||
| 68 | - <groupId>org.slf4j</groupId> | ||
| 69 | - <artifactId>slf4j-api</artifactId> | ||
| 70 | - </exclusion> | ||
| 71 | - </exclusions> | ||
| 72 | - </dependency> | ||
| 73 | - <dependency> | ||
| 74 | <groupId>com.aliyun.openservices</groupId> | 63 | <groupId>com.aliyun.openservices</groupId> |
| 75 | <artifactId>ons-client</artifactId> | 64 | <artifactId>ons-client</artifactId> |
| 76 | <version>1.7.2.Final</version> | 65 | <version>1.7.2.Final</version> |
src/main/java/org/apache/rocketmq/spring/starter/AliyunRocketMQAutoConfiguration.java
| @@ -22,13 +22,12 @@ import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerCon | @@ -22,13 +22,12 @@ import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerCon | ||
| 22 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_MODE; | 22 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_MODE; |
| 23 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_THREAD_MAX; | 23 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_THREAD_MAX; |
| 24 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_MESSAGE_MODEL; | 24 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_MESSAGE_MODEL; |
| 25 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_NAMESERVER; | ||
| 26 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_OBJECT_MAPPER; | 25 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_OBJECT_MAPPER; |
| 27 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_LISTENER; | 26 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_LISTENER; |
| 28 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_TEMPLATE; | 27 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_TEMPLATE; |
| 29 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_EXPRESS; | 28 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_EXPRESS; |
| 30 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_TYPE; | 29 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_TYPE; |
| 31 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_TOPIC; | 30 | +import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; |
| 32 | 31 | ||
| 33 | import java.util.Map; | 32 | import java.util.Map; |
| 34 | import java.util.Objects; | 33 | import java.util.Objects; |
| @@ -39,7 +38,6 @@ import javax.annotation.Resource; | @@ -39,7 +38,6 @@ import javax.annotation.Resource; | ||
| 39 | 38 | ||
| 40 | import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | 39 | import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; |
| 41 | import org.apache.rocketmq.spring.starter.core.AliyunRocketMQListenerContainer; | 40 | import org.apache.rocketmq.spring.starter.core.AliyunRocketMQListenerContainer; |
| 42 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
| 43 | import org.apache.rocketmq.spring.starter.core.RocketMQListener; | 41 | import org.apache.rocketmq.spring.starter.core.RocketMQListener; |
| 44 | import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | 42 | import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; |
| 45 | import org.springframework.aop.support.AopUtils; | 43 | import org.springframework.aop.support.AopUtils; |
| @@ -72,7 +70,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -72,7 +70,6 @@ import lombok.extern.slf4j.Slf4j; | ||
| 72 | 70 | ||
| 73 | @Configuration | 71 | @Configuration |
| 74 | @EnableConfigurationProperties(RocketMQProperties.class) | 72 | @EnableConfigurationProperties(RocketMQProperties.class) |
| 75 | -@ConditionalOnProperty(name = "spring.rocketmq.aliyun",havingValue="true") | ||
| 76 | @Order | 73 | @Order |
| 77 | @Slf4j | 74 | @Slf4j |
| 78 | public class AliyunRocketMQAutoConfiguration { | 75 | public class AliyunRocketMQAutoConfiguration { |
| @@ -80,23 +77,27 @@ public class AliyunRocketMQAutoConfiguration { | @@ -80,23 +77,27 @@ public class AliyunRocketMQAutoConfiguration { | ||
| 80 | @Bean | 77 | @Bean |
| 81 | @ConditionalOnClass(Producer.class) | 78 | @ConditionalOnClass(Producer.class) |
| 82 | @ConditionalOnMissingBean(Producer.class) | 79 | @ConditionalOnMissingBean(Producer.class) |
| 83 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"}) | 80 | + @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"environmentPrefix", "producer.group"}) |
| 84 | public Producer mqProducer(RocketMQProperties rocketMQProperties) { | 81 | public Producer mqProducer(RocketMQProperties rocketMQProperties) { |
| 85 | 82 | ||
| 86 | RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); | 83 | RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); |
| 87 | String groupName = producerConfig.getGroup(); | 84 | String groupName = producerConfig.getGroup(); |
| 88 | Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); | 85 | Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); |
| 89 | String accessKey = rocketMQProperties.getAccessKey(); | 86 | String accessKey = rocketMQProperties.getAccessKey(); |
| 90 | - Assert.hasText(accessKey, "[spring.rocketmq.producer.accessKey] must not be null"); | 87 | + Assert.hasText(accessKey, "[spring.rocketmq.accessKey] must not be null"); |
| 91 | String secretKey = rocketMQProperties.getSecretKey(); | 88 | String secretKey = rocketMQProperties.getSecretKey(); |
| 92 | - Assert.hasText(secretKey, "[spring.rocketmq.producer.secretKey] must not be null"); | 89 | + Assert.hasText(secretKey, "[spring.rocketmq.secretKey] must not be null"); |
| 90 | + String onsAddr = rocketMQProperties.getOnsAddr(); | ||
| 91 | + Assert.hasText(secretKey, "[spring.rocketmq.onsAddr] must not be null"); | ||
| 92 | + String environmentPrefix = rocketMQProperties.getEnvironmentPrefix(); | ||
| 93 | + Assert.hasText(secretKey, "[spring.rocketmq.environmentPrefix] must not be null"); | ||
| 93 | 94 | ||
| 94 | Properties producerProperties = new Properties(); | 95 | Properties producerProperties = new Properties(); |
| 95 | - producerProperties.setProperty(PropertyKeyConst.ProducerId, "PID_"+groupName); | 96 | + //生成者ProducerId添加前缀:PID_+环境标识_+groupName |
| 97 | + producerProperties.setProperty(PropertyKeyConst.ProducerId, "PID_"+environmentPrefix+"_"+groupName); | ||
| 96 | producerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); | 98 | producerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); |
| 97 | producerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); | 99 | producerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); |
| 98 | - producerProperties.setProperty(PropertyKeyConst.ONSAddr, rocketMQProperties.getNameServer()); | ||
| 99 | - | 100 | + producerProperties.setProperty(PropertyKeyConst.ONSAddr, onsAddr); |
| 100 | Producer producer = ONSFactory.createProducer(producerProperties); | 101 | Producer producer = ONSFactory.createProducer(producerProperties); |
| 101 | return producer; | 102 | return producer; |
| 102 | } | 103 | } |
| @@ -111,12 +112,13 @@ public class AliyunRocketMQAutoConfiguration { | @@ -111,12 +112,13 @@ public class AliyunRocketMQAutoConfiguration { | ||
| 111 | @Bean(destroyMethod = "destroy") | 112 | @Bean(destroyMethod = "destroy") |
| 112 | @ConditionalOnBean(Producer.class) | 113 | @ConditionalOnBean(Producer.class) |
| 113 | @ConditionalOnMissingBean(name = "rocketMQTemplate") | 114 | @ConditionalOnMissingBean(name = "rocketMQTemplate") |
| 114 | - public RocketMQTemplate rocketMQTemplate(Producer mqProducer, | 115 | + public RocketMQTemplate rocketMQTemplate(Producer mqProducer,RocketMQProperties rocketMQProperties, |
| 115 | @Autowired(required = false) | 116 | @Autowired(required = false) |
| 116 | @Qualifier("rocketMQMessageObjectMapper") | 117 | @Qualifier("rocketMQMessageObjectMapper") |
| 117 | ObjectMapper objectMapper) { | 118 | ObjectMapper objectMapper) { |
| 118 | RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); | 119 | RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); |
| 119 | rocketMQTemplate.setAliyunProducer(mqProducer); | 120 | rocketMQTemplate.setAliyunProducer(mqProducer); |
| 121 | + rocketMQTemplate.setEnvironmentPrefix(rocketMQProperties.getEnvironmentPrefix()); | ||
| 120 | if (Objects.nonNull(objectMapper)) { | 122 | if (Objects.nonNull(objectMapper)) { |
| 121 | rocketMQTemplate.setObjectMapper(objectMapper); | 123 | rocketMQTemplate.setObjectMapper(objectMapper); |
| 122 | } | 124 | } |
| @@ -176,10 +178,11 @@ public class AliyunRocketMQAutoConfiguration { | @@ -176,10 +178,11 @@ public class AliyunRocketMQAutoConfiguration { | ||
| 176 | RocketMQListener rocketMQListener = (RocketMQListener) bean; | 178 | RocketMQListener rocketMQListener = (RocketMQListener) bean; |
| 177 | RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); | 179 | RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); |
| 178 | BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(AliyunRocketMQListenerContainer.class); | 180 | BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(AliyunRocketMQListenerContainer.class); |
| 179 | - beanBuilder.addPropertyValue(PROP_NAMESERVER, rocketMQProperties.getNameServer()); | ||
| 180 | - beanBuilder.addPropertyValue(PROP_TOPIC, environment.resolvePlaceholders(annotation.topic())); | 181 | + beanBuilder.addPropertyValue(PROP_ONS_Addr, rocketMQProperties.getOnsAddr()); |
| 182 | + beanBuilder.addPropertyValue(PROP_TOPIC, rocketMQProperties.getEnvironmentPrefix()+"_"+environment.resolvePlaceholders(annotation.topic())); | ||
| 181 | 183 | ||
| 182 | - beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, environment.resolvePlaceholders(annotation.consumerGroup())); | 184 | + //消费者ConsumerId添加前缀:PID_+环境标识_+groupName |
| 185 | + beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, "CID_"+rocketMQProperties.getEnvironmentPrefix()+"_"+environment.resolvePlaceholders(annotation.consumerGroup())); | ||
| 183 | beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); | 186 | beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); |
| 184 | beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); | 187 | beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); |
| 185 | beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); | 188 | beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); |
| @@ -187,13 +190,14 @@ public class AliyunRocketMQAutoConfiguration { | @@ -187,13 +190,14 @@ public class AliyunRocketMQAutoConfiguration { | ||
| 187 | beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); | 190 | beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); |
| 188 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); | 191 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); |
| 189 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); | 192 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); |
| 193 | + beanBuilder.addPropertyValue(PROP_ENVIRONMENT_PREFIX, rocketMQProperties.getEnvironmentPrefix()); | ||
| 190 | if (Objects.nonNull(objectMapper)) { | 194 | if (Objects.nonNull(objectMapper)) { |
| 191 | beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); | 195 | beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); |
| 192 | } | 196 | } |
| 193 | beanBuilder.setDestroyMethodName(METHOD_DESTROY); | 197 | beanBuilder.setDestroyMethodName(METHOD_DESTROY); |
| 194 | //增加阿里云key | 198 | //增加阿里云key |
| 195 | - beanBuilder.addPropertyValue("accessKey", rocketMQProperties.getAccessKey()); | ||
| 196 | - beanBuilder.addPropertyValue("secretKey", rocketMQProperties.getSecretKey()); | 199 | + beanBuilder.addPropertyValue(PROP_ACCESS_KEY, rocketMQProperties.getAccessKey()); |
| 200 | + beanBuilder.addPropertyValue(PROP_SECRET_KEY, rocketMQProperties.getSecretKey()); | ||
| 197 | 201 | ||
| 198 | String containerBeanName = String.format("%s_%s", AliyunRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); | 202 | String containerBeanName = String.format("%s_%s", AliyunRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); |
| 199 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); | 203 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); |
src/main/java/org/apache/rocketmq/spring/starter/RocketMQAutoConfiguration.java deleted
| 1 | -/* | ||
| 2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| 3 | - * contributor license agreements. See the NOTICE file distributed with | ||
| 4 | - * this work for additional information regarding copyright ownership. | ||
| 5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| 6 | - * (the "License"); you may not use this file except in compliance with | ||
| 7 | - * the License. You may obtain a copy of the License at | ||
| 8 | - * | ||
| 9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | - * | ||
| 11 | - * Unless required by applicable law or agreed to in writing, software | ||
| 12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | - * See the License for the specific language governing permissions and | ||
| 15 | - * limitations under the License. | ||
| 16 | - */ | ||
| 17 | - | ||
| 18 | -package org.apache.rocketmq.spring.starter; | ||
| 19 | - | ||
| 20 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 21 | -import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
| 22 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
| 23 | -import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
| 24 | -import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
| 25 | -import java.util.Map; | ||
| 26 | -import java.util.Objects; | ||
| 27 | -import java.util.concurrent.atomic.AtomicLong; | ||
| 28 | -import javax.annotation.Resource; | ||
| 29 | -import lombok.extern.slf4j.Slf4j; | ||
| 30 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
| 31 | -import org.apache.rocketmq.client.impl.MQClientAPIImpl; | ||
| 32 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
| 33 | -import org.springframework.aop.support.AopUtils; | ||
| 34 | -import org.springframework.beans.BeansException; | ||
| 35 | -import org.springframework.beans.factory.InitializingBean; | ||
| 36 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 37 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
| 38 | -import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
| 39 | -import org.springframework.beans.factory.support.DefaultListableBeanFactory; | ||
| 40 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| 41 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
| 42 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| 43 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 44 | -import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| 45 | -import org.springframework.context.ApplicationContext; | ||
| 46 | -import org.springframework.context.ApplicationContextAware; | ||
| 47 | -import org.springframework.context.ConfigurableApplicationContext; | ||
| 48 | -import org.springframework.context.annotation.Bean; | ||
| 49 | -import org.springframework.context.annotation.Configuration; | ||
| 50 | -import org.springframework.core.annotation.Order; | ||
| 51 | -import org.springframework.core.env.StandardEnvironment; | ||
| 52 | -import org.springframework.util.Assert; | ||
| 53 | - | ||
| 54 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; | ||
| 55 | - | ||
| 56 | -@Configuration | ||
| 57 | -@ConditionalOnProperty(name = "spring.rocketmq.aliyun",havingValue="false") | ||
| 58 | -@EnableConfigurationProperties(RocketMQProperties.class) | ||
| 59 | -@ConditionalOnClass(MQClientAPIImpl.class) | ||
| 60 | -@Order | ||
| 61 | -@Slf4j | ||
| 62 | -public class RocketMQAutoConfiguration { | ||
| 63 | - | ||
| 64 | - @Bean | ||
| 65 | - @ConditionalOnClass(DefaultMQProducer.class) | ||
| 66 | - @ConditionalOnMissingBean(DefaultMQProducer.class) | ||
| 67 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"}) | ||
| 68 | - public DefaultMQProducer mqProducer(RocketMQProperties rocketMQProperties) { | ||
| 69 | - | ||
| 70 | - RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); | ||
| 71 | - String groupName = producerConfig.getGroup(); | ||
| 72 | - Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); | ||
| 73 | - | ||
| 74 | - DefaultMQProducer producer = new DefaultMQProducer(producerConfig.getGroup()); | ||
| 75 | - producer.setNamesrvAddr(rocketMQProperties.getNameServer()); | ||
| 76 | - producer.setSendMsgTimeout(producerConfig.getSendMsgTimeout()); | ||
| 77 | - producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed()); | ||
| 78 | - producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed()); | ||
| 79 | - producer.setMaxMessageSize(producerConfig.getMaxMessageSize()); | ||
| 80 | - producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMsgBodyOverHowmuch()); | ||
| 81 | - producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryAnotherBrokerWhenNotStoreOk()); | ||
| 82 | - | ||
| 83 | - return producer; | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - @Bean | ||
| 87 | - @ConditionalOnClass(ObjectMapper.class) | ||
| 88 | - @ConditionalOnMissingBean(name = "rocketMQMessageObjectMapper") | ||
| 89 | - public ObjectMapper rocketMQMessageObjectMapper() { | ||
| 90 | - return new ObjectMapper(); | ||
| 91 | - } | ||
| 92 | - | ||
| 93 | - @Bean(destroyMethod = "destroy") | ||
| 94 | - @ConditionalOnBean(DefaultMQProducer.class) | ||
| 95 | - @ConditionalOnMissingBean(name = "rocketMQTemplate") | ||
| 96 | - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, | ||
| 97 | - @Autowired(required = false) | ||
| 98 | - @Qualifier("rocketMQMessageObjectMapper") | ||
| 99 | - ObjectMapper objectMapper) { | ||
| 100 | - RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); | ||
| 101 | - rocketMQTemplate.setDefaultProducer(mqProducer); | ||
| 102 | - if (Objects.nonNull(objectMapper)) { | ||
| 103 | - rocketMQTemplate.setObjectMapper(objectMapper); | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - return rocketMQTemplate; | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - @Configuration | ||
| 110 | - @ConditionalOnClass(DefaultMQPushConsumer.class) | ||
| 111 | - @EnableConfigurationProperties(RocketMQProperties.class) | ||
| 112 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = "nameServer") | ||
| 113 | - @Order | ||
| 114 | - public static class ListenerContainerConfiguration implements ApplicationContextAware, InitializingBean { | ||
| 115 | - private ConfigurableApplicationContext applicationContext; | ||
| 116 | - | ||
| 117 | - private AtomicLong counter = new AtomicLong(0); | ||
| 118 | - | ||
| 119 | - @Resource | ||
| 120 | - private StandardEnvironment environment; | ||
| 121 | - | ||
| 122 | - @Resource | ||
| 123 | - private RocketMQProperties rocketMQProperties; | ||
| 124 | - | ||
| 125 | - private ObjectMapper objectMapper; | ||
| 126 | - | ||
| 127 | - @Autowired | ||
| 128 | - private RocketMQTemplate rocketMQTemplate; | ||
| 129 | - | ||
| 130 | - public ListenerContainerConfiguration() { | ||
| 131 | - } | ||
| 132 | - | ||
| 133 | - @Autowired(required = false) | ||
| 134 | - public ListenerContainerConfiguration( | ||
| 135 | - @Qualifier("rocketMQMessageObjectMapper") ObjectMapper objectMapper) { | ||
| 136 | - this.objectMapper = objectMapper; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - @Override | ||
| 140 | - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | ||
| 141 | - this.applicationContext = (ConfigurableApplicationContext) applicationContext; | ||
| 142 | - } | ||
| 143 | - | ||
| 144 | - @Override | ||
| 145 | - public void afterPropertiesSet() { | ||
| 146 | - Map<String, Object> beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class); | ||
| 147 | - | ||
| 148 | - if (Objects.nonNull(beans)) { | ||
| 149 | - beans.forEach(this::registerContainer); | ||
| 150 | - } | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - private void registerContainer(String beanName, Object bean) { | ||
| 154 | - Class<?> clazz = AopUtils.getTargetClass(bean); | ||
| 155 | - | ||
| 156 | - if (!RocketMQListener.class.isAssignableFrom(bean.getClass())) { | ||
| 157 | - throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName()); | ||
| 158 | - } | ||
| 159 | - | ||
| 160 | - RocketMQListener rocketMQListener = (RocketMQListener) bean; | ||
| 161 | - RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); | ||
| 162 | - BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultRocketMQListenerContainer.class); | ||
| 163 | - beanBuilder.addPropertyValue(PROP_NAMESERVER, rocketMQProperties.getNameServer()); | ||
| 164 | - beanBuilder.addPropertyValue(PROP_TOPIC, environment.resolvePlaceholders(annotation.topic())); | ||
| 165 | - | ||
| 166 | - beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, environment.resolvePlaceholders(annotation.consumerGroup())); | ||
| 167 | - beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); | ||
| 168 | - beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); | ||
| 169 | - beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); | ||
| 170 | - beanBuilder.addPropertyValue(PROP_SELECTOR_EXPRESS, environment.resolvePlaceholders(annotation.selectorExpress())); | ||
| 171 | - beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); | ||
| 172 | - beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); | ||
| 173 | - beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); | ||
| 174 | - if (Objects.nonNull(objectMapper)) { | ||
| 175 | - beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); | ||
| 176 | - } | ||
| 177 | - beanBuilder.setDestroyMethodName(METHOD_DESTROY); | ||
| 178 | - | ||
| 179 | - String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); | ||
| 180 | - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); | ||
| 181 | - beanFactory.registerBeanDefinition(containerBeanName, beanBuilder.getBeanDefinition()); | ||
| 182 | - | ||
| 183 | - DefaultRocketMQListenerContainer container = beanFactory.getBean(containerBeanName, DefaultRocketMQListenerContainer.class); | ||
| 184 | - | ||
| 185 | - if (!container.isStarted()) { | ||
| 186 | - try { | ||
| 187 | - container.start(); | ||
| 188 | - } catch (Exception e) { | ||
| 189 | - log.error("started container failed. {}", container, e); | ||
| 190 | - throw new RuntimeException(e); | ||
| 191 | - } | ||
| 192 | - } | ||
| 193 | - | ||
| 194 | - log.info("register rocketMQ listener to container, listenerBeanName:{}, containerBeanName:{}", beanName, containerBeanName); | ||
| 195 | - } | ||
| 196 | - } | ||
| 197 | -} |
src/main/java/org/apache/rocketmq/spring/starter/RocketMQProperties.java
| @@ -24,22 +24,25 @@ import org.springframework.boot.context.properties.ConfigurationProperties; | @@ -24,22 +24,25 @@ import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 24 | @ConfigurationProperties(prefix = "spring.rocketmq") | 24 | @ConfigurationProperties(prefix = "spring.rocketmq") |
| 25 | @Data | 25 | @Data |
| 26 | public class RocketMQProperties { | 26 | public class RocketMQProperties { |
| 27 | - | ||
| 28 | - /** | ||
| 29 | - * name server for rocketMQ, formats: `host:port;host:port` | 27 | + /** |
| 28 | + * 环境前缀 | ||
| 29 | + */ | ||
| 30 | + private String environmentPrefix; | ||
| 31 | + /** | ||
| 32 | + * 消息队列服务接入点 | ||
| 30 | */ | 33 | */ |
| 31 | - private String nameServer; | 34 | + private String onsAddr; |
| 32 | 35 | ||
| 33 | - private Producer producer; | ||
| 34 | - /** | ||
| 35 | - * 阿里云分配的accesskey | 36 | + /** |
| 37 | + * AccessKey, 用于标识、校验用户身份 | ||
| 36 | */ | 38 | */ |
| 37 | private String accessKey; | 39 | private String accessKey; |
| 38 | /** | 40 | /** |
| 39 | - * 阿里云分配的secretKey | 41 | + * SecretKey, 用于标识、校验用户身份 |
| 40 | */ | 42 | */ |
| 41 | private String secretKey; | 43 | private String secretKey; |
| 42 | 44 | ||
| 45 | + private Producer producer; | ||
| 43 | @Data | 46 | @Data |
| 44 | public static class Producer { | 47 | public static class Producer { |
| 45 | 48 |
src/main/java/org/apache/rocketmq/spring/starter/annotation/RocketMQMessageListener.java
| @@ -17,15 +17,17 @@ | @@ -17,15 +17,17 @@ | ||
| 17 | 17 | ||
| 18 | package org.apache.rocketmq.spring.starter.annotation; | 18 | package org.apache.rocketmq.spring.starter.annotation; |
| 19 | 19 | ||
| 20 | -import org.apache.rocketmq.common.filter.ExpressionType; | ||
| 21 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 22 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 23 | import java.lang.annotation.Documented; | 20 | import java.lang.annotation.Documented; |
| 24 | import java.lang.annotation.ElementType; | 21 | import java.lang.annotation.ElementType; |
| 25 | import java.lang.annotation.Retention; | 22 | import java.lang.annotation.Retention; |
| 26 | import java.lang.annotation.RetentionPolicy; | 23 | import java.lang.annotation.RetentionPolicy; |
| 27 | import java.lang.annotation.Target; | 24 | import java.lang.annotation.Target; |
| 28 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | 25 | + |
| 26 | +import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 27 | +import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 28 | + | ||
| 29 | +import com.aliyun.openservices.ons.api.ExpressionType; | ||
| 30 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 29 | 31 | ||
| 30 | @Target(ElementType.TYPE) | 32 | @Target(ElementType.TYPE) |
| 31 | @Retention(RetentionPolicy.RUNTIME) | 33 | @Retention(RetentionPolicy.RUNTIME) |
src/main/java/org/apache/rocketmq/spring/starter/core/AliyunRocketMQListenerContainer.java
| @@ -25,38 +25,39 @@ import java.util.List; | @@ -25,38 +25,39 @@ import java.util.List; | ||
| 25 | import java.util.Objects; | 25 | import java.util.Objects; |
| 26 | import java.util.Properties; | 26 | import java.util.Properties; |
| 27 | 27 | ||
| 28 | -import org.apache.commons.lang3.StringUtils; | ||
| 29 | -import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| 30 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
| 31 | -import org.apache.rocketmq.client.consumer.MessageSelector; | ||
| 32 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
| 33 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
| 34 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
| 35 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
| 36 | -import org.apache.rocketmq.client.exception.MQClientException; | ||
| 37 | -import org.apache.rocketmq.common.message.MessageExt; | ||
| 38 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 39 | import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | 28 | import org.apache.rocketmq.spring.starter.enums.ConsumeMode; |
| 40 | import org.apache.rocketmq.spring.starter.enums.SelectorType; | 29 | import org.apache.rocketmq.spring.starter.enums.SelectorType; |
| 41 | import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | 30 | import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; |
| 42 | import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | 31 | import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; |
| 32 | +import org.apache.rocketmq.spring.starter.utils.ExceptionUtil; | ||
| 43 | import org.apache.rocketmq.spring.starter.utils.IPUtil; | 33 | import org.apache.rocketmq.spring.starter.utils.IPUtil; |
| 44 | import org.springframework.beans.factory.InitializingBean; | 34 | import org.springframework.beans.factory.InitializingBean; |
| 45 | import org.springframework.util.Assert; | 35 | import org.springframework.util.Assert; |
| 36 | +import org.springframework.util.StringUtils; | ||
| 46 | 37 | ||
| 47 | import com.aliyun.openservices.ons.api.Action; | 38 | import com.aliyun.openservices.ons.api.Action; |
| 48 | import com.aliyun.openservices.ons.api.ConsumeContext; | 39 | import com.aliyun.openservices.ons.api.ConsumeContext; |
| 49 | import com.aliyun.openservices.ons.api.Consumer; | 40 | import com.aliyun.openservices.ons.api.Consumer; |
| 50 | import com.aliyun.openservices.ons.api.Message; | 41 | import com.aliyun.openservices.ons.api.Message; |
| 51 | import com.aliyun.openservices.ons.api.MessageListener; | 42 | import com.aliyun.openservices.ons.api.MessageListener; |
| 43 | +import com.aliyun.openservices.ons.api.MessageSelector; | ||
| 52 | import com.aliyun.openservices.ons.api.ONSFactory; | 44 | import com.aliyun.openservices.ons.api.ONSFactory; |
| 53 | import com.aliyun.openservices.ons.api.PropertyKeyConst; | 45 | import com.aliyun.openservices.ons.api.PropertyKeyConst; |
| 54 | import com.aliyun.openservices.ons.api.batch.BatchConsumer; | 46 | import com.aliyun.openservices.ons.api.batch.BatchConsumer; |
| 55 | -import com.aliyun.openservices.ons.api.bean.BatchConsumerBean; | 47 | +import com.aliyun.openservices.ons.api.batch.BatchMessageListener; |
| 48 | +import com.aliyun.openservices.ons.api.order.ConsumeOrderContext; | ||
| 56 | import com.aliyun.openservices.ons.api.order.MessageOrderListener; | 49 | import com.aliyun.openservices.ons.api.order.MessageOrderListener; |
| 50 | +import com.aliyun.openservices.ons.api.order.OrderAction; | ||
| 57 | import com.aliyun.openservices.ons.api.order.OrderConsumer; | 51 | import com.aliyun.openservices.ons.api.order.OrderConsumer; |
| 52 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
| 53 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
| 54 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
| 55 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
| 56 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.exception.MQClientException; | ||
| 57 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.message.MessageExt; | ||
| 58 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 58 | import com.fasterxml.jackson.databind.ObjectMapper; | 59 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 59 | - | 60 | +import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; |
| 60 | import lombok.Getter; | 61 | import lombok.Getter; |
| 61 | import lombok.Setter; | 62 | import lombok.Setter; |
| 62 | import lombok.extern.slf4j.Slf4j; | 63 | import lombok.extern.slf4j.Slf4j; |
| @@ -77,23 +78,13 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -77,23 +78,13 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
| 77 | 78 | ||
| 78 | @Setter | 79 | @Setter |
| 79 | @Getter | 80 | @Getter |
| 80 | - private long suspendCurrentQueueTimeMillis = 1000; | ||
| 81 | - | 81 | + private String consumerGroup; |
| 82 | /** | 82 | /** |
| 83 | - * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
| 84 | - * >0,client control retry frequency | 83 | + * 消息队列服务接入点 |
| 85 | */ | 84 | */ |
| 86 | @Setter | 85 | @Setter |
| 87 | @Getter | 86 | @Getter |
| 88 | - private int delayLevelWhenNextConsume = 0; | ||
| 89 | - | ||
| 90 | - @Setter | ||
| 91 | - @Getter | ||
| 92 | - private String consumerGroup; | ||
| 93 | - | ||
| 94 | - @Setter | ||
| 95 | - @Getter | ||
| 96 | - private String nameServer; | 87 | + private String onsAddr; |
| 97 | 88 | ||
| 98 | @Setter | 89 | @Setter |
| 99 | @Getter | 90 | @Getter |
| @@ -141,6 +132,11 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -141,6 +132,11 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
| 141 | private BatchConsumer batchConsumer; | 132 | private BatchConsumer batchConsumer; |
| 142 | 133 | ||
| 143 | private Class messageType; | 134 | private Class messageType; |
| 135 | + /** | ||
| 136 | + * 环境前缀 | ||
| 137 | + */ | ||
| 138 | + @Setter | ||
| 139 | + private String environmentPrefix; | ||
| 144 | 140 | ||
| 145 | @Setter | 141 | @Setter |
| 146 | private RocketMQTemplate rocketMQTemplate; | 142 | private RocketMQTemplate rocketMQTemplate; |
| @@ -180,66 +176,62 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -180,66 +176,62 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
| 180 | 176 | ||
| 181 | @SuppressWarnings("unchecked") | 177 | @SuppressWarnings("unchecked") |
| 182 | public Action consume(final Message message, final ConsumeContext context){ | 178 | public Action consume(final Message message, final ConsumeContext context){ |
| 183 | - for (MessageExt messageExt : msgs) { | ||
| 184 | - Date consumeBeginTime = new Date(); | ||
| 185 | - log.debug("received msg: {}", messageExt); | ||
| 186 | - try { | ||
| 187 | - long now = System.currentTimeMillis(); | ||
| 188 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 189 | - long costTime = System.currentTimeMillis() - now; | ||
| 190 | - log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 191 | - } catch (Exception e) { | ||
| 192 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 193 | - context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
| 194 | - if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
| 195 | - log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
| 196 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 197 | - } | ||
| 198 | - if(e instanceof ConvertMsgException){ | ||
| 199 | - log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
| 200 | - //消息消费失败,发送失败消息 | ||
| 201 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 202 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 203 | - } | ||
| 204 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 205 | - return ConsumeConcurrentlyStatus.RECONSUME_LATER; | 179 | + Date consumeBeginTime = new Date(); |
| 180 | + log.debug("received msg: {}", message); | ||
| 181 | + try { | ||
| 182 | + long now = consumeBeginTime.getTime(); | ||
| 183 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
| 184 | + long costTime = System.currentTimeMillis() - now; | ||
| 185 | + log.debug("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
| 186 | + } catch (Exception e) { | ||
| 187 | + log.warn("consume message failed. message:{}", message, e); | ||
| 188 | + if(message.getTopic().equals(environmentPrefix+"_"+CONSUMEFAILED_TOPIC) && CONSUMEFAILED_TAG.equals(message.getTag())){ | ||
| 189 | + log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
| 190 | + return Action.CommitMessage; | ||
| 191 | + } | ||
| 192 | + if(e instanceof ConvertMsgException){ | ||
| 193 | + log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
| 194 | + //消息消费失败,发送失败消息 | ||
| 195 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
| 196 | + return Action.CommitMessage; | ||
| 206 | } | 197 | } |
| 198 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
| 199 | + return Action.ReconsumeLater; | ||
| 207 | } | 200 | } |
| 208 | - | ||
| 209 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | 201 | + |
| 202 | + return Action.CommitMessage; | ||
| 210 | } | 203 | } |
| 211 | /** | 204 | /** |
| 212 | * 发送消息消费失败消息 | 205 | * 发送消息消费失败消息 |
| 213 | - * @param messageExt | 206 | + * @param message |
| 214 | * @param e | 207 | * @param e |
| 215 | * 2018年3月22日 zhaowg | 208 | * 2018年3月22日 zhaowg |
| 216 | */ | 209 | */ |
| 217 | - private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | 210 | + private void sendConsumeMsgFailed(Message message, Exception e,Date consumeBeginTime) { |
| 218 | log.info("消费消息失败,开始发送消费失败MQ"); | 211 | log.info("消费消息失败,开始发送消费失败MQ"); |
| 219 | - String topic = "DATA_COLLECTION_TOPIC"; | ||
| 220 | - String tag = "ConsumeMsgFailed"; | 212 | + String topic = environmentPrefix+"_"+CONSUMEFAILED_TOPIC; |
| 213 | + String tag = CONSUMEFAILED_TAG; | ||
| 221 | try{ | 214 | try{ |
| 222 | Date consumeEndTime = new Date(); | 215 | Date consumeEndTime = new Date(); |
| 223 | - String destination = topic+":"+tag; | ||
| 224 | ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | 216 | ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); |
| 225 | consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | 217 | consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); |
| 226 | consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | 218 | consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); |
| 227 | consumeFailedMsgVO.setConsumeGroup(consumerGroup); | 219 | consumeFailedMsgVO.setConsumeGroup(consumerGroup); |
| 228 | consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | 220 | consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); |
| 229 | if(e!=null){ | 221 | if(e!=null){ |
| 230 | - String errMsg = ExceptionUtils.getStackTrace(e); | ||
| 231 | - if(StringUtils.isNotBlank(errMsg)){ | 222 | + String errMsg = ExceptionUtil.getTrace(e); |
| 223 | + if(!StringUtils.isEmpty(errMsg)){ | ||
| 232 | //最多保存1024个字符 | 224 | //最多保存1024个字符 |
| 233 | consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | 225 | consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); |
| 234 | } | 226 | } |
| 235 | } | 227 | } |
| 236 | - consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
| 237 | - consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
| 238 | - consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
| 239 | - consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
| 240 | - consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
| 241 | - consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
| 242 | - rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | 228 | + consumeFailedMsgVO.setMsg(new String(message.getBody())); |
| 229 | + consumeFailedMsgVO.setMsgId(message.getMsgID()); | ||
| 230 | + consumeFailedMsgVO.setMsgKeys(message.getKey()); | ||
| 231 | + consumeFailedMsgVO.setReconsumeTimes(message.getReconsumeTimes()); | ||
| 232 | + consumeFailedMsgVO.setTag(message.getTag()); | ||
| 233 | + consumeFailedMsgVO.setTopic(message.getTopic()); | ||
| 234 | + rocketMQTemplate.sendOneWay(topic, tag, consumeFailedMsgVO); | ||
| 243 | log.info("发送消息消费失败MQ成功"); | 235 | log.info("发送消息消费失败MQ成功"); |
| 244 | }catch(Exception e1){ | 236 | }catch(Exception e1){ |
| 245 | log.info("发送消息消费失败MQ异常",e); | 237 | log.info("发送消息消费失败MQ异常",e); |
| @@ -250,50 +242,103 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -250,50 +242,103 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
| 250 | 242 | ||
| 251 | public class DefaultMessageListenerOrderly implements MessageOrderListener { | 243 | public class DefaultMessageListenerOrderly implements MessageOrderListener { |
| 252 | 244 | ||
| 253 | - @SuppressWarnings("unchecked") | ||
| 254 | - public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
| 255 | - for (MessageExt messageExt : msgs) { | ||
| 256 | - log.debug("received msg: {}", messageExt); | ||
| 257 | - try { | ||
| 258 | - long now = System.currentTimeMillis(); | ||
| 259 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 260 | - long costTime = System.currentTimeMillis() - now; | ||
| 261 | - log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 262 | - } catch (Exception e) { | ||
| 263 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 264 | - context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
| 265 | - return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
| 266 | - } | 245 | + @Override |
| 246 | + public OrderAction consume(Message message, ConsumeOrderContext context) { | ||
| 247 | + log.debug("received msg: {}", message); | ||
| 248 | + try { | ||
| 249 | + long now = System.currentTimeMillis(); | ||
| 250 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
| 251 | + long costTime = System.currentTimeMillis() - now; | ||
| 252 | + log.info("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
| 253 | + } catch (Exception e) { | ||
| 254 | + log.warn("consume message failed. message:{}", message, e); | ||
| 255 | + return OrderAction.Suspend; | ||
| 267 | } | 256 | } |
| 268 | - | ||
| 269 | - return ConsumeOrderlyStatus.SUCCESS; | ||
| 270 | - } | 257 | + return OrderAction.Success; |
| 258 | + } | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + public class DefaultMessageListenerBatchs implements BatchMessageListener{ | ||
| 262 | + | ||
| 263 | + @Override | ||
| 264 | + public Action consume(List<Message> messages, ConsumeContext context) { | ||
| 265 | + for (Message message : messages) { | ||
| 266 | + Date consumeBeginTime = new Date(); | ||
| 267 | + log.debug("received msg: {}", message); | ||
| 268 | + try { | ||
| 269 | + long now = consumeBeginTime.getTime(); | ||
| 270 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
| 271 | + long costTime = System.currentTimeMillis() - now; | ||
| 272 | + log.debug("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
| 273 | + } catch (Exception e) { | ||
| 274 | + log.warn("consume message failed. message:{}", message, e); | ||
| 275 | + if(message.getTopic().equals(environmentPrefix+"_"+CONSUMEFAILED_TOPIC) && CONSUMEFAILED_TAG.equals(message.getTag())){ | ||
| 276 | + log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
| 277 | + continue; | ||
| 278 | + } | ||
| 279 | + if(e instanceof ConvertMsgException){ | ||
| 280 | + log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
| 281 | + //消息消费失败,发送失败消息 | ||
| 282 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
| 283 | + continue; | ||
| 284 | + } | ||
| 285 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
| 286 | + return Action.ReconsumeLater; | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + return Action.CommitMessage; | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + /** | ||
| 293 | + * 发送消息消费失败消息 | ||
| 294 | + * @param message | ||
| 295 | + * @param e | ||
| 296 | + * 2018年3月22日 zhaowg | ||
| 297 | + */ | ||
| 298 | + private void sendConsumeMsgFailed(Message message, Exception e,Date consumeBeginTime) { | ||
| 299 | + log.info("消费消息失败,开始发送消费失败MQ"); | ||
| 300 | + String topic = environmentPrefix+"_"+CONSUMEFAILED_TOPIC; | ||
| 301 | + String tag = CONSUMEFAILED_TAG; | ||
| 302 | + try{ | ||
| 303 | + Date consumeEndTime = new Date(); | ||
| 304 | + ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
| 305 | + consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
| 306 | + consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
| 307 | + consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
| 308 | + consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
| 309 | + if(e!=null){ | ||
| 310 | + String errMsg = ExceptionUtil.getTrace(e); | ||
| 311 | + if(!StringUtils.isEmpty(errMsg)){ | ||
| 312 | + //最多保存1024个字符 | ||
| 313 | + consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
| 314 | + } | ||
| 315 | + } | ||
| 316 | + consumeFailedMsgVO.setMsg(new String(message.getBody())); | ||
| 317 | + consumeFailedMsgVO.setMsgId(message.getMsgID()); | ||
| 318 | + consumeFailedMsgVO.setMsgKeys(message.getKey()); | ||
| 319 | + consumeFailedMsgVO.setReconsumeTimes(message.getReconsumeTimes()); | ||
| 320 | + consumeFailedMsgVO.setTag(message.getTag()); | ||
| 321 | + consumeFailedMsgVO.setTopic(message.getTopic()); | ||
| 322 | + rocketMQTemplate.sendOneWay(topic, tag, consumeFailedMsgVO); | ||
| 323 | + log.info("发送消息消费失败MQ成功"); | ||
| 324 | + }catch(Exception e1){ | ||
| 325 | + log.info("发送消息消费失败MQ异常",e); | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + } | ||
| 271 | } | 329 | } |
| 272 | - | ||
| 273 | @Override | 330 | @Override |
| 274 | public void afterPropertiesSet() throws Exception { | 331 | public void afterPropertiesSet() throws Exception { |
| 275 | start(); | 332 | start(); |
| 276 | } | 333 | } |
| 277 | 334 | ||
| 278 | - @Override | ||
| 279 | - public String toString() { | ||
| 280 | - return "DefaultRocketMQListenerContainer{" + | ||
| 281 | - "consumerGroup='" + consumerGroup + '\'' + | ||
| 282 | - ", nameServer='" + nameServer + '\'' + | ||
| 283 | - ", topic='" + topic + '\'' + | ||
| 284 | - ", consumeMode=" + consumeMode + | ||
| 285 | - ", selectorType=" + selectorType + | ||
| 286 | - ", selectorExpress='" + selectorExpress + '\'' + | ||
| 287 | - ", messageModel=" + messageModel + | ||
| 288 | - '}'; | ||
| 289 | - } | ||
| 290 | 335 | ||
| 291 | @SuppressWarnings("unchecked") | 336 | @SuppressWarnings("unchecked") |
| 292 | - private Object doConvertMessage(MessageExt messageExt) { | ||
| 293 | - if (Objects.equals(messageType, MessageExt.class)) { | ||
| 294 | - return messageExt; | 337 | + private Object doConvertMessage(Message message) { |
| 338 | + if (Objects.equals(messageType, Message.class)) { | ||
| 339 | + return message; | ||
| 295 | } else { | 340 | } else { |
| 296 | - String str = new String(messageExt.getBody(), Charset.forName(charset)); | 341 | + String str = new String(message.getBody(), Charset.forName(charset)); |
| 297 | if (Objects.equals(messageType, String.class)) { | 342 | if (Objects.equals(messageType, String.class)) { |
| 298 | return str; | 343 | return str; |
| 299 | } else { | 344 | } else { |
| @@ -335,72 +380,45 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -335,72 +380,45 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
| 335 | 380 | ||
| 336 | Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | 381 | Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); |
| 337 | Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | 382 | Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); |
| 338 | - Assert.notNull(nameServer, "Property 'nameServer' is required"); | 383 | + Assert.notNull(onsAddr, "Property 'nameServer' is required"); |
| 339 | Assert.notNull(topic, "Property 'topic' is required"); | 384 | Assert.notNull(topic, "Property 'topic' is required"); |
| 340 | 385 | ||
| 341 | Properties consumerProperties = new Properties(); | 386 | Properties consumerProperties = new Properties(); |
| 342 | - consumerProperties.setProperty(PropertyKeyConst.ConsumerId, "CID_"+consumerGroup); | 387 | + consumerProperties.setProperty(PropertyKeyConst.ConsumerId, consumerGroup); |
| 343 | consumerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); | 388 | consumerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); |
| 344 | consumerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); | 389 | consumerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); |
| 345 | - consumerProperties.setProperty(PropertyKeyConst.ONSAddr, nameServer); | 390 | + consumerProperties.setProperty(PropertyKeyConst.ONSAddr, onsAddr); |
| 346 | consumerProperties.setProperty(PropertyKeyConst.ConsumeThreadNums, consumeThreadMax+""); | 391 | consumerProperties.setProperty(PropertyKeyConst.ConsumeThreadNums, consumeThreadMax+""); |
| 347 | consumerProperties.setProperty(PropertyKeyConst.MessageModel, messageModel.getModeCN()); | 392 | consumerProperties.setProperty(PropertyKeyConst.MessageModel, messageModel.getModeCN()); |
| 348 | - //判断是否为批量消费者 | ||
| 349 | - boolean isBatchConsume = false; | ||
| 350 | //允许用户自己设置该consumer的一些配置 | 393 | //允许用户自己设置该consumer的一些配置 |
| 351 | - DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer(); | ||
| 352 | - if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { | ||
| 353 | - ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(defaultMQPushConsumer); | ||
| 354 | - isBatchConsume = defaultMQPushConsumer.getConsumeMessageBatchMaxSize()>1; | 394 | + if (rocketMQListener instanceof AliyunRocketMQPushConsumerLifecycleListener) { |
| 395 | + ((AliyunRocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumerProperties); | ||
| 355 | } | 396 | } |
| 356 | - | ||
| 357 | switch (consumeMode) { | 397 | switch (consumeMode) { |
| 358 | case ORDERLY://顺序消息 | 398 | case ORDERLY://顺序消息 |
| 359 | orderConsumer = ONSFactory.createOrderedConsumer(consumerProperties); | 399 | orderConsumer = ONSFactory.createOrderedConsumer(consumerProperties); |
| 360 | if(selectorType == SelectorType.TAG){ | 400 | if(selectorType == SelectorType.TAG){ |
| 361 | orderConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerOrderly()); | 401 | orderConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerOrderly()); |
| 362 | }else if(selectorType == SelectorType.SQL92){ | 402 | }else if(selectorType == SelectorType.SQL92){ |
| 363 | - orderConsumer.subscribe(topic, com.aliyun.openservices.ons.api.MessageSelector.bySql(selectorExpress), new DefaultMessageListenerOrderly()); | 403 | + orderConsumer.subscribe(topic, MessageSelector.bySql(selectorExpress), new DefaultMessageListenerOrderly()); |
| 364 | } | 404 | } |
| 365 | break; | 405 | break; |
| 366 | case CONCURRENTLY://普通消息 | 406 | case CONCURRENTLY://普通消息 |
| 367 | - if(isBatchConsume){ | ||
| 368 | - //批量消息 | ||
| 369 | - | ||
| 370 | - } | ||
| 371 | - | ||
| 372 | consumer = ONSFactory.createConsumer(consumerProperties); | 407 | consumer = ONSFactory.createConsumer(consumerProperties); |
| 373 | if(selectorType == SelectorType.TAG){ | 408 | if(selectorType == SelectorType.TAG){ |
| 374 | consumer.subscribe(topic, selectorExpress, new DefaultMessageListenerConcurrently()); | 409 | consumer.subscribe(topic, selectorExpress, new DefaultMessageListenerConcurrently()); |
| 375 | }else if(selectorType == SelectorType.SQL92){ | 410 | }else if(selectorType == SelectorType.SQL92){ |
| 376 | - consumer.subscribe(topic, com.aliyun.openservices.ons.api.MessageSelector.bySql(selectorExpress), new DefaultMessageListenerConcurrently()); | 411 | + consumer.subscribe(topic, MessageSelector.bySql(selectorExpress), new DefaultMessageListenerConcurrently()); |
| 377 | } | 412 | } |
| 378 | break; | 413 | break; |
| 414 | + case BATCH://批量消息 | ||
| 415 | + batchConsumer = ONSFactory.createBatchConsumer(consumerProperties); | ||
| 416 | + batchConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerBatchs()); | ||
| 417 | + break; | ||
| 379 | default: | 418 | default: |
| 380 | throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | 419 | throw new IllegalArgumentException("Property 'consumeMode' was wrong."); |
| 381 | } | 420 | } |
| 382 | 421 | ||
| 383 | - | ||
| 384 | - | ||
| 385 | - | ||
| 386 | - | ||
| 387 | - consumer.subscribe(MqConfig.TOPIC, MqConfig.TAG, new MessageListenerImpl()); | ||
| 388 | - consumer.start(); | ||
| 389 | - | ||
| 390 | - switch (selectorType) { | ||
| 391 | - case TAG: | ||
| 392 | - consumer.subscribe(topic, selectorExpress); | ||
| 393 | - break; | ||
| 394 | - case SQL92: | ||
| 395 | - consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
| 396 | - break; | ||
| 397 | - default: | ||
| 398 | - throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
| 399 | - } | ||
| 400 | - | ||
| 401 | - | ||
| 402 | - | ||
| 403 | - | ||
| 404 | } | 422 | } |
| 405 | 423 | ||
| 406 | } | 424 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/RocketMQPushConsumerLifecycleListener.java renamed to src/main/java/org/apache/rocketmq/spring/starter/core/AliyunRocketMQPushConsumerLifecycleListener.java
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | 17 | ||
| 18 | package org.apache.rocketmq.spring.starter.core; | 18 | package org.apache.rocketmq.spring.starter.core; |
| 19 | 19 | ||
| 20 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | 20 | +import java.util.Properties; |
| 21 | 21 | ||
| 22 | -public interface RocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener<DefaultMQPushConsumer> { | 22 | +public interface AliyunRocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener<Properties> { |
| 23 | } | 23 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/DefaultRocketMQListenerContainer.java
| 1 | -/* | ||
| 2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| 3 | - * contributor license agreements. See the NOTICE file distributed with | ||
| 4 | - * this work for additional information regarding copyright ownership. | ||
| 5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| 6 | - * (the "License"); you may not use this file except in compliance with | ||
| 7 | - * the License. You may obtain a copy of the License at | ||
| 8 | - * | ||
| 9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | - * | ||
| 11 | - * Unless required by applicable law or agreed to in writing, software | ||
| 12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | - * See the License for the specific language governing permissions and | ||
| 15 | - * limitations under the License. | ||
| 16 | - */ | ||
| 17 | - | ||
| 18 | -package org.apache.rocketmq.spring.starter.core; | ||
| 19 | - | ||
| 20 | -import java.lang.reflect.ParameterizedType; | ||
| 21 | -import java.lang.reflect.Type; | ||
| 22 | -import java.nio.charset.Charset; | ||
| 23 | -import java.util.Date; | ||
| 24 | -import java.util.List; | ||
| 25 | -import java.util.Objects; | ||
| 26 | - | ||
| 27 | -import org.apache.commons.lang3.StringUtils; | ||
| 28 | -import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| 29 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
| 30 | -import org.apache.rocketmq.client.consumer.MessageSelector; | ||
| 31 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
| 32 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
| 33 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
| 34 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
| 35 | -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; | ||
| 36 | -import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; | ||
| 37 | -import org.apache.rocketmq.client.exception.MQClientException; | ||
| 38 | -import org.apache.rocketmq.common.message.MessageExt; | ||
| 39 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 40 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 41 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 42 | -import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | ||
| 43 | -import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | ||
| 44 | -import org.apache.rocketmq.spring.starter.utils.IPUtil; | ||
| 45 | -import org.springframework.beans.factory.InitializingBean; | ||
| 46 | -import org.springframework.util.Assert; | ||
| 47 | - | ||
| 48 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 49 | - | ||
| 50 | -import lombok.Getter; | ||
| 51 | -import lombok.Setter; | ||
| 52 | -import lombok.extern.slf4j.Slf4j; | ||
| 53 | - | ||
| 54 | -@SuppressWarnings("WeakerAccess") | ||
| 55 | -@Slf4j | ||
| 56 | -public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer { | ||
| 57 | - | ||
| 58 | - @Setter | ||
| 59 | - @Getter | ||
| 60 | - private long suspendCurrentQueueTimeMillis = 1000; | ||
| 61 | - | ||
| 62 | - /** | ||
| 63 | - * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
| 64 | - * >0,client control retry frequency | ||
| 65 | - */ | ||
| 66 | - @Setter | ||
| 67 | - @Getter | ||
| 68 | - private int delayLevelWhenNextConsume = 0; | ||
| 69 | - | ||
| 70 | - @Setter | ||
| 71 | - @Getter | ||
| 72 | - private String consumerGroup; | ||
| 73 | - | ||
| 74 | - @Setter | ||
| 75 | - @Getter | ||
| 76 | - private String nameServer; | ||
| 77 | - | ||
| 78 | - @Setter | ||
| 79 | - @Getter | ||
| 80 | - private String topic; | ||
| 81 | - | ||
| 82 | - @Setter | ||
| 83 | - @Getter | ||
| 84 | - private ConsumeMode consumeMode = ConsumeMode.CONCURRENTLY; | ||
| 85 | - | ||
| 86 | - @Setter | ||
| 87 | - @Getter | ||
| 88 | - private SelectorType selectorType = SelectorType.TAG; | ||
| 89 | - | ||
| 90 | - @Setter | ||
| 91 | - @Getter | ||
| 92 | - private String selectorExpress = "*"; | ||
| 93 | - | ||
| 94 | - @Setter | ||
| 95 | - @Getter | ||
| 96 | - private MessageModel messageModel = MessageModel.CLUSTERING; | ||
| 97 | - | ||
| 98 | - @Setter | ||
| 99 | - @Getter | ||
| 100 | - private int consumeThreadMax = 64; | ||
| 101 | - | ||
| 102 | - @Getter | ||
| 103 | - @Setter | ||
| 104 | - private String charset = "UTF-8"; | ||
| 105 | - | ||
| 106 | - @Setter | ||
| 107 | - @Getter | ||
| 108 | - private ObjectMapper objectMapper = new ObjectMapper(); | ||
| 109 | - | ||
| 110 | - @Setter | ||
| 111 | - @Getter | ||
| 112 | - private boolean started; | ||
| 113 | - | ||
| 114 | - @Setter | ||
| 115 | - private RocketMQListener rocketMQListener; | ||
| 116 | - | ||
| 117 | - private DefaultMQPushConsumer consumer; | ||
| 118 | - | ||
| 119 | - private Class messageType; | ||
| 120 | - | ||
| 121 | - @Setter | ||
| 122 | - private RocketMQTemplate rocketMQTemplate; | ||
| 123 | - | ||
| 124 | - public void setupMessageListener(RocketMQListener rocketMQListener) { | ||
| 125 | - this.rocketMQListener = rocketMQListener; | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | - @Override | ||
| 129 | - public void destroy() { | ||
| 130 | - this.setStarted(false); | ||
| 131 | - if (Objects.nonNull(consumer)) { | ||
| 132 | - consumer.shutdown(); | ||
| 133 | - } | ||
| 134 | - log.info("container destroyed, {}", this.toString()); | ||
| 135 | - } | ||
| 136 | - | ||
| 137 | - public synchronized void start() throws MQClientException { | ||
| 138 | - | ||
| 139 | - if (this.isStarted()) { | ||
| 140 | - throw new IllegalStateException("container already started. " + this.toString()); | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - initRocketMQPushConsumer(); | ||
| 144 | - | ||
| 145 | - // parse message type | ||
| 146 | - this.messageType = getMessageType(); | ||
| 147 | - log.debug("msgType: {}", messageType.getName()); | ||
| 148 | - | ||
| 149 | - consumer.start(); | ||
| 150 | - this.setStarted(true); | ||
| 151 | - | ||
| 152 | - log.info("started container: {}", this.toString()); | ||
| 153 | - } | ||
| 154 | - | ||
| 155 | - public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { | ||
| 156 | - | ||
| 157 | - @SuppressWarnings("unchecked") | ||
| 158 | - public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { | ||
| 159 | - for (MessageExt messageExt : msgs) { | ||
| 160 | - Date consumeBeginTime = new Date(); | ||
| 161 | - log.debug("received msg: {}", messageExt); | ||
| 162 | - try { | ||
| 163 | - long now = System.currentTimeMillis(); | ||
| 164 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 165 | - long costTime = System.currentTimeMillis() - now; | ||
| 166 | - log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 167 | - } catch (Exception e) { | ||
| 168 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 169 | - context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
| 170 | - if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
| 171 | - log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
| 172 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 173 | - } | ||
| 174 | - if(e instanceof ConvertMsgException){ | ||
| 175 | - log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
| 176 | - //消息消费失败,发送失败消息 | ||
| 177 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 178 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 179 | - } | ||
| 180 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 181 | - return ConsumeConcurrentlyStatus.RECONSUME_LATER; | ||
| 182 | - } | ||
| 183 | - } | ||
| 184 | - | ||
| 185 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 186 | - } | ||
| 187 | - /** | ||
| 188 | - * 发送消息消费失败消息 | ||
| 189 | - * @param messageExt | ||
| 190 | - * @param e | ||
| 191 | - * 2018年3月22日 zhaowg | ||
| 192 | - */ | ||
| 193 | - private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | ||
| 194 | - log.info("消费消息失败,开始发送消费失败MQ"); | ||
| 195 | - String topic = "DATA_COLLECTION_TOPIC"; | ||
| 196 | - String tag = "ConsumeMsgFailed"; | ||
| 197 | - try{ | ||
| 198 | - Date consumeEndTime = new Date(); | ||
| 199 | - String destination = topic+":"+tag; | ||
| 200 | - ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
| 201 | - consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
| 202 | - consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
| 203 | - consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
| 204 | - consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
| 205 | - if(e!=null){ | ||
| 206 | - String errMsg = ExceptionUtils.getStackTrace(e); | ||
| 207 | - if(StringUtils.isNotBlank(errMsg)){ | ||
| 208 | - //最多保存1024个字符 | ||
| 209 | - consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
| 210 | - } | ||
| 211 | - } | ||
| 212 | - consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
| 213 | - consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
| 214 | - consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
| 215 | - consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
| 216 | - consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
| 217 | - consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
| 218 | - rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | ||
| 219 | - log.info("发送消息消费失败MQ成功"); | ||
| 220 | - }catch(Exception e1){ | ||
| 221 | - log.info("发送消息消费失败MQ异常",e); | ||
| 222 | - } | ||
| 223 | - | ||
| 224 | - } | ||
| 225 | - } | ||
| 226 | - | ||
| 227 | - public class DefaultMessageListenerOrderly implements MessageListenerOrderly { | ||
| 228 | - | ||
| 229 | - @SuppressWarnings("unchecked") | ||
| 230 | - public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
| 231 | - for (MessageExt messageExt : msgs) { | ||
| 232 | - log.debug("received msg: {}", messageExt); | ||
| 233 | - try { | ||
| 234 | - long now = System.currentTimeMillis(); | ||
| 235 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 236 | - long costTime = System.currentTimeMillis() - now; | ||
| 237 | - log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 238 | - } catch (Exception e) { | ||
| 239 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 240 | - context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
| 241 | - return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
| 242 | - } | ||
| 243 | - } | ||
| 244 | - | ||
| 245 | - return ConsumeOrderlyStatus.SUCCESS; | ||
| 246 | - } | ||
| 247 | - } | ||
| 248 | - | ||
| 249 | - @Override | ||
| 250 | - public void afterPropertiesSet() throws Exception { | ||
| 251 | - start(); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - @Override | ||
| 255 | - public String toString() { | ||
| 256 | - return "DefaultRocketMQListenerContainer{" + | ||
| 257 | - "consumerGroup='" + consumerGroup + '\'' + | ||
| 258 | - ", nameServer='" + nameServer + '\'' + | ||
| 259 | - ", topic='" + topic + '\'' + | ||
| 260 | - ", consumeMode=" + consumeMode + | ||
| 261 | - ", selectorType=" + selectorType + | ||
| 262 | - ", selectorExpress='" + selectorExpress + '\'' + | ||
| 263 | - ", messageModel=" + messageModel + | ||
| 264 | - '}'; | ||
| 265 | - } | ||
| 266 | - | ||
| 267 | - @SuppressWarnings("unchecked") | ||
| 268 | - private Object doConvertMessage(MessageExt messageExt) { | ||
| 269 | - if (Objects.equals(messageType, MessageExt.class)) { | ||
| 270 | - return messageExt; | ||
| 271 | - } else { | ||
| 272 | - String str = new String(messageExt.getBody(), Charset.forName(charset)); | ||
| 273 | - if (Objects.equals(messageType, String.class)) { | ||
| 274 | - return str; | ||
| 275 | - } else { | ||
| 276 | - // if msgType not string, use objectMapper change it. | ||
| 277 | - try { | ||
| 278 | - return objectMapper.readValue(str, messageType); | ||
| 279 | - } catch (Exception e) { | ||
| 280 | - log.info("convert failed. str:{}, msgType:{}", str, messageType); | ||
| 281 | - throw new ConvertMsgException("cannot convert message to " + messageType, e); | ||
| 282 | - } | ||
| 283 | - } | ||
| 284 | - } | ||
| 285 | - } | ||
| 286 | - | ||
| 287 | - private Class getMessageType() { | ||
| 288 | - Type[] interfaces = rocketMQListener.getClass().getGenericInterfaces(); | ||
| 289 | - if (Objects.nonNull(interfaces)) { | ||
| 290 | - for (Type type : interfaces) { | ||
| 291 | - if (type instanceof ParameterizedType) { | ||
| 292 | - ParameterizedType parameterizedType = (ParameterizedType) type; | ||
| 293 | - if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { | ||
| 294 | - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); | ||
| 295 | - if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { | ||
| 296 | - return (Class) actualTypeArguments[0]; | ||
| 297 | - } else { | ||
| 298 | - return Object.class; | ||
| 299 | - } | ||
| 300 | - } | ||
| 301 | - } | ||
| 302 | - } | ||
| 303 | - | ||
| 304 | - return Object.class; | ||
| 305 | - } else { | ||
| 306 | - return Object.class; | ||
| 307 | - } | ||
| 308 | - } | ||
| 309 | - | ||
| 310 | - private void initRocketMQPushConsumer() throws MQClientException { | ||
| 311 | - | ||
| 312 | - Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | ||
| 313 | - Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | ||
| 314 | - Assert.notNull(nameServer, "Property 'nameServer' is required"); | ||
| 315 | - Assert.notNull(topic, "Property 'topic' is required"); | ||
| 316 | - | ||
| 317 | - consumer = new DefaultMQPushConsumer(consumerGroup); | ||
| 318 | - consumer.setNamesrvAddr(nameServer); | ||
| 319 | - consumer.setConsumeThreadMax(consumeThreadMax); | ||
| 320 | - if (consumeThreadMax < consumer.getConsumeThreadMin()) { | ||
| 321 | - consumer.setConsumeThreadMin(consumeThreadMax); | ||
| 322 | - } | ||
| 323 | - | ||
| 324 | - consumer.setMessageModel(messageModel); | ||
| 325 | - | ||
| 326 | - switch (selectorType) { | ||
| 327 | - case TAG: | ||
| 328 | - consumer.subscribe(topic, selectorExpress); | ||
| 329 | - break; | ||
| 330 | - case SQL92: | ||
| 331 | - consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
| 332 | - break; | ||
| 333 | - default: | ||
| 334 | - throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
| 335 | - } | ||
| 336 | - | ||
| 337 | - switch (consumeMode) { | ||
| 338 | - case ORDERLY: | ||
| 339 | - consumer.setMessageListener(new DefaultMessageListenerOrderly()); | ||
| 340 | - break; | ||
| 341 | - case CONCURRENTLY: | ||
| 342 | - consumer.setMessageListener(new DefaultMessageListenerConcurrently()); | ||
| 343 | - break; | ||
| 344 | - default: | ||
| 345 | - throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | ||
| 346 | - } | ||
| 347 | - | ||
| 348 | - // provide an entryway to custom setting RocketMQ consumer | ||
| 349 | - if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { | ||
| 350 | - ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer); | ||
| 351 | - } | ||
| 352 | - | ||
| 353 | - } | ||
| 354 | - | ||
| 355 | -} | 1 | +///* |
| 2 | +// * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| 3 | +// * contributor license agreements. See the NOTICE file distributed with | ||
| 4 | +// * this work for additional information regarding copyright ownership. | ||
| 5 | +// * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| 6 | +// * (the "License"); you may not use this file except in compliance with | ||
| 7 | +// * the License. You may obtain a copy of the License at | ||
| 8 | +// * | ||
| 9 | +// * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | +// * | ||
| 11 | +// * Unless required by applicable law or agreed to in writing, software | ||
| 12 | +// * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | +// * See the License for the specific language governing permissions and | ||
| 15 | +// * limitations under the License. | ||
| 16 | +// */ | ||
| 17 | +// | ||
| 18 | +//package org.apache.rocketmq.spring.starter.core; | ||
| 19 | +// | ||
| 20 | +//import java.lang.reflect.ParameterizedType; | ||
| 21 | +//import java.lang.reflect.Type; | ||
| 22 | +//import java.nio.charset.Charset; | ||
| 23 | +//import java.util.Date; | ||
| 24 | +//import java.util.List; | ||
| 25 | +//import java.util.Objects; | ||
| 26 | +// | ||
| 27 | +//import org.apache.commons.lang3.StringUtils; | ||
| 28 | +//import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| 29 | +//import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
| 30 | +//import org.apache.rocketmq.client.consumer.MessageSelector; | ||
| 31 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
| 32 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
| 33 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
| 34 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
| 35 | +//import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; | ||
| 36 | +//import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; | ||
| 37 | +//import org.apache.rocketmq.client.exception.MQClientException; | ||
| 38 | +//import org.apache.rocketmq.common.message.MessageExt; | ||
| 39 | +//import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 40 | +//import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 41 | +//import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 42 | +//import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | ||
| 43 | +//import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | ||
| 44 | +//import org.apache.rocketmq.spring.starter.utils.IPUtil; | ||
| 45 | +//import org.springframework.beans.factory.InitializingBean; | ||
| 46 | +//import org.springframework.util.Assert; | ||
| 47 | +// | ||
| 48 | +//import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 49 | +// | ||
| 50 | +//import lombok.Getter; | ||
| 51 | +//import lombok.Setter; | ||
| 52 | +//import lombok.extern.slf4j.Slf4j; | ||
| 53 | +// | ||
| 54 | +//@SuppressWarnings("WeakerAccess") | ||
| 55 | +//@Slf4j | ||
| 56 | +//public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer { | ||
| 57 | +// | ||
| 58 | +// @Setter | ||
| 59 | +// @Getter | ||
| 60 | +// private long suspendCurrentQueueTimeMillis = 1000; | ||
| 61 | +// | ||
| 62 | +// /** | ||
| 63 | +// * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
| 64 | +// * >0,client control retry frequency | ||
| 65 | +// */ | ||
| 66 | +// @Setter | ||
| 67 | +// @Getter | ||
| 68 | +// private int delayLevelWhenNextConsume = 0; | ||
| 69 | +// | ||
| 70 | +// @Setter | ||
| 71 | +// @Getter | ||
| 72 | +// private String consumerGroup; | ||
| 73 | +// | ||
| 74 | +// @Setter | ||
| 75 | +// @Getter | ||
| 76 | +// private String nameServer; | ||
| 77 | +// | ||
| 78 | +// @Setter | ||
| 79 | +// @Getter | ||
| 80 | +// private String topic; | ||
| 81 | +// | ||
| 82 | +// @Setter | ||
| 83 | +// @Getter | ||
| 84 | +// private ConsumeMode consumeMode = ConsumeMode.CONCURRENTLY; | ||
| 85 | +// | ||
| 86 | +// @Setter | ||
| 87 | +// @Getter | ||
| 88 | +// private SelectorType selectorType = SelectorType.TAG; | ||
| 89 | +// | ||
| 90 | +// @Setter | ||
| 91 | +// @Getter | ||
| 92 | +// private String selectorExpress = "*"; | ||
| 93 | +// | ||
| 94 | +// @Setter | ||
| 95 | +// @Getter | ||
| 96 | +// private MessageModel messageModel = MessageModel.CLUSTERING; | ||
| 97 | +// | ||
| 98 | +// @Setter | ||
| 99 | +// @Getter | ||
| 100 | +// private int consumeThreadMax = 64; | ||
| 101 | +// | ||
| 102 | +// @Getter | ||
| 103 | +// @Setter | ||
| 104 | +// private String charset = "UTF-8"; | ||
| 105 | +// | ||
| 106 | +// @Setter | ||
| 107 | +// @Getter | ||
| 108 | +// private ObjectMapper objectMapper = new ObjectMapper(); | ||
| 109 | +// | ||
| 110 | +// @Setter | ||
| 111 | +// @Getter | ||
| 112 | +// private boolean started; | ||
| 113 | +// | ||
| 114 | +// @Setter | ||
| 115 | +// private RocketMQListener rocketMQListener; | ||
| 116 | +// | ||
| 117 | +// private DefaultMQPushConsumer consumer; | ||
| 118 | +// | ||
| 119 | +// private Class messageType; | ||
| 120 | +// | ||
| 121 | +// @Setter | ||
| 122 | +// private RocketMQTemplate rocketMQTemplate; | ||
| 123 | +// | ||
| 124 | +// public void setupMessageListener(RocketMQListener rocketMQListener) { | ||
| 125 | +// this.rocketMQListener = rocketMQListener; | ||
| 126 | +// } | ||
| 127 | +// | ||
| 128 | +// @Override | ||
| 129 | +// public void destroy() { | ||
| 130 | +// this.setStarted(false); | ||
| 131 | +// if (Objects.nonNull(consumer)) { | ||
| 132 | +// consumer.shutdown(); | ||
| 133 | +// } | ||
| 134 | +// log.info("container destroyed, {}", this.toString()); | ||
| 135 | +// } | ||
| 136 | +// | ||
| 137 | +// public synchronized void start() throws MQClientException { | ||
| 138 | +// | ||
| 139 | +// if (this.isStarted()) { | ||
| 140 | +// throw new IllegalStateException("container already started. " + this.toString()); | ||
| 141 | +// } | ||
| 142 | +// | ||
| 143 | +// initRocketMQPushConsumer(); | ||
| 144 | +// | ||
| 145 | +// // parse message type | ||
| 146 | +// this.messageType = getMessageType(); | ||
| 147 | +// log.debug("msgType: {}", messageType.getName()); | ||
| 148 | +// | ||
| 149 | +// consumer.start(); | ||
| 150 | +// this.setStarted(true); | ||
| 151 | +// | ||
| 152 | +// log.info("started container: {}", this.toString()); | ||
| 153 | +// } | ||
| 154 | +// | ||
| 155 | +// public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { | ||
| 156 | +// | ||
| 157 | +// @SuppressWarnings("unchecked") | ||
| 158 | +// public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { | ||
| 159 | +// for (MessageExt messageExt : msgs) { | ||
| 160 | +// Date consumeBeginTime = new Date(); | ||
| 161 | +// log.debug("received msg: {}", messageExt); | ||
| 162 | +// try { | ||
| 163 | +// long now = System.currentTimeMillis(); | ||
| 164 | +// rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 165 | +// long costTime = System.currentTimeMillis() - now; | ||
| 166 | +// log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 167 | +// } catch (Exception e) { | ||
| 168 | +// log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 169 | +// context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
| 170 | +// if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
| 171 | +// log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
| 172 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 173 | +// } | ||
| 174 | +// if(e instanceof ConvertMsgException){ | ||
| 175 | +// log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
| 176 | +// //消息消费失败,发送失败消息 | ||
| 177 | +// this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 178 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 179 | +// } | ||
| 180 | +// this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
| 181 | +// return ConsumeConcurrentlyStatus.RECONSUME_LATER; | ||
| 182 | +// } | ||
| 183 | +// } | ||
| 184 | +// | ||
| 185 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
| 186 | +// } | ||
| 187 | +// /** | ||
| 188 | +// * 发送消息消费失败消息 | ||
| 189 | +// * @param messageExt | ||
| 190 | +// * @param e | ||
| 191 | +// * 2018年3月22日 zhaowg | ||
| 192 | +// */ | ||
| 193 | +// private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | ||
| 194 | +// log.info("消费消息失败,开始发送消费失败MQ"); | ||
| 195 | +// String topic = "DATA_COLLECTION_TOPIC"; | ||
| 196 | +// String tag = "ConsumeMsgFailed"; | ||
| 197 | +// try{ | ||
| 198 | +// Date consumeEndTime = new Date(); | ||
| 199 | +// String destination = topic+":"+tag; | ||
| 200 | +// ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
| 201 | +// consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
| 202 | +// consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
| 203 | +// consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
| 204 | +// consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
| 205 | +// if(e!=null){ | ||
| 206 | +// String errMsg = ExceptionUtils.getStackTrace(e); | ||
| 207 | +// if(StringUtils.isNotBlank(errMsg)){ | ||
| 208 | +// //最多保存1024个字符 | ||
| 209 | +// consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
| 210 | +// } | ||
| 211 | +// } | ||
| 212 | +// consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
| 213 | +// consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
| 214 | +// consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
| 215 | +// consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
| 216 | +// consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
| 217 | +// consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
| 218 | +// rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | ||
| 219 | +// log.info("发送消息消费失败MQ成功"); | ||
| 220 | +// }catch(Exception e1){ | ||
| 221 | +// log.info("发送消息消费失败MQ异常",e); | ||
| 222 | +// } | ||
| 223 | +// | ||
| 224 | +// } | ||
| 225 | +// } | ||
| 226 | +// | ||
| 227 | +// public class DefaultMessageListenerOrderly implements MessageListenerOrderly { | ||
| 228 | +// | ||
| 229 | +// @SuppressWarnings("unchecked") | ||
| 230 | +// public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
| 231 | +// for (MessageExt messageExt : msgs) { | ||
| 232 | +// log.debug("received msg: {}", messageExt); | ||
| 233 | +// try { | ||
| 234 | +// long now = System.currentTimeMillis(); | ||
| 235 | +// rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
| 236 | +// long costTime = System.currentTimeMillis() - now; | ||
| 237 | +// log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
| 238 | +// } catch (Exception e) { | ||
| 239 | +// log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
| 240 | +// context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
| 241 | +// return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
| 242 | +// } | ||
| 243 | +// } | ||
| 244 | +// | ||
| 245 | +// return ConsumeOrderlyStatus.SUCCESS; | ||
| 246 | +// } | ||
| 247 | +// } | ||
| 248 | +// | ||
| 249 | +// @Override | ||
| 250 | +// public void afterPropertiesSet() throws Exception { | ||
| 251 | +// start(); | ||
| 252 | +// } | ||
| 253 | +// | ||
| 254 | +// @Override | ||
| 255 | +// public String toString() { | ||
| 256 | +// return "DefaultRocketMQListenerContainer{" + | ||
| 257 | +// "consumerGroup='" + consumerGroup + '\'' + | ||
| 258 | +// ", nameServer='" + nameServer + '\'' + | ||
| 259 | +// ", topic='" + topic + '\'' + | ||
| 260 | +// ", consumeMode=" + consumeMode + | ||
| 261 | +// ", selectorType=" + selectorType + | ||
| 262 | +// ", selectorExpress='" + selectorExpress + '\'' + | ||
| 263 | +// ", messageModel=" + messageModel + | ||
| 264 | +// '}'; | ||
| 265 | +// } | ||
| 266 | +// | ||
| 267 | +// @SuppressWarnings("unchecked") | ||
| 268 | +// private Object doConvertMessage(MessageExt messageExt) { | ||
| 269 | +// if (Objects.equals(messageType, MessageExt.class)) { | ||
| 270 | +// return messageExt; | ||
| 271 | +// } else { | ||
| 272 | +// String str = new String(messageExt.getBody(), Charset.forName(charset)); | ||
| 273 | +// if (Objects.equals(messageType, String.class)) { | ||
| 274 | +// return str; | ||
| 275 | +// } else { | ||
| 276 | +// // if msgType not string, use objectMapper change it. | ||
| 277 | +// try { | ||
| 278 | +// return objectMapper.readValue(str, messageType); | ||
| 279 | +// } catch (Exception e) { | ||
| 280 | +// log.info("convert failed. str:{}, msgType:{}", str, messageType); | ||
| 281 | +// throw new ConvertMsgException("cannot convert message to " + messageType, e); | ||
| 282 | +// } | ||
| 283 | +// } | ||
| 284 | +// } | ||
| 285 | +// } | ||
| 286 | +// | ||
| 287 | +// private Class getMessageType() { | ||
| 288 | +// Type[] interfaces = rocketMQListener.getClass().getGenericInterfaces(); | ||
| 289 | +// if (Objects.nonNull(interfaces)) { | ||
| 290 | +// for (Type type : interfaces) { | ||
| 291 | +// if (type instanceof ParameterizedType) { | ||
| 292 | +// ParameterizedType parameterizedType = (ParameterizedType) type; | ||
| 293 | +// if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { | ||
| 294 | +// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); | ||
| 295 | +// if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { | ||
| 296 | +// return (Class) actualTypeArguments[0]; | ||
| 297 | +// } else { | ||
| 298 | +// return Object.class; | ||
| 299 | +// } | ||
| 300 | +// } | ||
| 301 | +// } | ||
| 302 | +// } | ||
| 303 | +// | ||
| 304 | +// return Object.class; | ||
| 305 | +// } else { | ||
| 306 | +// return Object.class; | ||
| 307 | +// } | ||
| 308 | +// } | ||
| 309 | +// | ||
| 310 | +// private void initRocketMQPushConsumer() throws MQClientException { | ||
| 311 | +// | ||
| 312 | +// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | ||
| 313 | +// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | ||
| 314 | +// Assert.notNull(nameServer, "Property 'nameServer' is required"); | ||
| 315 | +// Assert.notNull(topic, "Property 'topic' is required"); | ||
| 316 | +// | ||
| 317 | +// consumer = new DefaultMQPushConsumer(consumerGroup); | ||
| 318 | +// consumer.setNamesrvAddr(nameServer); | ||
| 319 | +// consumer.setConsumeThreadMax(consumeThreadMax); | ||
| 320 | +// if (consumeThreadMax < consumer.getConsumeThreadMin()) { | ||
| 321 | +// consumer.setConsumeThreadMin(consumeThreadMax); | ||
| 322 | +// } | ||
| 323 | +// | ||
| 324 | +// consumer.setMessageModel(messageModel); | ||
| 325 | +// | ||
| 326 | +// switch (selectorType) { | ||
| 327 | +// case TAG: | ||
| 328 | +// consumer.subscribe(topic, selectorExpress); | ||
| 329 | +// break; | ||
| 330 | +// case SQL92: | ||
| 331 | +// consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
| 332 | +// break; | ||
| 333 | +// default: | ||
| 334 | +// throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
| 335 | +// } | ||
| 336 | +// | ||
| 337 | +// switch (consumeMode) { | ||
| 338 | +// case ORDERLY: | ||
| 339 | +// consumer.setMessageListener(new DefaultMessageListenerOrderly()); | ||
| 340 | +// break; | ||
| 341 | +// case CONCURRENTLY: | ||
| 342 | +// consumer.setMessageListener(new DefaultMessageListenerConcurrently()); | ||
| 343 | +// break; | ||
| 344 | +// default: | ||
| 345 | +// throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | ||
| 346 | +// } | ||
| 347 | +// | ||
| 348 | +// // provide an entryway to custom setting RocketMQ consumer | ||
| 349 | +// if (rocketMQListener instanceof AliyunRocketMQPushConsumerLifecycleListener) { | ||
| 350 | +// ((AliyunRocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer); | ||
| 351 | +// } | ||
| 352 | +// | ||
| 353 | +// } | ||
| 354 | +// | ||
| 355 | +//} |
src/main/java/org/apache/rocketmq/spring/starter/core/DefaultRocketMQListenerContainerConstants.java
| @@ -32,6 +32,20 @@ public final class DefaultRocketMQListenerContainerConstants { | @@ -32,6 +32,20 @@ public final class DefaultRocketMQListenerContainerConstants { | ||
| 32 | public static final String PROP_ROCKETMQ_LISTENER = "rocketMQListener"; | 32 | public static final String PROP_ROCKETMQ_LISTENER = "rocketMQListener"; |
| 33 | public static final String PROP_OBJECT_MAPPER = "objectMapper"; | 33 | public static final String PROP_OBJECT_MAPPER = "objectMapper"; |
| 34 | public static final String METHOD_DESTROY = "destroy"; | 34 | public static final String METHOD_DESTROY = "destroy"; |
| 35 | - /**生产者 add zwg*/ | ||
| 36 | - public static final String PROP_ROCKETMQ_TEMPLATE = "rocketMQTemplate"; | 35 | + public static final String PROP_ROCKETMQ_TEMPLATE = "rocketMQTemplate"; |
| 36 | + public static final String PROP_ONS_Addr = "onsAddr"; | ||
| 37 | + public static final String PROP_ACCESS_KEY = "accessKey"; | ||
| 38 | + public static final String PROP_SECRET_KEY = "secretKey"; | ||
| 39 | + /** | ||
| 40 | + * 环境前缀 | ||
| 41 | + */ | ||
| 42 | + public static final String PROP_ENVIRONMENT_PREFIX = "environmentPrefix"; | ||
| 43 | + /** | ||
| 44 | + * 消息消费失败发送的主题 | ||
| 45 | + */ | ||
| 46 | + public final static String CONSUMEFAILED_TOPIC = "ZTEITS_RNT_CLOUD"; | ||
| 47 | + /** | ||
| 48 | + * 消息消费失败发送的tag | ||
| 49 | + */ | ||
| 50 | + public final static String CONSUMEFAILED_TAG = "ConsumeMsgFailed"; | ||
| 37 | } | 51 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/RocketMQTemplate.java
| @@ -17,54 +17,30 @@ | @@ -17,54 +17,30 @@ | ||
| 17 | 17 | ||
| 18 | package org.apache.rocketmq.spring.starter.core; | 18 | package org.apache.rocketmq.spring.starter.core; |
| 19 | 19 | ||
| 20 | -import com.aliyun.openservices.ons.api.MessageAccessor; | ||
| 21 | -import com.aliyun.openservices.ons.api.OnExceptionContext; | ||
| 22 | -import com.aliyun.openservices.ons.api.Producer; | ||
| 23 | -import com.aliyun.openservices.ons.api.PropertyKeyConst; | ||
| 24 | -import com.aliyun.openservices.ons.api.exception.ONSClientException; | ||
| 25 | -import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.message.MessageExt; | ||
| 26 | -import com.fasterxml.jackson.core.JsonProcessingException; | ||
| 27 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 28 | import java.nio.charset.Charset; | 20 | import java.nio.charset.Charset; |
| 29 | -import java.util.Iterator; | ||
| 30 | import java.util.Map; | 21 | import java.util.Map; |
| 31 | -import java.util.Objects; | ||
| 32 | -import java.util.Properties; | ||
| 33 | import java.util.Map.Entry; | 22 | import java.util.Map.Entry; |
| 23 | +import java.util.Objects; | ||
| 34 | 24 | ||
| 35 | -import lombok.Getter; | ||
| 36 | -import lombok.Setter; | ||
| 37 | -import lombok.extern.slf4j.Slf4j; | ||
| 38 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
| 39 | -import org.apache.rocketmq.client.producer.MessageQueueSelector; | ||
| 40 | -import org.apache.rocketmq.client.producer.SendCallback; | ||
| 41 | -import org.apache.rocketmq.client.producer.SendResult; | ||
| 42 | -import org.apache.rocketmq.client.producer.SendStatus; | ||
| 43 | -import org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash; | ||
| 44 | -import org.apache.rocketmq.common.message.MessageConst; | ||
| 45 | -import org.apache.rocketmq.common.message.MessageQueue; | ||
| 46 | import org.springframework.beans.factory.DisposableBean; | 25 | import org.springframework.beans.factory.DisposableBean; |
| 47 | import org.springframework.beans.factory.InitializingBean; | 26 | import org.springframework.beans.factory.InitializingBean; |
| 48 | -import org.springframework.messaging.Message; | ||
| 49 | -import org.springframework.messaging.MessageHeaders; | ||
| 50 | import org.springframework.messaging.MessagingException; | 27 | import org.springframework.messaging.MessagingException; |
| 51 | -import org.springframework.messaging.core.AbstractMessageSendingTemplate; | ||
| 52 | -import org.springframework.messaging.core.MessagePostProcessor; | ||
| 53 | -import org.springframework.messaging.support.MessageBuilder; | ||
| 54 | -import org.springframework.util.Assert; | ||
| 55 | -import org.springframework.util.MimeTypeUtils; | ||
| 56 | -import org.springframework.util.StringUtils; | ||
| 57 | 28 | ||
| 58 | -@SuppressWarnings({"WeakerAccess", "unused"}) | 29 | +import com.aliyun.openservices.ons.api.Message; |
| 30 | +import com.aliyun.openservices.ons.api.Producer; | ||
| 31 | +import com.aliyun.openservices.ons.api.SendCallback; | ||
| 32 | +import com.aliyun.openservices.ons.api.SendResult; | ||
| 33 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 34 | + | ||
| 35 | +import lombok.Getter; | ||
| 36 | +import lombok.Setter; | ||
| 37 | +import lombok.extern.slf4j.Slf4j; | ||
| 38 | + | ||
| 59 | @Slf4j | 39 | @Slf4j |
| 60 | -public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> implements InitializingBean, DisposableBean { | 40 | +public class RocketMQTemplate implements InitializingBean, DisposableBean { |
| 61 | 41 | ||
| 62 | @Getter | 42 | @Getter |
| 63 | @Setter | 43 | @Setter |
| 64 | - private DefaultMQProducer defaultProducer; | ||
| 65 | - | ||
| 66 | - @Getter | ||
| 67 | - @Setter | ||
| 68 | private Producer aliyunProducer; | 44 | private Producer aliyunProducer; |
| 69 | 45 | ||
| 70 | @Setter | 46 | @Setter |
| @@ -74,479 +50,252 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> imp | @@ -74,479 +50,252 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> imp | ||
| 74 | @Getter | 50 | @Getter |
| 75 | @Setter | 51 | @Setter |
| 76 | private String charset = "UTF-8"; | 52 | private String charset = "UTF-8"; |
| 77 | - | ||
| 78 | - @Getter | 53 | + |
| 54 | + /** | ||
| 55 | + * 环境前缀 | ||
| 56 | + */ | ||
| 79 | @Setter | 57 | @Setter |
| 80 | - private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); | 58 | + private String environmentPrefix; |
| 81 | 59 | ||
| 82 | /** | 60 | /** |
| 83 | - * <p> Send message in synchronous mode. This method returns only when the sending procedure totally completes. | ||
| 84 | - * Reliable synchronous transmission is used in extensive scenes, such as important notification messages, SMS | ||
| 85 | - * notification, SMS marketing system, etc.. </p> | ||
| 86 | - * | ||
| 87 | - * <strong>Warn:</strong> this method has internal retry-mechanism, that is, internal implementation will retry | ||
| 88 | - * {@link DefaultMQProducer#getRetryTimesWhenSendFailed} times before claiming failure. As a result, multiple | ||
| 89 | - * messages may potentially delivered to broker(s). It's up to the application developers to resolve potential | ||
| 90 | - * duplication issue. | ||
| 91 | - * | ||
| 92 | - * @param destination formats: `topicName:tags` | ||
| 93 | - * @param message {@link org.springframework.messaging.Message} | 61 | + * 同步发送消息 |
| 62 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 63 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 64 | + * @param key 业务主键 | ||
| 65 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 66 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
| 67 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
| 68 | + * </p> | ||
| 69 | + * <ol> | ||
| 70 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
| 71 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
| 72 | + * </ol> | ||
| 94 | * @return {@link SendResult} | 73 | * @return {@link SendResult} |
| 74 | + * 2018年3月23日 zhaowg | ||
| 95 | */ | 75 | */ |
| 96 | - public SendResult syncSend(String destination, Message<?> message) { | ||
| 97 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 98 | - log.info("syncSend failed. destination:{}, message is null ", destination); | ||
| 99 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 76 | + public SendResult syncSend(String topic,String tag,String keys,Object payload,Map<String, String> userProperties,Long startDeliverTime) { |
| 77 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
| 78 | + log.info("同步消息发送失败,主题和消息不能为空"); | ||
| 79 | + throw new IllegalArgumentException("同步消息发送失败,主题和消息不能为空"); | ||
| 100 | } | 80 | } |
| 101 | 81 | ||
| 102 | try { | 82 | try { |
| 103 | - SendResult sendResult = new SendResult(); | ||
| 104 | - long now = System.currentTimeMillis(); | ||
| 105 | - if(aliyunProducer != null){ | ||
| 106 | - //阿里云发送 | ||
| 107 | - com.aliyun.openservices.ons.api.Message aliyunMsg = convertToAliyunRocketMsg(destination,message); | ||
| 108 | - com.aliyun.openservices.ons.api.SendResult aliyunSendResult = aliyunProducer.send(aliyunMsg); | ||
| 109 | - sendResult = convertAliyunSendResult(aliyunSendResult); | ||
| 110 | - }else if(defaultProducer != null){ | ||
| 111 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 112 | - sendResult = defaultProducer.send(rocketMsg); | ||
| 113 | - }else{ | ||
| 114 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
| 115 | - } | 83 | + long now = System.currentTimeMillis(); |
| 84 | + | ||
| 85 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
| 86 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
| 87 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
| 88 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + if(startDeliverTime!=null){ | ||
| 92 | + //设置定时发送时间 | ||
| 93 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
| 94 | + } | ||
| 95 | + //阿里云发送 | ||
| 96 | + SendResult sendResult = aliyunProducer.send(rocketMsg); | ||
| 116 | long costTime = System.currentTimeMillis() - now; | 97 | long costTime = System.currentTimeMillis() - now; |
| 117 | - log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); | 98 | + log.debug("发送消息耗时: {} ms, msgId:{}", costTime, sendResult.getMessageId()); |
| 118 | return sendResult; | 99 | return sendResult; |
| 119 | } catch (Exception e) { | 100 | } catch (Exception e) { |
| 120 | - log.info("syncSend failed. destination:{}, message:{} ", destination, message); | 101 | + log.info("同步发送失败. topic:{}, message:{} ", topic, payload); |
| 121 | throw new MessagingException(e.getMessage(), e); | 102 | throw new MessagingException(e.getMessage(), e); |
| 122 | } | 103 | } |
| 123 | } | 104 | } |
| 124 | 105 | ||
| 125 | /** | 106 | /** |
| 126 | - * Same to {@link #syncSend(String, Message)}. | ||
| 127 | - * | ||
| 128 | - * @param destination formats: `topicName:tags` | ||
| 129 | - * @param payload the Object to use as payload | 107 | + * Same to {@link #syncSend(String, String, String, Object, Map, Long)}. |
| 108 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 109 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 110 | + * @param key 业务主键 | ||
| 111 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 130 | * @return {@link SendResult} | 112 | * @return {@link SendResult} |
| 113 | + * 2018年3月23日 zhaowg | ||
| 131 | */ | 114 | */ |
| 132 | - public SendResult syncSend(String destination, Object payload) { | ||
| 133 | - Message<?> message = this.doConvert(payload, null, null); | ||
| 134 | - return syncSend(destination, message); | 115 | + public SendResult syncSend(String topic,String tag,String keys, Object payload) { |
| 116 | + return syncSend(topic, tag, keys, payload, null, null); | ||
| 135 | } | 117 | } |
| 136 | - | ||
| 137 | - | ||
| 138 | - /** | ||
| 139 | - * Same to {@link #syncSend(String, Message)} with send orderly with hashKey by specified. | ||
| 140 | - * | ||
| 141 | - * @param destination formats: `topicName:tags` | ||
| 142 | - * @param message {@link org.springframework.messaging.Message} | ||
| 143 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
| 144 | - * @return {@link SendResult} | ||
| 145 | - */ | ||
| 146 | - /*public SendResult syncSendOrderly(String destination, Message<?> message, String hashKey) { | ||
| 147 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 148 | - log.info("syncSendOrderly failed. destination:{}, message is null ", destination); | ||
| 149 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - try { | ||
| 153 | - long now = System.currentTimeMillis(); | ||
| 154 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 155 | - //TODO | ||
| 156 | - throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
| 157 | -// SendResult sendResult = producer.send(rocketMsg, messageQueueSelector, hashKey, timeout); | ||
| 158 | -// long costTime = System.currentTimeMillis() - now; | ||
| 159 | -// log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); | ||
| 160 | -// return sendResult; | ||
| 161 | - } catch (Exception e) { | ||
| 162 | - log.info("syncSendOrderly failed. destination:{}, message:{} ", destination, message); | ||
| 163 | - throw new MessagingException(e.getMessage(), e); | ||
| 164 | - } | ||
| 165 | - }*/ | ||
| 166 | - | ||
| 167 | - | ||
| 168 | /** | 118 | /** |
| 169 | - * Same to {@link #syncSend(String, Object)} with send orderly with hashKey by specified. | ||
| 170 | - * | ||
| 171 | - * @param destination formats: `topicName:tags` | ||
| 172 | - * @param payload the Object to use as payload | ||
| 173 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | 119 | + * Same to {@link #syncSend(String, String, String, Object)}. |
| 120 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 121 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 122 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 174 | * @return {@link SendResult} | 123 | * @return {@link SendResult} |
| 124 | + * 2018年3月23日 zhaowg | ||
| 175 | */ | 125 | */ |
| 176 | -// public SendResult syncSendOrderly(String destination, Object payload, String hashKey) { | ||
| 177 | -// Message<?> message = this.doConvert(payload, null, null); | ||
| 178 | -// return syncSendOrderly(destination, message, hashKey); | ||
| 179 | -// } | 126 | + public SendResult syncSend(String topic,String tag, Object payload) { |
| 127 | + return syncSend(topic, tag,null, payload); | ||
| 128 | + } | ||
| 180 | 129 | ||
| 181 | /** | 130 | /** |
| 182 | - * 将公共的sendCallBack转换为阿里云的sendCallBack | ||
| 183 | - * @param sendCallback | ||
| 184 | - * @return | 131 | + * 异步发送消息 |
| 132 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 133 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 134 | + * @param key 业务主键 | ||
| 135 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 136 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
| 137 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
| 138 | + * </p> | ||
| 139 | + * <ol> | ||
| 140 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
| 141 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
| 142 | + * </ol> | ||
| 143 | + * @param sendCallback 发送完成要执行的回调函数 | ||
| 185 | * 2018年3月23日 zhaowg | 144 | * 2018年3月23日 zhaowg |
| 186 | */ | 145 | */ |
| 187 | - private com.aliyun.openservices.ons.api.SendCallback aliyunSendCallBackConvert(final SendCallback sendCallback) { | ||
| 188 | - com.aliyun.openservices.ons.api.SendCallback aliyunSendCallBack = new com.aliyun.openservices.ons.api.SendCallback() { | ||
| 189 | - | ||
| 190 | - @Override | ||
| 191 | - public void onSuccess(com.aliyun.openservices.ons.api.SendResult sendResult) { | ||
| 192 | - sendCallback.onSuccess(convertAliyunSendResult(sendResult)); | ||
| 193 | - } | ||
| 194 | - | ||
| 195 | - @Override | ||
| 196 | - public void onException(OnExceptionContext context) { | ||
| 197 | - sendCallback.onException(context.getException()); | ||
| 198 | - } | ||
| 199 | - }; | ||
| 200 | - return aliyunSendCallBack; | ||
| 201 | - } | ||
| 202 | - /** | ||
| 203 | - * <p> Send message to broker asynchronously. asynchronous transmission is generally used in response time sensitive | ||
| 204 | - * business scenarios. </p> | ||
| 205 | - * | ||
| 206 | - * This method returns immediately. On sending completion, <code>sendCallback</code> will be executed. | ||
| 207 | - * | ||
| 208 | - * Similar to {@link #syncSend(String, Object)}, internal implementation would potentially retry up to {@link | ||
| 209 | - * DefaultMQProducer#getRetryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield | ||
| 210 | - * message duplication and application developers are the one to resolve this potential issue. | ||
| 211 | - * | ||
| 212 | - * @param destination formats: `topicName:tags` | ||
| 213 | - * @param message {@link org.springframework.messaging.Message} | ||
| 214 | - * @param sendCallback {@link SendCallback} | ||
| 215 | - */ | ||
| 216 | - public void asyncSend(String destination, Message<?> message, SendCallback sendCallback) { | ||
| 217 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 218 | - log.info("asyncSend failed. destination:{}, message is null ", destination); | ||
| 219 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 146 | + public void asyncSend(String topic,String tag,String keys,Object payload,Map<String, String> userProperties, |
| 147 | + Long startDeliverTime,SendCallback sendCallback) { | ||
| 148 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
| 149 | + log.info("异步消息发送失败,主题和消息不能为空"); | ||
| 150 | + throw new IllegalArgumentException("异步消息发送失败,主题和消息不能为空"); | ||
| 220 | } | 151 | } |
| 221 | - | ||
| 222 | try { | 152 | try { |
| 223 | - if(aliyunProducer != null){ | ||
| 224 | - com.aliyun.openservices.ons.api.Message aliyunMsg = this.convertToAliyunRocketMsg(destination, message); | ||
| 225 | - aliyunProducer.sendAsync(aliyunMsg, aliyunSendCallBackConvert(sendCallback)); | ||
| 226 | - }else if(defaultProducer != null){ | ||
| 227 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 228 | - defaultProducer.send(rocketMsg, sendCallback); | ||
| 229 | - }else{ | ||
| 230 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | 153 | + long now = System.currentTimeMillis(); |
| 154 | + | ||
| 155 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
| 156 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
| 157 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
| 158 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
| 159 | + } | ||
| 160 | + } | ||
| 161 | + if(startDeliverTime!=null){ | ||
| 162 | + //设置定时发送时间 | ||
| 163 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
| 231 | } | 164 | } |
| 165 | + //阿里云发送 | ||
| 166 | + aliyunProducer.sendAsync(rocketMsg, sendCallback); | ||
| 167 | + long costTime = System.currentTimeMillis() - now; | ||
| 168 | + log.debug("发送消息耗时: {} ms", costTime); | ||
| 232 | } catch (Exception e) { | 169 | } catch (Exception e) { |
| 233 | - log.info("asyncSend failed. destination:{}, message:{} ", destination, message); | 170 | + log.info("异步发送失败. topic:{}, message:{} ", topic, payload); |
| 234 | throw new MessagingException(e.getMessage(), e); | 171 | throw new MessagingException(e.getMessage(), e); |
| 235 | } | 172 | } |
| 236 | } | 173 | } |
| 237 | - | ||
| 238 | - /** | ||
| 239 | - * Same to {@link #asyncSend(String, Message, SendCallback)}. | ||
| 240 | - * | ||
| 241 | - * @param destination formats: `topicName:tags` | ||
| 242 | - * @param payload the Object to use as payload | ||
| 243 | - * @param sendCallback {@link SendCallback} | 174 | + /** |
| 175 | + * Same to {@link #asyncSend(String, String, String, Object, Map, Long, SendCallback)}. | ||
| 176 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 177 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 178 | + * @param key 业务主键 | ||
| 179 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 180 | + * @param sendCallback 发送完成要执行的回调函数 | ||
| 181 | + * @return {@link SendResult} | ||
| 182 | + * 2018年3月23日 zhaowg | ||
| 244 | */ | 183 | */ |
| 245 | - public void asyncSend(String destination, Object payload, SendCallback sendCallback) { | ||
| 246 | - Message<?> message = this.doConvert(payload, null, null); | ||
| 247 | - asyncSend(destination, message, sendCallback); | 184 | + public void asyncSend(String topic,String tag,String keys, Object payload,SendCallback sendCallback) { |
| 185 | + asyncSend(topic, tag, keys, payload, null, null,sendCallback); | ||
| 248 | } | 186 | } |
| 249 | - | ||
| 250 | - | ||
| 251 | /** | 187 | /** |
| 252 | - * Same to {@link #asyncSend(String, Message, SendCallback)} with send orderly with hashKey by specified. | ||
| 253 | - * | ||
| 254 | - * @param destination formats: `topicName:tags` | ||
| 255 | - * @param message {@link org.springframework.messaging.Message} | ||
| 256 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
| 257 | - * @param sendCallback {@link SendCallback} | ||
| 258 | - */ | ||
| 259 | -// public void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback) { | ||
| 260 | -// if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 261 | -// log.info("asyncSendOrderly failed. destination:{}, message is null ", destination); | ||
| 262 | -// throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
| 263 | -// } | ||
| 264 | -// | ||
| 265 | -// try { | ||
| 266 | -// org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 267 | -// //TODO zwg | ||
| 268 | -// throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
| 269 | -// //producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); | ||
| 270 | -// } catch (Exception e) { | ||
| 271 | -// log.info("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); | ||
| 272 | -// throw new MessagingException(e.getMessage(), e); | ||
| 273 | -// } | ||
| 274 | -// } | ||
| 275 | - | ||
| 276 | - /** | ||
| 277 | - * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)}. | ||
| 278 | - * | ||
| 279 | - * @param destination formats: `topicName:tags` | ||
| 280 | - * @param payload the Object to use as payload | ||
| 281 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
| 282 | - * @param sendCallback {@link SendCallback} | 188 | + * Same to {@link #asyncSend(String, String, String, Object,SendCallback)}. |
| 189 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 190 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 191 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 192 | + * @param sendCallback 发送完成要执行的回调函数 | ||
| 193 | + * @return {@link SendResult} | ||
| 194 | + * 2018年3月23日 zhaowg | ||
| 283 | */ | 195 | */ |
| 284 | -// public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback) { | ||
| 285 | -// Message<?> message = this.doConvert(payload, null, null); | ||
| 286 | -// asyncSendOrderly(destination, message, hashKey, sendCallback); | ||
| 287 | -// } | ||
| 288 | - | 196 | + public void asyncSend(String topic,String tag, Object payload,SendCallback sendCallback) { |
| 197 | + asyncSend(topic, tag,null, payload,sendCallback); | ||
| 198 | + } | ||
| 289 | /** | 199 | /** |
| 290 | - * Similar to <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a>, this method won't wait for | ||
| 291 | - * acknowledgement from broker before return. Obviously, it has maximums throughput yet potentials of message loss. | ||
| 292 | - * | ||
| 293 | - * One-way transmission is used for cases requiring moderate reliability, such as log collection. | ||
| 294 | - * | ||
| 295 | - * @param destination formats: `topicName:tags` | ||
| 296 | - * @param message {@link org.springframework.messaging.Message} | 200 | + * 服务器不应答,无法保证消息是否成功到达服务器 |
| 201 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 202 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 203 | + * @param key 业务主键 | ||
| 204 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 205 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
| 206 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
| 207 | + * </p> | ||
| 208 | + * <ol> | ||
| 209 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
| 210 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
| 211 | + * </ol> | ||
| 212 | + * 2018年3月23日 zhaowg | ||
| 297 | */ | 213 | */ |
| 298 | - public void sendOneWay(String destination, Message<?> message) { | ||
| 299 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 300 | - log.info("sendOneWay failed. destination:{}, message is null ", destination); | ||
| 301 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 214 | + public void sendOneWay(String topic,String tag,String keys,Object payload,Map<String, String> userProperties, |
| 215 | + Long startDeliverTime) { | ||
| 216 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
| 217 | + log.info("sendOneWay消息发送失败,主题和消息不能为空"); | ||
| 218 | + throw new IllegalArgumentException("sendOneWay消息发送失败,主题和消息不能为空"); | ||
| 302 | } | 219 | } |
| 303 | - | ||
| 304 | try { | 220 | try { |
| 305 | - if(aliyunProducer !=null){ | ||
| 306 | - //阿里云环境 | ||
| 307 | - com.aliyun.openservices.ons.api.Message aliyunMsg = convertToAliyunRocketMsg(destination, message); | ||
| 308 | - aliyunProducer.sendOneway(aliyunMsg); | ||
| 309 | - }else if(defaultProducer != null){ | ||
| 310 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 311 | - defaultProducer.sendOneway(rocketMsg); | ||
| 312 | - }else{ | ||
| 313 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
| 314 | - } | 221 | + long now = System.currentTimeMillis(); |
| 315 | 222 | ||
| 223 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
| 224 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
| 225 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
| 226 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
| 227 | + } | ||
| 228 | + } | ||
| 229 | + if(startDeliverTime!=null){ | ||
| 230 | + //设置定时发送时间 | ||
| 231 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
| 232 | + } | ||
| 233 | + //阿里云发送 | ||
| 234 | + aliyunProducer.sendOneway(rocketMsg); | ||
| 235 | + long costTime = System.currentTimeMillis() - now; | ||
| 236 | + log.debug("发送消息耗时: {} ms", costTime); | ||
| 316 | } catch (Exception e) { | 237 | } catch (Exception e) { |
| 317 | - log.info("sendOneWay failed. destination:{}, message:{} ", destination, message); | 238 | + log.info("sendOneWay发送失败. topic:{}, message:{} ", topic, payload); |
| 318 | throw new MessagingException(e.getMessage(), e); | 239 | throw new MessagingException(e.getMessage(), e); |
| 319 | } | 240 | } |
| 320 | } | 241 | } |
| 321 | - | ||
| 322 | - /** | ||
| 323 | - * Same to {@link #sendOneWay(String, Message)} | ||
| 324 | - * | ||
| 325 | - * @param destination formats: `topicName:tags` | ||
| 326 | - * @param payload the Object to use as payload | 242 | + /** |
| 243 | + * Same to {@link #sendOneWay(String, String, String, Object, Map, Long)}. | ||
| 244 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 245 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 246 | + * @param key 业务主键 | ||
| 247 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 248 | + * 2018年3月23日 zhaowg | ||
| 327 | */ | 249 | */ |
| 328 | - public void sendOneWay(String destination, Object payload) { | ||
| 329 | - Message<?> message = this.doConvert(payload, null, null); | ||
| 330 | - sendOneWay(destination, message); | 250 | + public void sendOneWay(String topic,String tag,String keys, Object payload) { |
| 251 | + sendOneWay(topic, tag, keys, payload, null, null); | ||
| 331 | } | 252 | } |
| 332 | - | ||
| 333 | /** | 253 | /** |
| 334 | - * Same to {@link #sendOneWay(String, Message)} with send orderly with hashKey by specified. | ||
| 335 | - * | ||
| 336 | - * @param destination formats: `topicName:tags` | ||
| 337 | - * @param message {@link org.springframework.messaging.Message} | ||
| 338 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | 254 | + * Same to {@link #sendOneWay(String, String, String, Object)}. |
| 255 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
| 256 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
| 257 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
| 258 | + * 2018年3月23日 zhaowg | ||
| 339 | */ | 259 | */ |
| 340 | -// public void sendOneWayOrderly(String destination, Message<?> message, String hashKey) { | ||
| 341 | -// if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
| 342 | -// log.info("sendOneWayOrderly failed. destination:{}, message is null ", destination); | ||
| 343 | -// throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
| 344 | -// } | ||
| 345 | -// | ||
| 346 | -// try { | ||
| 347 | -// //TODO zwg | ||
| 348 | -// throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
| 349 | -// //org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
| 350 | -// //producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); | ||
| 351 | -// } catch (Exception e) { | ||
| 352 | -// log.info("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); | ||
| 353 | -// throw new MessagingException(e.getMessage(), e); | ||
| 354 | -// } | ||
| 355 | -// } | 260 | + public void sendOneWay(String topic,String tag, Object payload) { |
| 261 | + sendOneWay(topic, tag,null, payload); | ||
| 262 | + } | ||
| 356 | 263 | ||
| 357 | - /** | ||
| 358 | - * Same to {@link #sendOneWayOrderly(String, Message, String)} | ||
| 359 | - * | ||
| 360 | - * @param destination formats: `topicName:tags` | ||
| 361 | - * @param payload the Object to use as payload | ||
| 362 | - */ | ||
| 363 | -// public void sendOneWayOrderly(String destination, Object payload, String hashKey) { | ||
| 364 | -// Message<?> message = this.doConvert(payload, null, null); | ||
| 365 | -// sendOneWayOrderly(destination, message, hashKey); | ||
| 366 | -// } | ||
| 367 | - | ||
| 368 | @Override | 264 | @Override |
| 369 | public void afterPropertiesSet() throws Exception { | 265 | public void afterPropertiesSet() throws Exception { |
| 370 | if(aliyunProducer != null){ | 266 | if(aliyunProducer != null){ |
| 371 | - log.info("开始启动阿里云环境生产者"); | 267 | + log.info("开始启动阿里云[环境标识:"+environmentPrefix+"]生产者"); |
| 372 | aliyunProducer.start(); | 268 | aliyunProducer.start(); |
| 373 | - }else if(defaultProducer != null){ | ||
| 374 | - log.info("开始启动非阿里云环境生产者"); | ||
| 375 | - defaultProducer.start(); | ||
| 376 | - }else{ | ||
| 377 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
| 378 | } | 269 | } |
| 379 | } | 270 | } |
| 380 | 271 | ||
| 381 | - protected void doSend(String destination, Message<?> message) { | ||
| 382 | - SendResult sendResult = syncSend(destination, message); | ||
| 383 | - log.debug("send message to `{}` finished. result:{}", destination, sendResult); | ||
| 384 | - } | ||
| 385 | /** | 272 | /** |
| 386 | - * 转换阿里云返回对象 | ||
| 387 | - * @param aliyunSendResult | 273 | + * 转换对象为字节 |
| 274 | + * @param msgObj | ||
| 388 | * @return | 275 | * @return |
| 389 | * 2018年3月23日 zhaowg | 276 | * 2018年3月23日 zhaowg |
| 390 | */ | 277 | */ |
| 391 | - private SendResult convertAliyunSendResult(com.aliyun.openservices.ons.api.SendResult aliyunSendResult) { | ||
| 392 | - SendResult sendResult = new SendResult(); | ||
| 393 | - sendResult.setMsgId(aliyunSendResult.getMessageId()); | ||
| 394 | - MessageQueue messageQueue = new MessageQueue(aliyunSendResult.getTopic(), null, 0); | ||
| 395 | - sendResult.setMessageQueue(messageQueue); | ||
| 396 | - sendResult.setSendStatus(SendStatus.SEND_OK); | ||
| 397 | - return sendResult; | ||
| 398 | - } | ||
| 399 | - /** | ||
| 400 | - * 转换为阿里云发送的消息对象 | ||
| 401 | - * @param destination formats: `topicName:tags` | ||
| 402 | - * @param message {@link org.springframework.messaging.Message} | ||
| 403 | - * @return | ||
| 404 | - * 2018年3月23日 zhaowg | ||
| 405 | - */ | ||
| 406 | - private com.aliyun.openservices.ons.api.Message convertToAliyunRocketMsg(String destination, Message<?> message) { | ||
| 407 | - Object payloadObj = message.getPayload(); | ||
| 408 | - byte[] payloads; | ||
| 409 | - | ||
| 410 | - if (payloadObj instanceof String) { | ||
| 411 | - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); | ||
| 412 | - } else { | ||
| 413 | - try { | ||
| 414 | - String jsonObj = this.objectMapper.writeValueAsString(payloadObj); | ||
| 415 | - payloads = jsonObj.getBytes(Charset.forName(charset)); | ||
| 416 | - } catch (Exception e) { | ||
| 417 | - throw new RuntimeException("convert to RocketMQ message failed.", e); | ||
| 418 | - } | ||
| 419 | - } | ||
| 420 | - | ||
| 421 | - String[] tempArr = destination.split(":", 2); | ||
| 422 | - String topic = tempArr[0]; | ||
| 423 | - String tags = ""; | ||
| 424 | - if (tempArr.length > 1) { | ||
| 425 | - tags = tempArr[1]; | ||
| 426 | - } | ||
| 427 | - | ||
| 428 | - com.aliyun.openservices.ons.api.Message rocketMsg = new com.aliyun.openservices.ons.api.Message(topic, tags, payloads); | ||
| 429 | - | ||
| 430 | - MessageHeaders headers = message.getHeaders(); | ||
| 431 | - if (Objects.nonNull(headers) && !headers.isEmpty()) { | ||
| 432 | - Object keys = headers.get(MessageConst.PROPERTY_KEYS); | ||
| 433 | - if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key | ||
| 434 | - rocketMsg.setKey(keys.toString()); | ||
| 435 | - } | ||
| 436 | - | ||
| 437 | - headers.entrySet().stream() | ||
| 438 | - .filter(entry -> !Objects.equals(entry.getKey(), MessageConst.PROPERTY_KEYS) | ||
| 439 | - && !Objects.equals(entry.getKey(), "FLAG") | ||
| 440 | - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "KEYS", "FLAG", "WAIT_STORE_MSG_OK" | ||
| 441 | - .forEach(entry -> { | ||
| 442 | - rocketMsg.putUserProperties("USERS_" + entry.getKey(), String.valueOf(entry.getValue())); // add other properties with prefix "USERS_" | ||
| 443 | - }); | ||
| 444 | - | ||
| 445 | - } | ||
| 446 | - | ||
| 447 | - return rocketMsg; | ||
| 448 | - } | ||
| 449 | - /** | ||
| 450 | - * Convert spring message to rocketMQ message | ||
| 451 | - * | ||
| 452 | - * @param destination formats: `topicName:tags` | ||
| 453 | - * @param message {@link org.springframework.messaging.Message} | ||
| 454 | - * @return instance of {@link org.apache.rocketmq.common.message.Message} | ||
| 455 | - */ | ||
| 456 | - private org.apache.rocketmq.common.message.Message convertToRocketMsg(String destination, Message<?> message) { | ||
| 457 | - Object payloadObj = message.getPayload(); | 278 | + private byte[] convertToRocketMsg(Object msgObj) { |
| 458 | byte[] payloads; | 279 | byte[] payloads; |
| 459 | 280 | ||
| 460 | - if (payloadObj instanceof String) { | ||
| 461 | - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); | 281 | + if (msgObj instanceof String) { |
| 282 | + payloads = ((String) msgObj).getBytes(Charset.forName(charset)); | ||
| 462 | } else { | 283 | } else { |
| 463 | try { | 284 | try { |
| 464 | - String jsonObj = this.objectMapper.writeValueAsString(payloadObj); | 285 | + String jsonObj = this.objectMapper.writeValueAsString(msgObj); |
| 465 | payloads = jsonObj.getBytes(Charset.forName(charset)); | 286 | payloads = jsonObj.getBytes(Charset.forName(charset)); |
| 466 | } catch (Exception e) { | 287 | } catch (Exception e) { |
| 467 | throw new RuntimeException("convert to RocketMQ message failed.", e); | 288 | throw new RuntimeException("convert to RocketMQ message failed.", e); |
| 468 | } | 289 | } |
| 469 | } | 290 | } |
| 470 | - | ||
| 471 | - String[] tempArr = destination.split(":", 2); | ||
| 472 | - String topic = tempArr[0]; | ||
| 473 | - String tags = ""; | ||
| 474 | - if (tempArr.length > 1) { | ||
| 475 | - tags = tempArr[1]; | ||
| 476 | - } | ||
| 477 | - | ||
| 478 | - org.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message(topic, tags, payloads); | ||
| 479 | - | ||
| 480 | - MessageHeaders headers = message.getHeaders(); | ||
| 481 | - if (Objects.nonNull(headers) && !headers.isEmpty()) { | ||
| 482 | - Object keys = headers.get(MessageConst.PROPERTY_KEYS); | ||
| 483 | - if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key | ||
| 484 | - rocketMsg.setKeys(keys.toString()); | ||
| 485 | - } | ||
| 486 | - | ||
| 487 | - // set rocketMQ message flag | ||
| 488 | - Object flagObj = headers.getOrDefault("FLAG", "0"); | ||
| 489 | - int flag = 0; | ||
| 490 | - try { | ||
| 491 | - flag = Integer.parseInt(flagObj.toString()); | ||
| 492 | - } catch (NumberFormatException e) { | ||
| 493 | - // ignore | ||
| 494 | - log.info("flag must be integer, flagObj:{}", flagObj); | ||
| 495 | - } | ||
| 496 | - rocketMsg.setFlag(flag); | ||
| 497 | - | ||
| 498 | - // set rocketMQ message waitStoreMsgOkObj | ||
| 499 | - Object waitStoreMsgOkObj = headers.getOrDefault("WAIT_STORE_MSG_OK", "true"); | ||
| 500 | - boolean waitStoreMsgOK = Boolean.TRUE.equals(waitStoreMsgOkObj); | ||
| 501 | - rocketMsg.setWaitStoreMsgOK(waitStoreMsgOK); | ||
| 502 | - | ||
| 503 | - headers.entrySet().stream() | ||
| 504 | - .filter(entry -> !Objects.equals(entry.getKey(), MessageConst.PROPERTY_KEYS) | ||
| 505 | - && !Objects.equals(entry.getKey(), "FLAG") | ||
| 506 | - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "KEYS", "FLAG", "WAIT_STORE_MSG_OK" | ||
| 507 | - .forEach(entry -> { | ||
| 508 | - rocketMsg.putUserProperty("USERS_" + entry.getKey(), String.valueOf(entry.getValue())); // add other properties with prefix "USERS_" | ||
| 509 | - }); | ||
| 510 | - | ||
| 511 | - } | ||
| 512 | - | ||
| 513 | - return rocketMsg; | 291 | + return payloads; |
| 514 | } | 292 | } |
| 515 | 293 | ||
| 516 | - @Override | ||
| 517 | - protected Message<?> doConvert(Object payload, Map<String, Object> headers, MessagePostProcessor postProcessor) { | ||
| 518 | - String content; | ||
| 519 | - if (payload instanceof String) { | ||
| 520 | - content = (String) payload; | ||
| 521 | - } else { | ||
| 522 | - // if payload not as string, use objectMapper change it. | ||
| 523 | - try { | ||
| 524 | - content = objectMapper.writeValueAsString(payload); | ||
| 525 | - } catch (JsonProcessingException e) { | ||
| 526 | - log.info("convert payload to String failed. payload:{}", payload); | ||
| 527 | - throw new RuntimeException("convert to payload to String failed.", e); | ||
| 528 | - } | ||
| 529 | - } | ||
| 530 | - | ||
| 531 | - MessageBuilder<?> builder = MessageBuilder.withPayload(content); | ||
| 532 | - if (headers != null) { | ||
| 533 | - builder.copyHeaders(headers); | ||
| 534 | - } | ||
| 535 | - builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); | ||
| 536 | - | ||
| 537 | - Message<?> message = builder.build(); | ||
| 538 | - if (postProcessor != null) { | ||
| 539 | - message = postProcessor.postProcessMessage(message); | ||
| 540 | - } | ||
| 541 | - return message; | ||
| 542 | - } | ||
| 543 | 294 | ||
| 544 | @Override | 295 | @Override |
| 545 | public void destroy() { | 296 | public void destroy() { |
| 546 | - if (Objects.nonNull(defaultProducer)) { | ||
| 547 | - defaultProducer.shutdown(); | ||
| 548 | - } | ||
| 549 | if(Objects.nonNull(aliyunProducer)){ | 297 | if(Objects.nonNull(aliyunProducer)){ |
| 298 | + log.info("开始关闭阿里云[环境标识:"+environmentPrefix+"]生产者"); | ||
| 550 | aliyunProducer.shutdown(); | 299 | aliyunProducer.shutdown(); |
| 551 | } | 300 | } |
| 552 | } | 301 | } |
src/main/java/org/apache/rocketmq/spring/starter/enums/ConsumeMode.java
| @@ -19,12 +19,17 @@ package org.apache.rocketmq.spring.starter.enums; | @@ -19,12 +19,17 @@ package org.apache.rocketmq.spring.starter.enums; | ||
| 19 | 19 | ||
| 20 | public enum ConsumeMode { | 20 | public enum ConsumeMode { |
| 21 | /** | 21 | /** |
| 22 | - * receive asynchronously delivered messages concurrently | 22 | + * 同时接收异步发送的消息 |
| 23 | */ | 23 | */ |
| 24 | CONCURRENTLY, | 24 | CONCURRENTLY, |
| 25 | 25 | ||
| 26 | /** | 26 | /** |
| 27 | - * receive asynchronously delivered messages orderly. one queue, one thread | 27 | + * 顺序接收消息,一个队列,一个线程 |
| 28 | */ | 28 | */ |
| 29 | - ORDERLY | 29 | + ORDERLY, |
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 批量接收发送的消息,允许自定义范围为[1, 32], 实际消费数量可能小于该值 | ||
| 33 | + */ | ||
| 34 | + BATCH | ||
| 30 | } | 35 | } |
src/main/java/org/apache/rocketmq/spring/starter/enums/SelectorType.java
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | 17 | ||
| 18 | package org.apache.rocketmq.spring.starter.enums; | 18 | package org.apache.rocketmq.spring.starter.enums; |
| 19 | 19 | ||
| 20 | -import org.apache.rocketmq.common.filter.ExpressionType; | 20 | +import com.aliyun.openservices.ons.api.ExpressionType; |
| 21 | 21 | ||
| 22 | public enum SelectorType { | 22 | public enum SelectorType { |
| 23 | 23 |
src/main/java/org/apache/rocketmq/spring/starter/utils/ExceptionUtil.java
0 → 100644
| 1 | +package org.apache.rocketmq.spring.starter.utils; | ||
| 2 | + | ||
| 3 | +import java.io.PrintWriter; | ||
| 4 | +import java.io.StringWriter; | ||
| 5 | + | ||
| 6 | +public class ExceptionUtil { | ||
| 7 | + | ||
| 8 | + public static String getTrace(Throwable t) { | ||
| 9 | + StringBuffer buffer = new StringBuffer(); | ||
| 10 | + if(t==null){ | ||
| 11 | + return ""; | ||
| 12 | + } | ||
| 13 | + StringWriter stringWriter = new StringWriter(); | ||
| 14 | + PrintWriter writer = new PrintWriter(stringWriter); | ||
| 15 | + t.printStackTrace(writer); | ||
| 16 | + //设置堆栈信息 | ||
| 17 | + buffer.append("堆栈信息为:" + stringWriter.getBuffer().toString()); | ||
| 18 | + return buffer.toString(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
src/test/java/org/apache/rocketmq/spring/starter/RocketMQAutoConfigurationTests.java
| 1 | -/* | ||
| 2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| 3 | - * contributor license agreements. See the NOTICE file distributed with | ||
| 4 | - * this work for additional information regarding copyright ownership. | ||
| 5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| 6 | - * (the "License"); you may not use this file except in compliance with | ||
| 7 | - * the License. You may obtain a copy of the License at | ||
| 8 | - * | ||
| 9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | - * | ||
| 11 | - * Unless required by applicable law or agreed to in writing, software | ||
| 12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | - * See the License for the specific language governing permissions and | ||
| 15 | - * limitations under the License. | ||
| 16 | - */ | ||
| 17 | - | ||
| 18 | -package org.apache.rocketmq.spring.starter; | ||
| 19 | - | ||
| 20 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 21 | -import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
| 22 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
| 23 | -import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
| 24 | -import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
| 25 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 26 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 27 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
| 28 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 29 | -import org.junit.After; | ||
| 30 | -import org.junit.Test; | ||
| 31 | -import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
| 32 | -import org.springframework.boot.test.util.EnvironmentTestUtils; | ||
| 33 | -import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||
| 34 | - | ||
| 35 | -import static org.assertj.core.api.Assertions.assertThat; | ||
| 36 | - | ||
| 37 | -public class RocketMQAutoConfigurationTests { | ||
| 38 | - | ||
| 39 | - private static final String TEST_CONSUMER_GROUP = "my_consumer"; | ||
| 40 | - | ||
| 41 | - private static final String TEST_TOPIC = "test-topic"; | ||
| 42 | - | ||
| 43 | - private AnnotationConfigApplicationContext context; | ||
| 44 | - | ||
| 45 | - @Test | ||
| 46 | - public void rocketMQTemplate() { | ||
| 47 | - | ||
| 48 | - load("spring.rocketmq.nameServer=127.0.0.1:9876", | ||
| 49 | - "spring.rocketmq.producer.group=my_group", | ||
| 50 | - "spring.rocketmq.producer.send-msg-timeout=30000", | ||
| 51 | - "spring.rocketmq.producer.retry-times-when-send-async-failed=1", | ||
| 52 | - "spring.rocketmq.producer.compress-msg-body-over-howmuch=1024", | ||
| 53 | - "spring.rocketmq.producer.max-message-size=10240", | ||
| 54 | - "spring.rocketmq.producer.retry-another-broker-when-not-store-ok=true", | ||
| 55 | - "spring.rocketmq.producer.retry-times-when-send-failed=1"); | ||
| 56 | - | ||
| 57 | - assertThat(this.context.containsBean("rocketMQMessageObjectMapper")).isTrue(); | ||
| 58 | - assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
| 59 | - assertThat(this.context.containsBean("rocketMQTemplate")).isTrue(); | ||
| 60 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 61 | - | ||
| 62 | - RocketMQTemplate rocketMQTemplate = this.context.getBean(RocketMQTemplate.class); | ||
| 63 | - ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
| 64 | - assertThat(rocketMQTemplate.getObjectMapper()).isEqualTo(objectMapper); | ||
| 65 | - | ||
| 66 | - DefaultMQProducer defaultMQProducer = rocketMQTemplate.getProducer(); | ||
| 67 | - | ||
| 68 | - assertThat(defaultMQProducer.getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); | ||
| 69 | - assertThat(defaultMQProducer.getProducerGroup()).isEqualTo("my_group"); | ||
| 70 | - assertThat(defaultMQProducer.getSendMsgTimeout()).isEqualTo(30000); | ||
| 71 | - assertThat(defaultMQProducer.getRetryTimesWhenSendAsyncFailed()).isEqualTo(1); | ||
| 72 | - assertThat(defaultMQProducer.getCompressMsgBodyOverHowmuch()).isEqualTo(1024); | ||
| 73 | - assertThat(defaultMQProducer.getMaxMessageSize()).isEqualTo(10240); | ||
| 74 | - assertThat(defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()).isTrue(); | ||
| 75 | - assertThat(defaultMQProducer.getRetryTimesWhenSendFailed()).isEqualTo(1); | ||
| 76 | - } | ||
| 77 | - | ||
| 78 | - @Test | ||
| 79 | - public void enableProducer() { | ||
| 80 | - load(); | ||
| 81 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 82 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 83 | - closeContext(); | ||
| 84 | - | ||
| 85 | - load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 86 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 87 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 88 | - closeContext(); | ||
| 89 | - | ||
| 90 | - load("spring.rocketmq.producer.group=my_group"); | ||
| 91 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 92 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 93 | - closeContext(); | ||
| 94 | - | ||
| 95 | - load("spring.rocketmq.nameServer=127.0.0.1:9876", "spring.rocketmq.producer.group=my_group"); | ||
| 96 | - assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
| 97 | - assertThat(this.context.containsBean("rocketMQTemplate")).isEqualTo(true); | ||
| 98 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - @Test | ||
| 102 | - public void enableConsumer() { | ||
| 103 | - load(); | ||
| 104 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 105 | - closeContext(); | ||
| 106 | - | ||
| 107 | - load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 108 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 109 | - closeContext(); | ||
| 110 | - | ||
| 111 | - load(false); | ||
| 112 | - this.context.registerBeanDefinition("myListener", | ||
| 113 | - BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
| 114 | - this.context.refresh(); | ||
| 115 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 116 | - closeContext(); | ||
| 117 | - | ||
| 118 | - load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 119 | - this.context.registerBeanDefinition("myListener", | ||
| 120 | - BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
| 121 | - this.context.refresh(); | ||
| 122 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
| 123 | - assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
| 124 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 125 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 126 | - | ||
| 127 | - } | ||
| 128 | - | ||
| 129 | - @Test | ||
| 130 | - public void listenerContainer() { | ||
| 131 | - load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 132 | - BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(MyListener.class); | ||
| 133 | - this.context.registerBeanDefinition("myListener", beanBuilder.getBeanDefinition()); | ||
| 134 | - this.context.refresh(); | ||
| 135 | - | ||
| 136 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
| 137 | - assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
| 138 | - | ||
| 139 | - DefaultRocketMQListenerContainer listenerContainer = | ||
| 140 | - this.context.getBean(DefaultRocketMQListenerContainer.class.getName() + "_1", | ||
| 141 | - DefaultRocketMQListenerContainer.class); | ||
| 142 | - ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
| 143 | - assertThat(listenerContainer.getObjectMapper()).isEqualTo(objectMapper); | ||
| 144 | - assertThat(listenerContainer.getConsumeMode()).isEqualTo(ConsumeMode.CONCURRENTLY); | ||
| 145 | - assertThat(listenerContainer.getSelectorType()).isEqualTo(SelectorType.TAG); | ||
| 146 | - assertThat(listenerContainer.getSelectorExpress()).isEqualTo("*"); | ||
| 147 | - assertThat(listenerContainer.getConsumerGroup()).isEqualTo(TEST_CONSUMER_GROUP); | ||
| 148 | - assertThat(listenerContainer.getTopic()).isEqualTo(TEST_TOPIC); | ||
| 149 | - assertThat(listenerContainer.getNameServer()).isEqualTo("127.0.0.1:9876"); | ||
| 150 | - assertThat(listenerContainer.getMessageModel()).isEqualTo(MessageModel.CLUSTERING); | ||
| 151 | - assertThat(listenerContainer.getConsumeThreadMax()).isEqualTo(1); | ||
| 152 | - } | ||
| 153 | - | ||
| 154 | - @After | ||
| 155 | - public void closeContext() { | ||
| 156 | - if (this.context != null) { | ||
| 157 | - this.context.close(); | ||
| 158 | - } | ||
| 159 | - } | ||
| 160 | - | ||
| 161 | - @RocketMQMessageListener(consumerGroup = TEST_CONSUMER_GROUP, topic = TEST_TOPIC, consumeThreadMax = 1) | ||
| 162 | - private static class MyListener implements RocketMQListener<String> { | ||
| 163 | - | ||
| 164 | - @Override | ||
| 165 | - public void onMessage(String message) { | ||
| 166 | - System.out.println(message); | ||
| 167 | - } | ||
| 168 | - } | ||
| 169 | - | ||
| 170 | - private void load(boolean refresh, String... environment) { | ||
| 171 | - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
| 172 | - ctx.register(RocketMQAutoConfiguration.class); | ||
| 173 | - EnvironmentTestUtils.addEnvironment(ctx, environment); | ||
| 174 | - if (refresh) { | ||
| 175 | - ctx.refresh(); | ||
| 176 | - } | ||
| 177 | - this.context = ctx; | ||
| 178 | - } | ||
| 179 | - | ||
| 180 | - private void load(String... environment) { | ||
| 181 | - load(true, environment); | ||
| 182 | - } | ||
| 183 | -} | ||
| 184 | - | 1 | +///* |
| 2 | +// * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| 3 | +// * contributor license agreements. See the NOTICE file distributed with | ||
| 4 | +// * this work for additional information regarding copyright ownership. | ||
| 5 | +// * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| 6 | +// * (the "License"); you may not use this file except in compliance with | ||
| 7 | +// * the License. You may obtain a copy of the License at | ||
| 8 | +// * | ||
| 9 | +// * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | +// * | ||
| 11 | +// * Unless required by applicable law or agreed to in writing, software | ||
| 12 | +// * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | +// * See the License for the specific language governing permissions and | ||
| 15 | +// * limitations under the License. | ||
| 16 | +// */ | ||
| 17 | +// | ||
| 18 | +//package org.apache.rocketmq.spring.starter; | ||
| 19 | +// | ||
| 20 | +//import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 21 | +//import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
| 22 | +//import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
| 23 | +//import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
| 24 | +//import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
| 25 | +//import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
| 26 | +//import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
| 27 | +//import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
| 28 | +//import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
| 29 | +//import org.junit.After; | ||
| 30 | +//import org.junit.Test; | ||
| 31 | +//import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
| 32 | +//import org.springframework.boot.test.util.EnvironmentTestUtils; | ||
| 33 | +//import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||
| 34 | +// | ||
| 35 | +//import static org.assertj.core.api.Assertions.assertThat; | ||
| 36 | +// | ||
| 37 | +//public class RocketMQAutoConfigurationTests { | ||
| 38 | +// | ||
| 39 | +// private static final String TEST_CONSUMER_GROUP = "my_consumer"; | ||
| 40 | +// | ||
| 41 | +// private static final String TEST_TOPIC = "test-topic"; | ||
| 42 | +// | ||
| 43 | +// private AnnotationConfigApplicationContext context; | ||
| 44 | +// | ||
| 45 | +// @Test | ||
| 46 | +// public void rocketMQTemplate() { | ||
| 47 | +// | ||
| 48 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876", | ||
| 49 | +// "spring.rocketmq.producer.group=my_group", | ||
| 50 | +// "spring.rocketmq.producer.send-msg-timeout=30000", | ||
| 51 | +// "spring.rocketmq.producer.retry-times-when-send-async-failed=1", | ||
| 52 | +// "spring.rocketmq.producer.compress-msg-body-over-howmuch=1024", | ||
| 53 | +// "spring.rocketmq.producer.max-message-size=10240", | ||
| 54 | +// "spring.rocketmq.producer.retry-another-broker-when-not-store-ok=true", | ||
| 55 | +// "spring.rocketmq.producer.retry-times-when-send-failed=1"); | ||
| 56 | +// | ||
| 57 | +// assertThat(this.context.containsBean("rocketMQMessageObjectMapper")).isTrue(); | ||
| 58 | +// assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
| 59 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isTrue(); | ||
| 60 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 61 | +// | ||
| 62 | +// RocketMQTemplate rocketMQTemplate = this.context.getBean(RocketMQTemplate.class); | ||
| 63 | +// ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
| 64 | +// assertThat(rocketMQTemplate.getObjectMapper()).isEqualTo(objectMapper); | ||
| 65 | +// | ||
| 66 | +// DefaultMQProducer defaultMQProducer = rocketMQTemplate.getProducer(); | ||
| 67 | +// | ||
| 68 | +// assertThat(defaultMQProducer.getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); | ||
| 69 | +// assertThat(defaultMQProducer.getProducerGroup()).isEqualTo("my_group"); | ||
| 70 | +// assertThat(defaultMQProducer.getSendMsgTimeout()).isEqualTo(30000); | ||
| 71 | +// assertThat(defaultMQProducer.getRetryTimesWhenSendAsyncFailed()).isEqualTo(1); | ||
| 72 | +// assertThat(defaultMQProducer.getCompressMsgBodyOverHowmuch()).isEqualTo(1024); | ||
| 73 | +// assertThat(defaultMQProducer.getMaxMessageSize()).isEqualTo(10240); | ||
| 74 | +// assertThat(defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()).isTrue(); | ||
| 75 | +// assertThat(defaultMQProducer.getRetryTimesWhenSendFailed()).isEqualTo(1); | ||
| 76 | +// } | ||
| 77 | +// | ||
| 78 | +// @Test | ||
| 79 | +// public void enableProducer() { | ||
| 80 | +// load(); | ||
| 81 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 82 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 83 | +// closeContext(); | ||
| 84 | +// | ||
| 85 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 86 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 87 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 88 | +// closeContext(); | ||
| 89 | +// | ||
| 90 | +// load("spring.rocketmq.producer.group=my_group"); | ||
| 91 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 92 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 93 | +// closeContext(); | ||
| 94 | +// | ||
| 95 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876", "spring.rocketmq.producer.group=my_group"); | ||
| 96 | +// assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
| 97 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isEqualTo(true); | ||
| 98 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 99 | +// } | ||
| 100 | +// | ||
| 101 | +// @Test | ||
| 102 | +// public void enableConsumer() { | ||
| 103 | +// load(); | ||
| 104 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 105 | +// closeContext(); | ||
| 106 | +// | ||
| 107 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 108 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 109 | +// closeContext(); | ||
| 110 | +// | ||
| 111 | +// load(false); | ||
| 112 | +// this.context.registerBeanDefinition("myListener", | ||
| 113 | +// BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
| 114 | +// this.context.refresh(); | ||
| 115 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
| 116 | +// closeContext(); | ||
| 117 | +// | ||
| 118 | +// load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 119 | +// this.context.registerBeanDefinition("myListener", | ||
| 120 | +// BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
| 121 | +// this.context.refresh(); | ||
| 122 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
| 123 | +// assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
| 124 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
| 125 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
| 126 | +// | ||
| 127 | +// } | ||
| 128 | +// | ||
| 129 | +// @Test | ||
| 130 | +// public void listenerContainer() { | ||
| 131 | +// load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
| 132 | +// BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(MyListener.class); | ||
| 133 | +// this.context.registerBeanDefinition("myListener", beanBuilder.getBeanDefinition()); | ||
| 134 | +// this.context.refresh(); | ||
| 135 | +// | ||
| 136 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
| 137 | +// assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
| 138 | +// | ||
| 139 | +// DefaultRocketMQListenerContainer listenerContainer = | ||
| 140 | +// this.context.getBean(DefaultRocketMQListenerContainer.class.getName() + "_1", | ||
| 141 | +// DefaultRocketMQListenerContainer.class); | ||
| 142 | +// ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
| 143 | +// assertThat(listenerContainer.getObjectMapper()).isEqualTo(objectMapper); | ||
| 144 | +// assertThat(listenerContainer.getConsumeMode()).isEqualTo(ConsumeMode.CONCURRENTLY); | ||
| 145 | +// assertThat(listenerContainer.getSelectorType()).isEqualTo(SelectorType.TAG); | ||
| 146 | +// assertThat(listenerContainer.getSelectorExpress()).isEqualTo("*"); | ||
| 147 | +// assertThat(listenerContainer.getConsumerGroup()).isEqualTo(TEST_CONSUMER_GROUP); | ||
| 148 | +// assertThat(listenerContainer.getTopic()).isEqualTo(TEST_TOPIC); | ||
| 149 | +// assertThat(listenerContainer.getNameServer()).isEqualTo("127.0.0.1:9876"); | ||
| 150 | +// assertThat(listenerContainer.getMessageModel()).isEqualTo(MessageModel.CLUSTERING); | ||
| 151 | +// assertThat(listenerContainer.getConsumeThreadMax()).isEqualTo(1); | ||
| 152 | +// } | ||
| 153 | +// | ||
| 154 | +// @After | ||
| 155 | +// public void closeContext() { | ||
| 156 | +// if (this.context != null) { | ||
| 157 | +// this.context.close(); | ||
| 158 | +// } | ||
| 159 | +// } | ||
| 160 | +// | ||
| 161 | +// @RocketMQMessageListener(consumerGroup = TEST_CONSUMER_GROUP, topic = TEST_TOPIC, consumeThreadMax = 1) | ||
| 162 | +// private static class MyListener implements RocketMQListener<String> { | ||
| 163 | +// | ||
| 164 | +// @Override | ||
| 165 | +// public void onMessage(String message) { | ||
| 166 | +// System.out.println(message); | ||
| 167 | +// } | ||
| 168 | +// } | ||
| 169 | +// | ||
| 170 | +// private void load(boolean refresh, String... environment) { | ||
| 171 | +// AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
| 172 | +// ctx.register(RocketMQAutoConfiguration.class); | ||
| 173 | +// EnvironmentTestUtils.addEnvironment(ctx, environment); | ||
| 174 | +// if (refresh) { | ||
| 175 | +// ctx.refresh(); | ||
| 176 | +// } | ||
| 177 | +// this.context = ctx; | ||
| 178 | +// } | ||
| 179 | +// | ||
| 180 | +// private void load(String... environment) { | ||
| 181 | +// load(true, environment); | ||
| 182 | +// } | ||
| 183 | +//} | ||
| 184 | +// |