Commit 7b3d47526792fd5a26fdaa9233afcc69f110ed5b
Committed by
GitHub
1 parent
ca193239
[2.5] created rabbitmq queue (#2589)
* created main classes for RabbitMq queue * created temp version rabbitmq * Merge branch 'develop/2.5' of https://github.com/thingsboard/thingsboard into develop/2.5-rabbitmq # Conflicts: # common/queue/pom.xml * rabbit improvements
Showing
16 changed files
with
904 additions
and
20 deletions
@@ -119,6 +119,8 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | @@ -119,6 +119,8 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< | ||
119 | if (submitExecutor != null) { | 119 | if (submitExecutor != null) { |
120 | submitExecutor.shutdownNow(); | 120 | submitExecutor.shutdownNow(); |
121 | } | 121 | } |
122 | + | ||
123 | + ruleEngineSettings.getQueues().forEach(config -> consumerConfigurations.put(config.getName(), config)); | ||
122 | } | 124 | } |
123 | 125 | ||
124 | @Override | 126 | @Override |
@@ -550,6 +550,16 @@ queue: | @@ -550,6 +550,16 @@ queue: | ||
550 | sas_key_name: "${TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME:YOUR_SAS_KEY_NAME}" | 550 | sas_key_name: "${TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME:YOUR_SAS_KEY_NAME}" |
551 | sas_key: "${TB_QUEUE_SERVICE_BUS_SAS_KEY:YOUR_SAS_KEY}" | 551 | sas_key: "${TB_QUEUE_SERVICE_BUS_SAS_KEY:YOUR_SAS_KEY}" |
552 | max_messages: "${TB_QUEUE_SERVICE_BUS_MAX_MESSAGES:1000}" | 552 | max_messages: "${TB_QUEUE_SERVICE_BUS_MAX_MESSAGES:1000}" |
553 | + rabbitmq: | ||
554 | + exchange_name: "${TB_QUEUE_RABBIT_MQ_EXCHANGE_NAME:}" | ||
555 | + host: "${TB_QUEUE_RABBIT_MQ_HOST:localhost}" | ||
556 | + port: "${TB_QUEUE_RABBIT_MQ_PORT:5672}" | ||
557 | + virtual_host: "${TB_QUEUE_RABBIT_MQ_VIRTUAL_HOST:/}" | ||
558 | + username: "${TB_QUEUE_RABBIT_MQ_USERNAME:YOUR_USERNAME}" | ||
559 | + password: "${TB_QUEUE_RABBIT_MQ_PASSWORD:YOUR_PASSWORD}" | ||
560 | + automatic_recovery_enabled: "${TB_QUEUE_RABBIT_MQ_AUTOMATIC_RECOVERY_ENABLED:false}" | ||
561 | + connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" | ||
562 | + handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" | ||
553 | partitions: | 563 | partitions: |
554 | hash_function_name: "${TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" | 564 | hash_function_name: "${TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" |
555 | virtual_nodes_size: "${TB_QUEUE_PARTITIONS_VIRTUAL_NODES_SIZE:16}" | 565 | virtual_nodes_size: "${TB_QUEUE_PARTITIONS_VIRTUAL_NODES_SIZE:16}" |
@@ -65,6 +65,10 @@ | @@ -65,6 +65,10 @@ | ||
65 | <artifactId>azure-servicebus</artifactId> | 65 | <artifactId>azure-servicebus</artifactId> |
66 | </dependency> | 66 | </dependency> |
67 | <dependency> | 67 | <dependency> |
68 | + <groupId>com.rabbitmq</groupId> | ||
69 | + <artifactId>amqp-client</artifactId> | ||
70 | + </dependency> | ||
71 | + <dependency> | ||
68 | <groupId>org.springframework</groupId> | 72 | <groupId>org.springframework</groupId> |
69 | <artifactId>spring-context-support</artifactId> | 73 | <artifactId>spring-context-support</artifactId> |
70 | </dependency> | 74 | </dependency> |
@@ -17,7 +17,6 @@ package org.thingsboard.server.queue.common; | @@ -17,7 +17,6 @@ package org.thingsboard.server.queue.common; | ||
17 | 17 | ||
18 | import lombok.Data; | 18 | import lombok.Data; |
19 | import org.thingsboard.server.queue.TbQueueMsg; | 19 | import org.thingsboard.server.queue.TbQueueMsg; |
20 | -import org.thingsboard.server.queue.TbQueueMsgHeaders; | ||
21 | 20 | ||
22 | import java.util.UUID; | 21 | import java.util.UUID; |
23 | 22 | ||
@@ -25,13 +24,7 @@ import java.util.UUID; | @@ -25,13 +24,7 @@ import java.util.UUID; | ||
25 | public class DefaultTbQueueMsg implements TbQueueMsg { | 24 | public class DefaultTbQueueMsg implements TbQueueMsg { |
26 | private final UUID key; | 25 | private final UUID key; |
27 | private final byte[] data; | 26 | private final byte[] data; |
28 | - private DefaultTbQueueMsgHeaders headers; | ||
29 | - | ||
30 | - | ||
31 | - public DefaultTbQueueMsg(UUID key, byte[] data) { | ||
32 | - this.key = key; | ||
33 | - this.data = data; | ||
34 | - } | 27 | + private final DefaultTbQueueMsgHeaders headers; |
35 | 28 | ||
36 | public DefaultTbQueueMsg(TbQueueMsg msg) { | 29 | public DefaultTbQueueMsg(TbQueueMsg msg) { |
37 | this.key = msg.getKey(); | 30 | this.key = msg.getKey(); |
@@ -20,7 +20,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -20,7 +20,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
20 | import com.google.common.util.concurrent.SettableFuture; | 20 | import com.google.common.util.concurrent.SettableFuture; |
21 | import lombok.Builder; | 21 | import lombok.Builder; |
22 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
23 | -import org.apache.kafka.common.errors.InterruptException; | 23 | +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
24 | import org.thingsboard.server.queue.TbQueueAdmin; | 24 | import org.thingsboard.server.queue.TbQueueAdmin; |
25 | import org.thingsboard.server.queue.TbQueueCallback; | 25 | import org.thingsboard.server.queue.TbQueueCallback; |
26 | import org.thingsboard.server.queue.TbQueueConsumer; | 26 | import org.thingsboard.server.queue.TbQueueConsumer; |
@@ -28,7 +28,6 @@ import org.thingsboard.server.queue.TbQueueMsg; | @@ -28,7 +28,6 @@ import org.thingsboard.server.queue.TbQueueMsg; | ||
28 | import org.thingsboard.server.queue.TbQueueMsgMetadata; | 28 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
29 | import org.thingsboard.server.queue.TbQueueProducer; | 29 | import org.thingsboard.server.queue.TbQueueProducer; |
30 | import org.thingsboard.server.queue.TbQueueRequestTemplate; | 30 | import org.thingsboard.server.queue.TbQueueRequestTemplate; |
31 | -import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | ||
32 | 31 | ||
33 | import java.util.List; | 32 | import java.util.List; |
34 | import java.util.UUID; | 33 | import java.util.UUID; |
@@ -128,10 +127,6 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response | @@ -128,10 +127,6 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response | ||
128 | }); | 127 | }); |
129 | nextCleanupMs = tickTs + maxRequestTimeout; | 128 | nextCleanupMs = tickTs + maxRequestTimeout; |
130 | } | 129 | } |
131 | - } catch (InterruptException ie) { | ||
132 | - if (!stopped) { | ||
133 | - log.warn("Fetching data from kafka was interrupted.", ie); | ||
134 | - } | ||
135 | } catch (Throwable e) { | 130 | } catch (Throwable e) { |
136 | log.warn("Failed to obtain responses from queue.", e); | 131 | log.warn("Failed to obtain responses from queue.", e); |
137 | try { | 132 | try { |
@@ -17,7 +17,6 @@ package org.thingsboard.server.queue.common; | @@ -17,7 +17,6 @@ package org.thingsboard.server.queue.common; | ||
17 | 17 | ||
18 | import lombok.Builder; | 18 | import lombok.Builder; |
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | -import org.apache.kafka.common.errors.InterruptException; | ||
21 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 20 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
22 | import org.thingsboard.server.queue.TbQueueConsumer; | 21 | import org.thingsboard.server.queue.TbQueueConsumer; |
23 | import org.thingsboard.server.queue.TbQueueHandler; | 22 | import org.thingsboard.server.queue.TbQueueHandler; |
@@ -133,10 +132,6 @@ public class DefaultTbQueueResponseTemplate<Request extends TbQueueMsg, Response | @@ -133,10 +132,6 @@ public class DefaultTbQueueResponseTemplate<Request extends TbQueueMsg, Response | ||
133 | } | 132 | } |
134 | }); | 133 | }); |
135 | requestTemplate.commit(); | 134 | requestTemplate.commit(); |
136 | - } catch (InterruptException ie) { | ||
137 | - if (!stopped) { | ||
138 | - log.warn("Fetching data from queue was interrupted.", ie); | ||
139 | - } | ||
140 | } catch (Throwable e) { | 135 | } catch (Throwable e) { |
141 | log.warn("Failed to obtain messages from queue.", e); | 136 | log.warn("Failed to obtain messages from queue.", e); |
142 | try { | 137 | try { |
common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.provider; | ||
17 | + | ||
18 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.common.msg.queue.ServiceType; | ||
21 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
22 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
23 | +import org.thingsboard.server.queue.TbQueueConsumer; | ||
24 | +import org.thingsboard.server.queue.TbQueueProducer; | ||
25 | +import org.thingsboard.server.queue.common.TbProtoQueueMsg; | ||
26 | +import org.thingsboard.server.queue.discovery.PartitionService; | ||
27 | +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; | ||
28 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; | ||
29 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; | ||
30 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; | ||
31 | +import org.thingsboard.server.queue.settings.TbQueueCoreSettings; | ||
32 | +import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | ||
33 | +import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; | ||
34 | +import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; | ||
35 | +import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; | ||
36 | + | ||
37 | +@Component | ||
38 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='monolith'") | ||
39 | +public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory { | ||
40 | + | ||
41 | + private final PartitionService partitionService; | ||
42 | + private final TbQueueCoreSettings coreSettings; | ||
43 | + private final TbServiceInfoProvider serviceInfoProvider; | ||
44 | + private final TbQueueRuleEngineSettings ruleEngineSettings; | ||
45 | + private final TbQueueTransportApiSettings transportApiSettings; | ||
46 | + private final TbQueueTransportNotificationSettings transportNotificationSettings; | ||
47 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
48 | + private final TbQueueAdmin admin; | ||
49 | + | ||
50 | + public RabbitMqMonolithQueueFactory(PartitionService partitionService, TbQueueCoreSettings coreSettings, | ||
51 | + TbQueueRuleEngineSettings ruleEngineSettings, | ||
52 | + TbServiceInfoProvider serviceInfoProvider, | ||
53 | + TbQueueTransportApiSettings transportApiSettings, | ||
54 | + TbQueueTransportNotificationSettings transportNotificationSettings, | ||
55 | + TbRabbitMqSettings rabbitMqSettings, | ||
56 | + TbQueueAdmin admin) { | ||
57 | + this.partitionService = partitionService; | ||
58 | + this.coreSettings = coreSettings; | ||
59 | + this.serviceInfoProvider = serviceInfoProvider; | ||
60 | + this.ruleEngineSettings = ruleEngineSettings; | ||
61 | + this.transportApiSettings = transportApiSettings; | ||
62 | + this.transportNotificationSettings = transportNotificationSettings; | ||
63 | + this.rabbitMqSettings = rabbitMqSettings; | ||
64 | + this.admin = admin; | ||
65 | + } | ||
66 | + | ||
67 | + @Override | ||
68 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToTransportMsg>> createTransportNotificationsMsgProducer() { | ||
69 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, transportNotificationSettings.getNotificationsTopic()); | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> createRuleEngineMsgProducer() { | ||
74 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic()); | ||
75 | + } | ||
76 | + | ||
77 | + @Override | ||
78 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { | ||
79 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic()); | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> createTbCoreMsgProducer() { | ||
84 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { | ||
89 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> createToRuleEngineMsgConsumer(TbRuleEngineQueueConfiguration configuration) { | ||
94 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic(), | ||
95 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
96 | + } | ||
97 | + | ||
98 | + @Override | ||
99 | + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { | ||
100 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, | ||
101 | + partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), | ||
102 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
103 | + } | ||
104 | + | ||
105 | + @Override | ||
106 | + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToCoreMsg>> createToCoreMsgConsumer() { | ||
107 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic(), | ||
108 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
109 | + } | ||
110 | + | ||
111 | + @Override | ||
112 | + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { | ||
113 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, | ||
114 | + partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), | ||
115 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
116 | + } | ||
117 | + | ||
118 | + @Override | ||
119 | + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg>> createTransportApiRequestConsumer() { | ||
120 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getRequestsTopic(), | ||
121 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
122 | + } | ||
123 | + | ||
124 | + @Override | ||
125 | + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.TransportApiResponseMsg>> createTransportApiResponseProducer() { | ||
126 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getResponsesTopic()); | ||
127 | + } | ||
128 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.provider; | ||
17 | + | ||
18 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.common.msg.queue.ServiceType; | ||
21 | +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; | ||
22 | +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; | ||
23 | +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | ||
24 | +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; | ||
25 | +import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | ||
26 | +import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | ||
27 | +import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; | ||
28 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
29 | +import org.thingsboard.server.queue.TbQueueConsumer; | ||
30 | +import org.thingsboard.server.queue.TbQueueProducer; | ||
31 | +import org.thingsboard.server.queue.common.TbProtoQueueMsg; | ||
32 | +import org.thingsboard.server.queue.discovery.PartitionService; | ||
33 | +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; | ||
34 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; | ||
35 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; | ||
36 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; | ||
37 | +import org.thingsboard.server.queue.settings.TbQueueCoreSettings; | ||
38 | +import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | ||
39 | +import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; | ||
40 | + | ||
41 | +@Component | ||
42 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-core'") | ||
43 | +public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { | ||
44 | + | ||
45 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
46 | + private final TbQueueRuleEngineSettings ruleEngineSettings; | ||
47 | + private final TbQueueCoreSettings coreSettings; | ||
48 | + private final TbQueueTransportApiSettings transportApiSettings; | ||
49 | + private final PartitionService partitionService; | ||
50 | + private final TbServiceInfoProvider serviceInfoProvider; | ||
51 | + private final TbQueueAdmin admin; | ||
52 | + | ||
53 | + public RabbitMqTbCoreQueueFactory(TbRabbitMqSettings rabbitMqSettings, | ||
54 | + TbQueueCoreSettings coreSettings, | ||
55 | + TbQueueTransportApiSettings transportApiSettings, | ||
56 | + TbQueueRuleEngineSettings ruleEngineSettings, | ||
57 | + PartitionService partitionService, | ||
58 | + TbServiceInfoProvider serviceInfoProvider, | ||
59 | + TbQueueAdmin admin) { | ||
60 | + this.rabbitMqSettings = rabbitMqSettings; | ||
61 | + this.coreSettings = coreSettings; | ||
62 | + this.transportApiSettings = transportApiSettings; | ||
63 | + this.ruleEngineSettings = ruleEngineSettings; | ||
64 | + this.partitionService = partitionService; | ||
65 | + this.serviceInfoProvider = serviceInfoProvider; | ||
66 | + this.admin = admin; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { | ||
71 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { | ||
76 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
80 | + public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { | ||
81 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic()); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
85 | + public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { | ||
86 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
87 | + } | ||
88 | + | ||
89 | + @Override | ||
90 | + public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { | ||
91 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
92 | + } | ||
93 | + | ||
94 | + @Override | ||
95 | + public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { | ||
96 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic(), | ||
97 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
98 | + } | ||
99 | + | ||
100 | + @Override | ||
101 | + public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { | ||
102 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, | ||
103 | + partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), | ||
104 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
105 | + } | ||
106 | + | ||
107 | + @Override | ||
108 | + public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { | ||
109 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getRequestsTopic(), | ||
110 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
111 | + } | ||
112 | + | ||
113 | + @Override | ||
114 | + public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { | ||
115 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
116 | + } | ||
117 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.provider; | ||
17 | + | ||
18 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.thingsboard.server.common.msg.queue.ServiceType; | ||
21 | +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; | ||
22 | +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; | ||
23 | +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | ||
24 | +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; | ||
25 | +import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | ||
26 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
27 | +import org.thingsboard.server.queue.TbQueueConsumer; | ||
28 | +import org.thingsboard.server.queue.TbQueueProducer; | ||
29 | +import org.thingsboard.server.queue.common.TbProtoQueueMsg; | ||
30 | +import org.thingsboard.server.queue.discovery.PartitionService; | ||
31 | +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; | ||
32 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; | ||
33 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; | ||
34 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; | ||
35 | +import org.thingsboard.server.queue.settings.TbQueueCoreSettings; | ||
36 | +import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | ||
37 | +import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; | ||
38 | + | ||
39 | +@Component | ||
40 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-rule-engine'") | ||
41 | +public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { | ||
42 | + | ||
43 | + private final PartitionService partitionService; | ||
44 | + private final TbQueueCoreSettings coreSettings; | ||
45 | + private final TbServiceInfoProvider serviceInfoProvider; | ||
46 | + private final TbQueueRuleEngineSettings ruleEngineSettings; | ||
47 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
48 | + private final TbQueueAdmin admin; | ||
49 | + | ||
50 | + public RabbitMqTbRuleEngineQueueFactory(PartitionService partitionService, TbQueueCoreSettings coreSettings, | ||
51 | + TbQueueRuleEngineSettings ruleEngineSettings, | ||
52 | + TbServiceInfoProvider serviceInfoProvider, | ||
53 | + TbRabbitMqSettings rabbitMqSettings, | ||
54 | + TbQueueAdmin admin) { | ||
55 | + this.partitionService = partitionService; | ||
56 | + this.coreSettings = coreSettings; | ||
57 | + this.serviceInfoProvider = serviceInfoProvider; | ||
58 | + this.ruleEngineSettings = ruleEngineSettings; | ||
59 | + this.rabbitMqSettings = rabbitMqSettings; | ||
60 | + this.admin = admin; | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { | ||
65 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { | ||
70 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
71 | + } | ||
72 | + | ||
73 | + @Override | ||
74 | + public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { | ||
75 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic()); | ||
76 | + } | ||
77 | + | ||
78 | + @Override | ||
79 | + public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { | ||
80 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
81 | + } | ||
82 | + | ||
83 | + @Override | ||
84 | + public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { | ||
85 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, coreSettings.getTopic()); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(TbRuleEngineQueueConfiguration configuration) { | ||
90 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, ruleEngineSettings.getTopic(), | ||
91 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
92 | + } | ||
93 | + | ||
94 | + @Override | ||
95 | + public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { | ||
96 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, | ||
97 | + partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), | ||
98 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
99 | + } | ||
100 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.provider; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
20 | +import org.springframework.stereotype.Component; | ||
21 | +import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; | ||
22 | +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | ||
23 | +import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | ||
24 | +import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | ||
25 | +import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; | ||
26 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
27 | +import org.thingsboard.server.queue.TbQueueConsumer; | ||
28 | +import org.thingsboard.server.queue.TbQueueProducer; | ||
29 | +import org.thingsboard.server.queue.TbQueueRequestTemplate; | ||
30 | +import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; | ||
31 | +import org.thingsboard.server.queue.common.TbProtoQueueMsg; | ||
32 | +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; | ||
33 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; | ||
34 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; | ||
35 | +import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; | ||
36 | +import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; | ||
37 | +import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; | ||
38 | + | ||
39 | +@Component | ||
40 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && ('${service.type:null}'=='monolith' || '${service.type:null}'=='tb-transport')") | ||
41 | +@Slf4j | ||
42 | +public class RabbitMqTransportQueueFactory implements TbTransportQueueFactory { | ||
43 | + private final TbQueueTransportApiSettings transportApiSettings; | ||
44 | + private final TbQueueTransportNotificationSettings transportNotificationSettings; | ||
45 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
46 | + private final TbQueueAdmin admin; | ||
47 | + private final TbServiceInfoProvider serviceInfoProvider; | ||
48 | + | ||
49 | + public RabbitMqTransportQueueFactory(TbQueueTransportApiSettings transportApiSettings, | ||
50 | + TbQueueTransportNotificationSettings transportNotificationSettings, | ||
51 | + TbRabbitMqSettings rabbitMqSettings, | ||
52 | + TbServiceInfoProvider serviceInfoProvider, | ||
53 | + TbQueueAdmin admin) { | ||
54 | + this.transportApiSettings = transportApiSettings; | ||
55 | + this.transportNotificationSettings = transportNotificationSettings; | ||
56 | + this.rabbitMqSettings = rabbitMqSettings; | ||
57 | + this.admin = admin; | ||
58 | + this.serviceInfoProvider = serviceInfoProvider; | ||
59 | + } | ||
60 | + | ||
61 | + @Override | ||
62 | + public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { | ||
63 | + TbRabbitMqProducerTemplate<TbProtoQueueMsg<TransportApiRequestMsg>> producerTemplate = | ||
64 | + new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getRequestsTopic()); | ||
65 | + | ||
66 | + TbRabbitMqConsumerTemplate<TbProtoQueueMsg<TransportApiResponseMsg>> consumerTemplate = | ||
67 | + new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, | ||
68 | + transportApiSettings.getResponsesTopic() + "." + serviceInfoProvider.getServiceId(), | ||
69 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
70 | + | ||
71 | + DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder | ||
72 | + <TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); | ||
73 | + templateBuilder.queueAdmin(admin); | ||
74 | + templateBuilder.requestTemplate(producerTemplate); | ||
75 | + templateBuilder.responseTemplate(consumerTemplate); | ||
76 | + templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); | ||
77 | + templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); | ||
78 | + templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); | ||
79 | + return templateBuilder.build(); | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { | ||
84 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getRequestsTopic()); | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { | ||
89 | + return new TbRabbitMqProducerTemplate<>(admin, rabbitMqSettings, transportApiSettings.getRequestsTopic()); | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { | ||
94 | + return new TbRabbitMqConsumerTemplate<>(admin, rabbitMqSettings, transportNotificationSettings.getNotificationsTopic() + "." + serviceInfoProvider.getServiceId(), | ||
95 | + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); | ||
96 | + } | ||
97 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.rabbitmq; | ||
17 | +import com.rabbitmq.client.Channel; | ||
18 | +import com.rabbitmq.client.Connection; | ||
19 | + | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
22 | +import org.springframework.stereotype.Component; | ||
23 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
24 | + | ||
25 | +import javax.annotation.PreDestroy; | ||
26 | +import java.io.IOException; | ||
27 | +import java.util.concurrent.TimeoutException; | ||
28 | + | ||
29 | +@Slf4j | ||
30 | +@Component | ||
31 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'") | ||
32 | +public class TbRabbitMqAdmin implements TbQueueAdmin { | ||
33 | + | ||
34 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
35 | + private final Channel channel; | ||
36 | + private final Connection connection; | ||
37 | + | ||
38 | + public TbRabbitMqAdmin(TbRabbitMqSettings rabbitMqSettings) { | ||
39 | + this.rabbitMqSettings = rabbitMqSettings; | ||
40 | + | ||
41 | + try { | ||
42 | + connection = rabbitMqSettings.getConnectionFactory().newConnection(); | ||
43 | + } catch (IOException | TimeoutException e) { | ||
44 | + log.error("Failed to create connection.", e); | ||
45 | + throw new RuntimeException("Failed to create connection.", e); | ||
46 | + } | ||
47 | + | ||
48 | + try { | ||
49 | + channel = connection.createChannel(); | ||
50 | + } catch (IOException e) { | ||
51 | + log.error("Failed to create chanel.", e); | ||
52 | + throw new RuntimeException("Failed to create chanel.", e); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + public void createTopicIfNotExists(String topic) { | ||
58 | + try { | ||
59 | + channel.queueDeclare(topic, false, false, false, null); | ||
60 | + } catch (IOException e) { | ||
61 | + log.error("Failed to bind queue: [{}]", topic, e); | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | + @PreDestroy | ||
66 | + private void destroy() { | ||
67 | + if (channel != null) { | ||
68 | + try { | ||
69 | + channel.close(); | ||
70 | + } catch (IOException | TimeoutException e) { | ||
71 | + log.error("Failed to close Chanel.", e); | ||
72 | + } | ||
73 | + } | ||
74 | + if (connection != null) { | ||
75 | + try { | ||
76 | + connection.close(); | ||
77 | + } catch (IOException e) { | ||
78 | + log.error("Failed to close Connection.", e); | ||
79 | + } | ||
80 | + } | ||
81 | + } | ||
82 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.rabbitmq; | ||
17 | + | ||
18 | +import com.google.gson.Gson; | ||
19 | +import com.google.protobuf.InvalidProtocolBufferException; | ||
20 | +import com.rabbitmq.client.Channel; | ||
21 | +import com.rabbitmq.client.Connection; | ||
22 | +import com.rabbitmq.client.GetResponse; | ||
23 | +import lombok.extern.slf4j.Slf4j; | ||
24 | +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | ||
25 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
26 | +import org.thingsboard.server.queue.TbQueueConsumer; | ||
27 | +import org.thingsboard.server.queue.TbQueueMsg; | ||
28 | +import org.thingsboard.server.queue.TbQueueMsgDecoder; | ||
29 | +import org.thingsboard.server.queue.common.DefaultTbQueueMsg; | ||
30 | + | ||
31 | +import java.io.IOException; | ||
32 | +import java.util.Collections; | ||
33 | +import java.util.List; | ||
34 | +import java.util.Objects; | ||
35 | +import java.util.Set; | ||
36 | +import java.util.concurrent.TimeoutException; | ||
37 | +import java.util.stream.Collectors; | ||
38 | + | ||
39 | +@Slf4j | ||
40 | +public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> implements TbQueueConsumer<T> { | ||
41 | + | ||
42 | + private final Gson gson = new Gson(); | ||
43 | + private final TbQueueAdmin admin; | ||
44 | + private final String topic; | ||
45 | + private final TbQueueMsgDecoder<T> decoder; | ||
46 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
47 | + private final Channel channel; | ||
48 | + private final Connection connection; | ||
49 | + | ||
50 | + private volatile Set<TopicPartitionInfo> partitions; | ||
51 | + private volatile boolean subscribed; | ||
52 | + private volatile Set<String> queues; | ||
53 | + private volatile boolean stopped; | ||
54 | + | ||
55 | + public TbRabbitMqConsumerTemplate(TbQueueAdmin admin, TbRabbitMqSettings rabbitMqSettings, String topic, TbQueueMsgDecoder<T> decoder) { | ||
56 | + this.admin = admin; | ||
57 | + this.decoder = decoder; | ||
58 | + this.topic = topic; | ||
59 | + this.rabbitMqSettings = rabbitMqSettings; | ||
60 | + try { | ||
61 | + connection = rabbitMqSettings.getConnectionFactory().newConnection(); | ||
62 | + } catch (IOException | TimeoutException e) { | ||
63 | + log.error("Failed to create connection.", e); | ||
64 | + throw new RuntimeException("Failed to create connection.", e); | ||
65 | + } | ||
66 | + | ||
67 | + try { | ||
68 | + channel = connection.createChannel(); | ||
69 | + } catch (IOException e) { | ||
70 | + log.error("Failed to create chanel.", e); | ||
71 | + throw new RuntimeException("Failed to create chanel.", e); | ||
72 | + } | ||
73 | + stopped = false; | ||
74 | + } | ||
75 | + | ||
76 | + @Override | ||
77 | + public String getTopic() { | ||
78 | + return topic; | ||
79 | + } | ||
80 | + | ||
81 | + @Override | ||
82 | + public void subscribe() { | ||
83 | + partitions = Collections.singleton(new TopicPartitionInfo(topic, null, null, true)); | ||
84 | + subscribed = false; | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public void subscribe(Set<TopicPartitionInfo> partitions) { | ||
89 | + this.partitions = partitions; | ||
90 | + subscribed = false; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public void unsubscribe() { | ||
95 | + stopped = true; | ||
96 | + if (channel != null) { | ||
97 | + try { | ||
98 | + channel.close(); | ||
99 | + } catch (IOException | TimeoutException e) { | ||
100 | + log.error("Failed to close the channel."); | ||
101 | + } | ||
102 | + } | ||
103 | + if (connection != null) { | ||
104 | + try { | ||
105 | + connection.close(); | ||
106 | + } catch (IOException e) { | ||
107 | + log.error("Failed to close the connection."); | ||
108 | + } | ||
109 | + } | ||
110 | + } | ||
111 | + | ||
112 | + @Override | ||
113 | + public List<T> poll(long durationInMillis) { | ||
114 | + if (!subscribed && partitions == null) { | ||
115 | + try { | ||
116 | + Thread.sleep(durationInMillis); | ||
117 | + } catch (InterruptedException e) { | ||
118 | + log.debug("Failed to await subscription", e); | ||
119 | + } | ||
120 | + } else { | ||
121 | + if (!subscribed) { | ||
122 | + queues = partitions.stream() | ||
123 | + .map(TopicPartitionInfo::getFullTopicName) | ||
124 | + .collect(Collectors.toSet()); | ||
125 | + | ||
126 | + queues.forEach(admin::createTopicIfNotExists); | ||
127 | + subscribed = true; | ||
128 | + } | ||
129 | + | ||
130 | + List<T> result = queues.stream() | ||
131 | + .map(queue -> { | ||
132 | + try { | ||
133 | + return channel.basicGet(queue, false); | ||
134 | + } catch (IOException e) { | ||
135 | + log.error("Failed to get messages from queue: [{}]", queue); | ||
136 | + throw new RuntimeException("Failed to get messages from queue.", e); | ||
137 | + } | ||
138 | + }).filter(Objects::nonNull).map(message -> { | ||
139 | + try { | ||
140 | + return decode(message); | ||
141 | + } catch (InvalidProtocolBufferException e) { | ||
142 | + log.error("Failed to decode message: [{}].", message); | ||
143 | + throw new RuntimeException("Failed to decode message.", e); | ||
144 | + } | ||
145 | + }).collect(Collectors.toList()); | ||
146 | + if (result.size() > 0) { | ||
147 | + return result; | ||
148 | + } | ||
149 | + } | ||
150 | + try { | ||
151 | + Thread.sleep(durationInMillis); | ||
152 | + } catch (InterruptedException e) { | ||
153 | + if (!stopped) { | ||
154 | + log.error("Failed to wait.", e); | ||
155 | + } | ||
156 | + } | ||
157 | + return Collections.emptyList(); | ||
158 | + } | ||
159 | + | ||
160 | + @Override | ||
161 | + public void commit() { | ||
162 | + try { | ||
163 | + channel.basicAck(0, true); | ||
164 | + } catch (IOException e) { | ||
165 | + log.error("Failed to ack messages.", e); | ||
166 | + } | ||
167 | + } | ||
168 | + | ||
169 | + public T decode(GetResponse message) throws InvalidProtocolBufferException { | ||
170 | + DefaultTbQueueMsg msg = gson.fromJson(new String(message.getBody()), DefaultTbQueueMsg.class); | ||
171 | + return decoder.decode(msg); | ||
172 | + } | ||
173 | +} |
common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqProducerTemplate.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.rabbitmq; | ||
17 | + | ||
18 | +import com.google.common.util.concurrent.ListeningExecutorService; | ||
19 | +import com.google.common.util.concurrent.MoreExecutors; | ||
20 | +import com.google.gson.Gson; | ||
21 | +import com.rabbitmq.client.AMQP; | ||
22 | +import com.rabbitmq.client.Channel; | ||
23 | +import com.rabbitmq.client.Connection; | ||
24 | +import lombok.extern.slf4j.Slf4j; | ||
25 | +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | ||
26 | +import org.thingsboard.server.queue.TbQueueAdmin; | ||
27 | +import org.thingsboard.server.queue.TbQueueCallback; | ||
28 | +import org.thingsboard.server.queue.TbQueueMsg; | ||
29 | +import org.thingsboard.server.queue.TbQueueProducer; | ||
30 | +import org.thingsboard.server.queue.common.DefaultTbQueueMsg; | ||
31 | + | ||
32 | +import java.io.IOException; | ||
33 | +import java.util.concurrent.Executors; | ||
34 | +import java.util.concurrent.TimeoutException; | ||
35 | + | ||
36 | +@Slf4j | ||
37 | +public class TbRabbitMqProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { | ||
38 | + private final String defaultTopic; | ||
39 | + private final Gson gson = new Gson(); | ||
40 | + private final TbQueueAdmin admin; | ||
41 | + private final TbRabbitMqSettings rabbitMqSettings; | ||
42 | + private ListeningExecutorService producerExecutor; | ||
43 | + private final Channel channel; | ||
44 | + private final Connection connection; | ||
45 | + | ||
46 | + public TbRabbitMqProducerTemplate(TbQueueAdmin admin, TbRabbitMqSettings rabbitMqSettings, String defaultTopic) { | ||
47 | + this.admin = admin; | ||
48 | + this.defaultTopic = defaultTopic; | ||
49 | + this.rabbitMqSettings = rabbitMqSettings; | ||
50 | + producerExecutor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); | ||
51 | + try { | ||
52 | + connection = rabbitMqSettings.getConnectionFactory().newConnection(); | ||
53 | + } catch (IOException | TimeoutException e) { | ||
54 | + log.error("Failed to create connection.", e); | ||
55 | + throw new RuntimeException("Failed to create connection.", e); | ||
56 | + } | ||
57 | + | ||
58 | + try { | ||
59 | + channel = connection.createChannel(); | ||
60 | + } catch (IOException e) { | ||
61 | + log.error("Failed to create chanel.", e); | ||
62 | + throw new RuntimeException("Failed to create chanel.", e); | ||
63 | + } | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + public void init() { | ||
68 | + | ||
69 | + } | ||
70 | + | ||
71 | + @Override | ||
72 | + public String getDefaultTopic() { | ||
73 | + return defaultTopic; | ||
74 | + } | ||
75 | + | ||
76 | + @Override | ||
77 | + public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { | ||
78 | + AMQP.BasicProperties properties = new AMQP.BasicProperties(); | ||
79 | + try { | ||
80 | + channel.basicPublish(rabbitMqSettings.getExchangeName(), tpi.getFullTopicName(), properties, gson.toJson(new DefaultTbQueueMsg(msg)).getBytes()); | ||
81 | + if (callback != null) { | ||
82 | + callback.onSuccess(null); | ||
83 | + } | ||
84 | + } catch (IOException e) { | ||
85 | + log.error("Failed publish message: [{}].", msg, e); | ||
86 | + if (callback != null) { | ||
87 | + callback.onFailure(e); | ||
88 | + } | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
92 | + @Override | ||
93 | + public void stop() { | ||
94 | + if (producerExecutor != null) { | ||
95 | + producerExecutor.shutdownNow(); | ||
96 | + } | ||
97 | + if (channel != null) { | ||
98 | + try { | ||
99 | + channel.close(); | ||
100 | + } catch (IOException | TimeoutException e) { | ||
101 | + log.error("Failed to close the channel."); | ||
102 | + } | ||
103 | + } | ||
104 | + if (connection != null) { | ||
105 | + try { | ||
106 | + connection.close(); | ||
107 | + } catch (IOException e) { | ||
108 | + log.error("Failed to close the connection."); | ||
109 | + } | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.queue.rabbitmq; | ||
17 | + | ||
18 | +import com.rabbitmq.client.ConnectionFactory; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.springframework.beans.factory.annotation.Value; | ||
22 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
23 | +import org.springframework.stereotype.Component; | ||
24 | + | ||
25 | +import javax.annotation.PostConstruct; | ||
26 | + | ||
27 | +@Slf4j | ||
28 | +@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'") | ||
29 | +@Component | ||
30 | +@Data | ||
31 | +public class TbRabbitMqSettings { | ||
32 | + @Value("${queue.rabbitmq.exchange_name:}") | ||
33 | + private String exchangeName; | ||
34 | + @Value("${queue.rabbitmq.host:}") | ||
35 | + private String host; | ||
36 | + @Value("${queue.rabbitmq.port:}") | ||
37 | + private int port; | ||
38 | + @Value("${queue.rabbitmq.virtual_host:}") | ||
39 | + private String virtualHost; | ||
40 | + @Value("${queue.rabbitmq.username:}") | ||
41 | + private String username; | ||
42 | + @Value("${queue.rabbitmq.password:}") | ||
43 | + private String password; | ||
44 | + @Value("${queue.rabbitmq.automatic_recovery_enabled:}") | ||
45 | + private boolean automaticRecoveryEnabled; | ||
46 | + @Value("${queue.rabbitmq.connection_timeout:}") | ||
47 | + private int connectionTimeout; | ||
48 | + @Value("${queue.rabbitmq.handshake_timeout:}") | ||
49 | + private int handshakeTimeout; | ||
50 | + | ||
51 | + private ConnectionFactory connectionFactory; | ||
52 | + | ||
53 | + @PostConstruct | ||
54 | + private void init() { | ||
55 | + connectionFactory = new ConnectionFactory(); | ||
56 | + connectionFactory.setHost(host); | ||
57 | + connectionFactory.setPort(port); | ||
58 | + connectionFactory.setVirtualHost(virtualHost); | ||
59 | + connectionFactory.setUsername(username); | ||
60 | + connectionFactory.setPassword(password); | ||
61 | + connectionFactory.setAutomaticRecoveryEnabled(automaticRecoveryEnabled); | ||
62 | + connectionFactory.setConnectionTimeout(connectionTimeout); | ||
63 | + connectionFactory.setHandshakeTimeout(handshakeTimeout); | ||
64 | + } | ||
65 | +} |
@@ -78,7 +78,7 @@ public class TbAwsSqsProducerTemplate<T extends TbQueueMsg> implements TbQueuePr | @@ -78,7 +78,7 @@ public class TbAwsSqsProducerTemplate<T extends TbQueueMsg> implements TbQueuePr | ||
78 | public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { | 78 | public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
79 | SendMessageRequest sendMsgRequest = new SendMessageRequest(); | 79 | SendMessageRequest sendMsgRequest = new SendMessageRequest(); |
80 | sendMsgRequest.withQueueUrl(getQueueUrl(tpi.getFullTopicName())); | 80 | sendMsgRequest.withQueueUrl(getQueueUrl(tpi.getFullTopicName())); |
81 | - sendMsgRequest.withMessageBody(gson.toJson(new DefaultTbQueueMsg(msg.getKey(), msg.getData()))); | 81 | + sendMsgRequest.withMessageBody(gson.toJson(new DefaultTbQueueMsg(msg))); |
82 | 82 | ||
83 | sendMsgRequest.withMessageGroupId(msg.getKey().toString()); | 83 | sendMsgRequest.withMessageGroupId(msg.getKey().toString()); |
84 | ListenableFuture<SendMessageResult> future = producerExecutor.submit(() -> sqsClient.sendMessage(sendMsgRequest)); | 84 | ListenableFuture<SendMessageResult> future = producerExecutor.submit(() -> sqsClient.sendMessage(sendMsgRequest)); |
@@ -88,6 +88,16 @@ queue: | @@ -88,6 +88,16 @@ queue: | ||
88 | sas_key_name: "${TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME:YOUR_SAS_KEY_NAME}" | 88 | sas_key_name: "${TB_QUEUE_SERVICE_BUS_SAS_KEY_NAME:YOUR_SAS_KEY_NAME}" |
89 | sas_key: "${TB_QUEUE_SERVICE_BUS_SAS_KEY:YOUR_SAS_KEY}" | 89 | sas_key: "${TB_QUEUE_SERVICE_BUS_SAS_KEY:YOUR_SAS_KEY}" |
90 | max_messages: "${TB_QUEUE_SERVICE_BUS_MAX_MESSAGES:1000}" | 90 | max_messages: "${TB_QUEUE_SERVICE_BUS_MAX_MESSAGES:1000}" |
91 | + rabbitmq: | ||
92 | + exchange_name: "${TB_QUEUE_RABBIT_MQ_EXCHANGE_NAME:}" | ||
93 | + host: "${TB_QUEUE_RABBIT_MQ_HOST:localhost}" | ||
94 | + port: "${TB_QUEUE_RABBIT_MQ_PORT:5672}" | ||
95 | + virtual_host: "${TB_QUEUE_RABBIT_MQ_VIRTUAL_HOST:/}" | ||
96 | + username: "${TB_QUEUE_RABBIT_MQ_USERNAME:YOUR_USERNAME}" | ||
97 | + password: "${TB_QUEUE_RABBIT_MQ_PASSWORD:YOUR_PASSWORD}" | ||
98 | + automatic_recovery_enabled: "${TB_QUEUE_RABBIT_MQ_AUTOMATIC_RECOVERY_ENABLED:false}" | ||
99 | + connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" | ||
100 | + handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" | ||
91 | partitions: | 101 | partitions: |
92 | hash_function_name: "${TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" | 102 | hash_function_name: "${TB_QUEUE_PARTITIONS_HASH_FUNCTION_NAME:murmur3_128}" |
93 | virtual_nodes_size: "${TB_QUEUE_PARTITIONS_VIRTUAL_NODES_SIZE:16}" | 103 | virtual_nodes_size: "${TB_QUEUE_PARTITIONS_VIRTUAL_NODES_SIZE:16}" |