Commit 4fb309c37ea5854b1c7650c73b48db2bd86d5d56
1 parent
12973cec
moved kafka from service.js to own module
Showing
7 changed files
with
152 additions
and
102 deletions
@@ -46,17 +46,17 @@ import java.util.concurrent.atomic.AtomicInteger; | @@ -46,17 +46,17 @@ import java.util.concurrent.atomic.AtomicInteger; | ||
46 | @Service | 46 | @Service |
47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { | 47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { |
48 | 48 | ||
49 | - @Value("${js.remote.max_requests_timeout}") | 49 | + @Value("${queue.js.max_requests_timeout}") |
50 | private long maxRequestsTimeout; | 50 | private long maxRequestsTimeout; |
51 | 51 | ||
52 | @Getter | 52 | @Getter |
53 | - @Value("${js.remote.max_errors}") | 53 | +// @Value("${queue.js.max_errors}") |
54 | private int maxErrors; | 54 | private int maxErrors; |
55 | 55 | ||
56 | - @Value("${js.remote.max_black_list_duration_sec:60}") | 56 | + @Value("${queue.js.max_black_list_duration_sec:60}") |
57 | private int maxBlackListDurationSec; | 57 | private int maxBlackListDurationSec; |
58 | 58 | ||
59 | - @Value("${js.remote.stats.enabled:false}") | 59 | + @Value("${queue.js.stats.enabled:false}") |
60 | private boolean statsEnabled; | 60 | private boolean statsEnabled; |
61 | 61 | ||
62 | private final AtomicInteger kafkaPushedMsgs = new AtomicInteger(0); | 62 | private final AtomicInteger kafkaPushedMsgs = new AtomicInteger(0); |
@@ -65,7 +65,7 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -65,7 +65,7 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
65 | private final AtomicInteger kafkaFailedMsgs = new AtomicInteger(0); | 65 | private final AtomicInteger kafkaFailedMsgs = new AtomicInteger(0); |
66 | private final AtomicInteger kafkaTimeoutMsgs = new AtomicInteger(0); | 66 | private final AtomicInteger kafkaTimeoutMsgs = new AtomicInteger(0); |
67 | 67 | ||
68 | - @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") | 68 | +// @Scheduled(fixedDelayString = "${queue.js.stats.print_interval_ms}") |
69 | public void printStats() { | 69 | public void printStats() { |
70 | if (statsEnabled) { | 70 | if (statsEnabled) { |
71 | int pushedMsgs = kafkaPushedMsgs.getAndSet(0); | 71 | int pushedMsgs = kafkaPushedMsgs.getAndSet(0); |
@@ -415,7 +415,7 @@ state: | @@ -415,7 +415,7 @@ state: | ||
415 | persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}" | 415 | persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}" |
416 | 416 | ||
417 | js: | 417 | js: |
418 | - evaluator: "${JS_EVALUATOR:local}" # local/remote | 418 | + evaluator: "${JS_EVALUATOR:remote}" # local/remote |
419 | # Built-in JVM JavaScript environment properties | 419 | # Built-in JVM JavaScript environment properties |
420 | local: | 420 | local: |
421 | # Use Sandboxed (secured) JVM JavaScript environment | 421 | # Use Sandboxed (secured) JVM JavaScript environment |
@@ -582,9 +582,9 @@ queue: | @@ -582,9 +582,9 @@ queue: | ||
582 | print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" | 582 | print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" |
583 | js: | 583 | js: |
584 | # JS Eval request topic | 584 | # JS Eval request topic |
585 | - request_topic: "${REMOTE_JS_EVAL_REQUEST_TOPIC:js_eval.requests}" | 585 | + request_topic: "${REMOTE_JS_EVAL_REQUEST_TOPIC:js.eval.requests}" |
586 | # JS Eval responses topic prefix that is combined with node id | 586 | # JS Eval responses topic prefix that is combined with node id |
587 | - response_topic_prefix: "${REMOTE_JS_EVAL_RESPONSE_TOPIC:js_eval.responses}" | 587 | + response_topic_prefix: "${REMOTE_JS_EVAL_RESPONSE_TOPIC:js.eval.responses}" |
588 | # JS Eval max pending requests | 588 | # JS Eval max pending requests |
589 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" | 589 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" |
590 | # JS Eval max request timeout | 590 | # JS Eval max request timeout |
@@ -31,6 +31,7 @@ const useSandbox = config.get('script.use_sandbox') === 'true'; | @@ -31,6 +31,7 @@ const useSandbox = config.get('script.use_sandbox') === 'true'; | ||
31 | const maxActiveScripts = Number(config.get('script.max_active_scripts')); | 31 | const maxActiveScripts = Number(config.get('script.max_active_scripts')); |
32 | 32 | ||
33 | function JsInvokeMessageProcessor(producer) { | 33 | function JsInvokeMessageProcessor(producer) { |
34 | + console.log("Kafka Producer:", producer); | ||
34 | this.producer = producer; | 35 | this.producer = producer; |
35 | this.executor = new JsExecutor(useSandbox); | 36 | this.executor = new JsExecutor(useSandbox); |
36 | this.scriptMap = {}; | 37 | this.scriptMap = {}; |
@@ -144,17 +145,17 @@ JsInvokeMessageProcessor.prototype.processReleaseRequest = function(requestId, r | @@ -144,17 +145,17 @@ JsInvokeMessageProcessor.prototype.processReleaseRequest = function(requestId, r | ||
144 | JsInvokeMessageProcessor.prototype.sendResponse = function (requestId, responseTopic, scriptId, compileResponse, invokeResponse, releaseResponse) { | 145 | JsInvokeMessageProcessor.prototype.sendResponse = function (requestId, responseTopic, scriptId, compileResponse, invokeResponse, releaseResponse) { |
145 | var remoteResponse = createRemoteResponse(requestId, compileResponse, invokeResponse, releaseResponse); | 146 | var remoteResponse = createRemoteResponse(requestId, compileResponse, invokeResponse, releaseResponse); |
146 | var rawResponse = Buffer.from(JSON.stringify(remoteResponse), 'utf8'); | 147 | var rawResponse = Buffer.from(JSON.stringify(remoteResponse), 'utf8'); |
147 | - this.producer.send( | ||
148 | - { | ||
149 | - topic: responseTopic, | ||
150 | - messages: [ | ||
151 | - { | ||
152 | - key: scriptId, | ||
153 | - value: rawResponse, | ||
154 | - headers: headers | ||
155 | - } | ||
156 | - ] | ||
157 | - } | 148 | + this.producer.send(responseTopic, scriptId, rawResponse, headers |
149 | + // { | ||
150 | + // topic: responseTopic, | ||
151 | + // messages: [ | ||
152 | + // { | ||
153 | + // key: scriptId, | ||
154 | + // value: rawResponse, | ||
155 | + // headers: headers | ||
156 | + // } | ||
157 | + // ] | ||
158 | + // } | ||
158 | ).then( | 159 | ).then( |
159 | () => {}, | 160 | () => {}, |
160 | (err) => { | 161 | (err) => { |
@@ -14,6 +14,8 @@ | @@ -14,6 +14,8 @@ | ||
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | # | 15 | # |
16 | 16 | ||
17 | +service-type: "TB_SERVICE_TYPE" | ||
18 | + | ||
17 | kafka: | 19 | kafka: |
18 | request_topic: "REMOTE_JS_EVAL_REQUEST_TOPIC" | 20 | request_topic: "REMOTE_JS_EVAL_REQUEST_TOPIC" |
19 | bootstrap: | 21 | bootstrap: |
msa/js-executor/queue/kafka/kafkaTemplate.js
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 | +const { logLevel, Kafka } = require('kafkajs'); | ||
17 | + | ||
18 | +const config = require('config'), | ||
19 | + JsInvokeMessageProcessor = require('../../api/jsInvokeMessageProcessor'), | ||
20 | + logger = require('../../config/logger')._logger('main'), | ||
21 | + KafkaJsWinstonLogCreator = require('../../config/logger').KafkaJsWinstonLogCreator; | ||
22 | + | ||
23 | +var kafkaClient; | ||
24 | +var consumer; | ||
25 | +var producer; | ||
26 | + | ||
27 | +function KafkaProducer() { | ||
28 | + this.send = async (responseTopic, scriptId, rawResponse, headers) => { | ||
29 | + return producer.send( | ||
30 | + { | ||
31 | + topic: responseTopic, | ||
32 | + messages: [ | ||
33 | + { | ||
34 | + key: scriptId, | ||
35 | + value: rawResponse, | ||
36 | + headers: headers | ||
37 | + } | ||
38 | + ] | ||
39 | + }); | ||
40 | + } | ||
41 | +} | ||
42 | + | ||
43 | +(async() => { | ||
44 | + try { | ||
45 | + logger.info('Starting ThingsBoard JavaScript Executor Microservice...'); | ||
46 | + | ||
47 | + const kafkaBootstrapServers = config.get('kafka.bootstrap.servers'); | ||
48 | + const kafkaRequestTopic = config.get('kafka.request_topic'); | ||
49 | + | ||
50 | + logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers); | ||
51 | + logger.info('Kafka Requests Topic: %s', kafkaRequestTopic); | ||
52 | + | ||
53 | + kafkaClient = new Kafka({ | ||
54 | + brokers: kafkaBootstrapServers.split(','), | ||
55 | + logLevel: logLevel.INFO, | ||
56 | + logCreator: KafkaJsWinstonLogCreator | ||
57 | + }); | ||
58 | + | ||
59 | + consumer = kafkaClient.consumer({ groupId: 'js-executor-group' }); | ||
60 | + producer = kafkaClient.producer(); | ||
61 | + const messageProcessor = new JsInvokeMessageProcessor(new KafkaProducer()); | ||
62 | + await consumer.connect(); | ||
63 | + await producer.connect(); | ||
64 | + await consumer.subscribe({ topic: kafkaRequestTopic}); | ||
65 | + | ||
66 | + logger.info('Started ThingsBoard JavaScript Executor Microservice.'); | ||
67 | + await consumer.run({ | ||
68 | + eachMessage: async ({ topic, partition, message }) => { | ||
69 | + messageProcessor.onJsInvokeMessage(message); | ||
70 | + }, | ||
71 | + }); | ||
72 | + | ||
73 | + } catch (e) { | ||
74 | + logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message); | ||
75 | + logger.error(e.stack); | ||
76 | + exit(-1); | ||
77 | + } | ||
78 | +})(); | ||
79 | + | ||
80 | +process.on('exit', () => { | ||
81 | + exit(0); | ||
82 | +}); | ||
83 | + | ||
84 | +async function exit(status) { | ||
85 | + logger.info('Exiting with status: %d ...', status); | ||
86 | + if (consumer) { | ||
87 | + logger.info('Stopping Kafka Consumer...'); | ||
88 | + var _consumer = consumer; | ||
89 | + consumer = null; | ||
90 | + try { | ||
91 | + await _consumer.disconnect(); | ||
92 | + logger.info('Kafka Consumer stopped.'); | ||
93 | + await disconnectProducer(); | ||
94 | + process.exit(status); | ||
95 | + } catch (e) { | ||
96 | + logger.info('Kafka Consumer stop error.'); | ||
97 | + await disconnectProducer(); | ||
98 | + process.exit(status); | ||
99 | + } | ||
100 | + } else { | ||
101 | + process.exit(status); | ||
102 | + } | ||
103 | +} | ||
104 | + | ||
105 | +async function disconnectProducer() { | ||
106 | + if (producer) { | ||
107 | + logger.info('Stopping Kafka Producer...'); | ||
108 | + var _producer = producer; | ||
109 | + producer = null; | ||
110 | + try { | ||
111 | + await _producer.disconnect(); | ||
112 | + logger.info('Kafka Producer stopped.'); | ||
113 | + } catch (e) { | ||
114 | + logger.info('Kafka Producer stop error.'); | ||
115 | + } | ||
116 | + } | ||
117 | +} |
@@ -13,89 +13,17 @@ | @@ -13,89 +13,17 @@ | ||
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -const { logLevel, Kafka } = require('kafkajs'); | ||
17 | 16 | ||
18 | -const config = require('config'), | ||
19 | - JsInvokeMessageProcessor = require('./api/jsInvokeMessageProcessor'), | ||
20 | - logger = require('./config/logger')._logger('main'), | ||
21 | - KafkaJsWinstonLogCreator = require('./config/logger').KafkaJsWinstonLogCreator; | ||
22 | - | ||
23 | -var kafkaClient; | ||
24 | -var consumer; | ||
25 | -var producer; | ||
26 | - | ||
27 | -(async() => { | ||
28 | - try { | ||
29 | - logger.info('Starting ThingsBoard JavaScript Executor Microservice...'); | ||
30 | - | ||
31 | - const kafkaBootstrapServers = config.get('kafka.bootstrap.servers'); | ||
32 | - const kafkaRequestTopic = config.get('kafka.request_topic'); | ||
33 | - | ||
34 | - logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers); | ||
35 | - logger.info('Kafka Requests Topic: %s', kafkaRequestTopic); | ||
36 | - | ||
37 | - kafkaClient = new Kafka({ | ||
38 | - brokers: kafkaBootstrapServers.split(','), | ||
39 | - logLevel: logLevel.INFO, | ||
40 | - logCreator: KafkaJsWinstonLogCreator | ||
41 | - }); | ||
42 | - | ||
43 | - consumer = kafkaClient.consumer({ groupId: 'js-executor-group' }); | ||
44 | - producer = kafkaClient.producer(); | ||
45 | - const messageProcessor = new JsInvokeMessageProcessor(producer); | ||
46 | - await consumer.connect(); | ||
47 | - await producer.connect(); | ||
48 | - await consumer.subscribe({ topic: kafkaRequestTopic}); | ||
49 | - | ||
50 | - logger.info('Started ThingsBoard JavaScript Executor Microservice.'); | ||
51 | - await consumer.run({ | ||
52 | - eachMessage: async ({ topic, partition, message }) => { | ||
53 | - messageProcessor.onJsInvokeMessage(message); | ||
54 | - }, | ||
55 | - }); | ||
56 | - | ||
57 | - } catch (e) { | ||
58 | - logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message); | ||
59 | - logger.error(e.stack); | ||
60 | - exit(-1); | ||
61 | - } | ||
62 | -})(); | ||
63 | - | ||
64 | -process.on('exit', () => { | ||
65 | - exit(0); | ||
66 | -}); | ||
67 | - | ||
68 | -async function exit(status) { | ||
69 | - logger.info('Exiting with status: %d ...', status); | ||
70 | - if (consumer) { | ||
71 | - logger.info('Stopping Kafka Consumer...'); | ||
72 | - var _consumer = consumer; | ||
73 | - consumer = null; | ||
74 | - try { | ||
75 | - await _consumer.disconnect(); | ||
76 | - logger.info('Kafka Consumer stopped.'); | ||
77 | - await disconnectProducer(); | ||
78 | - process.exit(status); | ||
79 | - } catch (e) { | ||
80 | - logger.info('Kafka Consumer stop error.'); | ||
81 | - await disconnectProducer(); | ||
82 | - process.exit(status); | ||
83 | - } | ||
84 | - } else { | ||
85 | - process.exit(status); | ||
86 | - } | 17 | +const config = require('config'); |
18 | + | ||
19 | +const serviceType = config.get('service-type'); | ||
20 | +switch (serviceType) { | ||
21 | + case 'kafka': | ||
22 | + require('./queue/kafka/kafkaTemplate'); | ||
23 | + console.log('Used kafka template.'); | ||
24 | + break; | ||
25 | + default: | ||
26 | + console.error('Unknown service type: ', serviceType); | ||
27 | + process.exit(-1); | ||
87 | } | 28 | } |
88 | 29 | ||
89 | -async function disconnectProducer() { | ||
90 | - if (producer) { | ||
91 | - logger.info('Stopping Kafka Producer...'); | ||
92 | - var _producer = producer; | ||
93 | - producer = null; | ||
94 | - try { | ||
95 | - await _producer.disconnect(); | ||
96 | - logger.info('Kafka Producer stopped.'); | ||
97 | - } catch (e) { | ||
98 | - logger.info('Kafka Producer stop error.'); | ||
99 | - } | ||
100 | - } | ||
101 | -} |