Skip to content

Commit ded1e0b

Browse files
authored
Merge pull request #3600 from ControlSystemStudio/kafka_upgrade
Kafka upgrade
2 parents 1a6e90f + d6e321e commit ded1e0b

File tree

5 files changed

+136
-49
lines changed

5 files changed

+136
-49
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
<apache.commons.math.version>3.6.1</apache.commons.math.version>
8080
<junit.version>5.8.2</junit.version>
8181
<elasticsearch.version>8.2.0</elasticsearch.version>
82-
<kafka.version>3.6.1</kafka.version>
82+
<kafka.version>3.9.1</kafka.version>
8383
<!--<maven.repo.local>${project.build.directory}/.m2</maven.repo.local> -->
8484
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
8585
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

services/alarm-logger/src/main/java/org/phoebus/alarm/logging/AlarmLoggingService.java

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -228,20 +228,6 @@ else if (cmd.equals("-logging"))
228228
iter.remove();
229229
LogManager.getLogManager().readConfiguration(new FileInputStream(filename));
230230
}
231-
else if(cmd.equals("-thread_pool_size")){
232-
if (! iter.hasNext()){
233-
throw new Exception("Missing -thread_pool_size value");
234-
}
235-
iter.remove();
236-
try {
237-
String size = iter.next();
238-
Integer threadPoolSize = Integer.valueOf(size);
239-
properties.put("thread_pool_size", size);
240-
} catch (NumberFormatException e) {
241-
logger.warning("Specified thread pool size is not a number, will use value from properties or default value");
242-
}
243-
iter.remove();
244-
}
245231
else
246232
throw new Exception("Unknown option " + cmd);
247233
}
@@ -257,23 +243,17 @@ else if(cmd.equals("-thread_pool_size")){
257243
logger.info("Alarm Logging Service (PID " + ProcessHandle.current().pid() + ")");
258244
context = SpringApplication.run(AlarmLoggingService.class, original_args);
259245

260-
// Create scheduler with configured or default thread pool size
261-
Integer threadPoolSize;
262-
try {
263-
threadPoolSize = Integer.valueOf(properties.getProperty("thread_pool_size"));
264-
} catch (NumberFormatException e) {
265-
logger.info("Specified thread pool size is not a number, will default to 4");
266-
threadPoolSize = 4;
267-
}
268-
Scheduler = Executors.newScheduledThreadPool(threadPoolSize);
269-
270246
logger.info("Properties:");
271247
properties.forEach((k, v) -> { logger.info(k + ":" + v); });
272248

273249
// Read list of Topics
274250
final List<String> topicNames = Arrays.asList(properties.getProperty("alarm_topics").split(","));
275251
logger.info("Starting logger for '..State': " + topicNames);
276252

253+
// Create scheduler with configured or default thread pool size
254+
int threadPoolSize = topicNames.size() * 2; // default to 2 threads per topic
255+
Scheduler = Executors.newScheduledThreadPool(threadPoolSize);
256+
277257
final boolean standalone = Boolean.valueOf(properties.getProperty("standalone"));
278258

279259
// If the standalone is true, ignore the Schedulers for AlarmMessageLogger and AlarmCmdLogger

services/alarm-logger/src/main/resources/application.properties

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ use_dated_index_names=true
4848
# The units of the indices date span: Days (D), Weeks(W), Months(M), Years(Y).
4949
date_span_units=M
5050

51-
# Size of the thread pool for message and command loggers. Two threads per topic/configuration are required
52-
thread_pool_size=4
53-
5451
# Standalone - Alarm Logger Service
5552
standalone=false
5653

services/alarm-server/src/main/java/org/phoebus/applications/alarm/server/AlarmServerMain.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,18 @@
1818
import java.util.Set;
1919
import java.util.concurrent.ConcurrentHashMap;
2020
import java.util.concurrent.SynchronousQueue;
21+
import java.util.concurrent.TimeUnit;
2122
import java.util.concurrent.atomic.AtomicInteger;
2223
import java.util.logging.Level;
2324
import java.util.logging.LogManager;
2425
import java.util.prefs.Preferences;
2526

27+
import org.apache.kafka.clients.admin.AdminClient;
28+
import org.apache.kafka.clients.admin.AdminClientConfig;
29+
import org.apache.kafka.clients.admin.AlterConfigOp;
30+
import org.apache.kafka.clients.admin.ConfigEntry;
31+
import org.apache.kafka.clients.admin.ListTopicsResult;
32+
import org.apache.kafka.clients.admin.NewTopic;
2633
import org.phoebus.applications.alarm.AlarmSystemConstants;
2734
import org.phoebus.applications.alarm.client.ClientState;
2835
import org.phoebus.applications.alarm.model.AlarmTreeItem;
@@ -35,6 +42,7 @@
3542
import org.phoebus.util.shell.CommandShell;
3643

3744
import com.fasterxml.jackson.databind.JsonNode;
45+
import org.apache.kafka.common.config.ConfigResource;
3846

3947
/** Alarm Server
4048
* @author Kay Kasemir
@@ -72,6 +80,107 @@ public class AlarmServerMain implements ServerModelListener
7280
"\trestart - Re-load alarm configuration and restart.\n" +
7381
"\tshutdown - Shut alarm server down and exit.\n";
7482

83+
/**
84+
* Ensure that the required Kafka topics exist and are correctly configured.
85+
* <p>
86+
* Creates and configures the main alarm topic (compacted) and command/talk topics (deleted).
87+
* For more details on alarm topic configuration, see:
88+
* Refer to <a href="https://github.com/ControlSystemStudio/phoebus/tree/master/app/alarm#configure-alarm-topics">Configure Alarm Topics</a>
89+
*
90+
* @param server Kafka server
91+
* @param topic Base topic name
92+
* @param kafka_props_file Extra Kafka properties file
93+
* @throws Exception
94+
*/
95+
private static void ensureKafkaTopics(String server, String topic, String kafka_props_file) throws Exception {
96+
try (AdminClient admin = AdminClient.create(Map.of(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, server))) {
97+
Set<String> topics = admin.listTopics().names().get(60, TimeUnit.SECONDS);
98+
// Compacted topic
99+
String compactedTopic = topic;
100+
if (!topics.contains(compactedTopic)) {
101+
createTopic(admin, compactedTopic);
102+
}
103+
setCompactedConfig(admin, compactedTopic);
104+
105+
// Deleted topics
106+
for (String suffix : List.of("Command", "Talk")) {
107+
String deletedTopic = topic + suffix;
108+
if (!topics.contains(deletedTopic)) {
109+
createTopic(admin, deletedTopic);
110+
}
111+
setDeletedConfig(admin, deletedTopic);
112+
}
113+
}
114+
}
115+
116+
/**
117+
* Create topics
118+
*
119+
* @param admin Admin client
120+
* @param topic Topic name
121+
* @throws Exception
122+
*/
123+
private static void createTopic(AdminClient admin, String topic) throws Exception {
124+
NewTopic newTopic = new NewTopic(topic, 1, (short) 1);
125+
try {
126+
admin.createTopics(List.of(newTopic)).all().get();
127+
logger.info("Created topic: " + topic);
128+
} catch (Exception e) {
129+
if (e.getCause() instanceof org.apache.kafka.common.errors.TopicExistsException) {
130+
logger.info("Topic already exists: " + topic);
131+
} else {
132+
throw e;
133+
}
134+
}
135+
}
136+
137+
/**
138+
* Configure topic for alarm state storage with compaction to retain latest state.
139+
* For configuration information, see:
140+
* <p>
141+
* Refer to <a href="https://github.com/ControlSystemStudio/phoebus/tree/master/app/alarm#configure-alarm-topics">Configure Alarm Topics</a>
142+
*
143+
* @param admin Admin client
144+
* @param topic Topic name
145+
* @throws Exception
146+
*/
147+
private static void setCompactedConfig(AdminClient admin, String topic) throws Exception {
148+
ConfigResource resource = new ConfigResource(ConfigResource.Type.TOPIC, topic);
149+
List<AlterConfigOp> configOps = List.of(
150+
new AlterConfigOp(new ConfigEntry("cleanup.policy", "compact"), AlterConfigOp.OpType.SET),
151+
new AlterConfigOp(new ConfigEntry("segment.ms", "10000"), AlterConfigOp.OpType.SET),
152+
new AlterConfigOp(new ConfigEntry("min.cleanable.dirty.ratio", "0.01"), AlterConfigOp.OpType.SET),
153+
new AlterConfigOp(new ConfigEntry("min.compaction.lag.ms", "1000"), AlterConfigOp.OpType.SET)
154+
);
155+
admin.incrementalAlterConfigs(Map.of(resource, configOps)).all().get();
156+
logger.info("Set compacted config for topic: " + topic);
157+
}
158+
159+
/**
160+
* Configure topic for command/talk messages with time-based deletion.
161+
* For configuration information, see:
162+
*
163+
* Refer to <a href="https://github.com/ControlSystemStudio/phoebus/tree/master/app/alarm#configure-alarm-topics">Configure Alarm Topics</a>
164+
*
165+
* @param admin Admin client
166+
* @param topic Topic name
167+
* @throws Exception
168+
*/
169+
private static void setDeletedConfig(AdminClient admin, String topic) throws Exception {
170+
ConfigResource resource = new ConfigResource(ConfigResource.Type.TOPIC, topic);
171+
List<AlterConfigOp> configOps = List.of(
172+
new AlterConfigOp(new ConfigEntry("cleanup.policy", "delete"), AlterConfigOp.OpType.SET),
173+
new AlterConfigOp(new ConfigEntry("segment.ms", "10000"), AlterConfigOp.OpType.SET),
174+
new AlterConfigOp(new ConfigEntry("min.cleanable.dirty.ratio", "0.01"), AlterConfigOp.OpType.SET),
175+
new AlterConfigOp(new ConfigEntry("min.compaction.lag.ms", "1000"), AlterConfigOp.OpType.SET),
176+
new AlterConfigOp(new ConfigEntry("retention.ms", "20000"), AlterConfigOp.OpType.SET),
177+
new AlterConfigOp(new ConfigEntry("delete.retention.ms", "1000"), AlterConfigOp.OpType.SET),
178+
new AlterConfigOp(new ConfigEntry("file.delete.delay.ms", "1000"), AlterConfigOp.OpType.SET)
179+
);
180+
admin.incrementalAlterConfigs(Map.of(resource, configOps)).all().get();
181+
logger.info("Set deleted config for topic: " + topic);
182+
}
183+
75184
private AlarmServerMain(final String server, final String config, final boolean use_shell, final String kafka_props_file)
76185
{
77186
logger.info("Server: " + server);
@@ -85,6 +194,10 @@ private AlarmServerMain(final String server, final String config, final boolean
85194
boolean run = true;
86195
while (run)
87196
{
197+
logger.info("Verify topics exists and are correctly configured...");
198+
// Create/verify topics before using Kafka
199+
ensureKafkaTopics(server, config, kafka_props_file);
200+
88201
logger.info("Fetching past alarm states...");
89202
final AlarmStateInitializer init = new AlarmStateInitializer(server, config, kafka_props_file);
90203
if (init.awaitCompleteStates())
Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
11
version: '2.2'
22

3-
networks:
4-
rmoff_kafka:
5-
name: rmoff_kafka
6-
73
services:
8-
zookeeper:
9-
image: confluentinc/cp-zookeeper:5.5.0
10-
container_name: zookeeper
11-
ports:
12-
- "2181:2181"
13-
environment:
14-
ZOOKEEPER_CLIENT_PORT: 2181
15-
164
kafka:
17-
image: confluentinc/cp-kafka:5.5.0
5+
image: confluentinc/cp-kafka:7.6.0
186
container_name: kafka
197
ports:
208
- "9092:9092"
21-
- "19092:19092"
22-
depends_on:
23-
- zookeeper
249
environment:
25-
KAFKA_BROKER_ID: 1
26-
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
27-
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,CONNECTIONS_FROM_HOST://localhost:19092
28-
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT
29-
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
10+
CLUSTER_ID: 'MkU3OEVBNTcwNTJENDM2Qk'
11+
KAFKA_NODE_ID: 1
12+
KAFKA_PROCESS_ROLES: broker,controller
13+
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
14+
KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
15+
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
16+
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
17+
KAFKA_LOG_DIRS: /var/lib/kafka/data
18+
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
19+
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
20+
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
21+
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
22+
volumes:
23+
- kafka_data:/var/lib/kafka/data
24+
25+
volumes:
26+
kafka_data:

0 commit comments

Comments
 (0)