Skip to content

Commit 4923686

Browse files
authored
noderoster: configurable host cache size and eviction duration (#1246)
1 parent bfcadfd commit 4923686

File tree

4 files changed

+58
-67
lines changed

4 files changed

+58
-67
lines changed

server/dist/src/main/resources/concord-server.conf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,15 @@ concord-server {
724724
# date/time of the first event that should be processed (ISO 8601 timestamp)
725725
# if partitioning is used then the value must be in the existing partition's range
726726
# startTimestamp = "2020-01-20T23:59:59.000Z"
727+
728+
# Host id cache size. Each element (hostname[String] + id[UUID]) is
729+
# up-to 2072 bytes each, but usually in the 200-300 bytes range.
730+
# 50,000 entries will use approx 10-15MB of heap or worst-case 98MB
731+
# if all hostnames are max-length. A value of 0 disables caching.
732+
hostCacheSize = 10000
733+
734+
# Duration to keep host IDs in cache after last access
735+
hostCacheDuration = "1 hour"
727736
}
728737
}
729738

server/plugins/noderoster/impl/src/main/java/com/walmartlabs/concord/server/plugins/noderoster/HostManager.java

Lines changed: 32 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,45 @@
2020
* =====
2121
*/
2222

23-
import com.google.common.cache.Cache;
2423
import com.google.common.cache.CacheBuilder;
24+
import com.google.common.cache.CacheLoader;
25+
import com.google.common.cache.LoadingCache;
26+
import com.walmartlabs.concord.server.plugins.noderoster.cfg.NodeRosterEventsConfiguration;
2527
import com.walmartlabs.concord.server.plugins.noderoster.dao.HostsDao;
2628
import com.walmartlabs.concord.server.sdk.metrics.WithTimer;
2729

30+
import javax.annotation.Nonnull;
2831
import javax.inject.Inject;
2932
import javax.inject.Named;
33+
import javax.inject.Singleton;
3034
import java.util.Optional;
3135
import java.util.UUID;
32-
import java.util.concurrent.Callable;
33-
import java.util.concurrent.TimeUnit;
3436

3537
@Named
38+
@Singleton
3639
public class HostManager {
3740

3841
private final HostsDao dao;
3942
private final HostNormalizer hostNormalizer;
4043

41-
private final Cache<String, Optional<UUID>> hostCache;
44+
private final LoadingCache<String, Optional<UUID>> hostCache;
4245

4346
@Inject
44-
public HostManager(HostsDao dao, HostNormalizer hostNormalizer) {
47+
public HostManager(HostsDao dao, HostNormalizer hostNormalizer, NodeRosterEventsConfiguration cfg) {
4548
this.dao = dao;
4649
this.hostNormalizer = hostNormalizer;
4750

4851
this.hostCache = CacheBuilder.newBuilder()
49-
.expireAfterAccess(1, TimeUnit.MINUTES)
50-
.build();
52+
.expireAfterAccess(cfg.getHostCacheDuration())
53+
.maximumSize(cfg.getHostCacheSize())
54+
.recordStats()
55+
.build(new CacheLoader<>() {
56+
@Override
57+
public @Nonnull Optional<UUID> load(@Nonnull String host) {
58+
UUID id = findHost(host);
59+
return Optional.ofNullable(id);
60+
}
61+
});
5162
}
5263

5364
@WithTimer
@@ -57,7 +68,7 @@ public UUID getId(UUID hostId, String host) {
5768
}
5869

5970
try {
60-
return hostCache.get(host, new GetLoader(host))
71+
return hostCache.get(host)
6172
.orElse(null);
6273
} catch (Exception e) {
6374
throw new RuntimeException(e);
@@ -67,69 +78,24 @@ public UUID getId(UUID hostId, String host) {
6778
@WithTimer
6879
public UUID getOrCreate(String host) {
6980
try {
70-
return hostCache.get(host, new GetOrCreateLoader(host))
71-
.orElseThrow(() -> new RuntimeException("Can't find a host: " + host));
72-
} catch (Exception e) {
73-
throw new RuntimeException(e);
74-
}
75-
}
76-
77-
private Host findHost(String host) {
78-
String normalizedHost = hostNormalizer.normalize(host);
79-
UUID hostId = dao.getId(normalizedHost);
80-
if (hostId != null) {
81-
return new Host(hostId, normalizedHost);
82-
}
83-
84-
return new Host(null, normalizedHost);
85-
}
86-
87-
private static class Host {
88-
89-
private final UUID id;
90-
private final String normalizedHost;
91-
92-
public Host(UUID id, String normalizedHost) {
93-
this.id = id;
94-
this.normalizedHost = normalizedHost;
95-
}
96-
}
81+
Optional<UUID> knownHost = hostCache.get(host);
9782

98-
private final class GetLoader implements Callable<Optional<UUID>> {
99-
100-
private final String host;
101-
102-
private GetLoader(String host) {
103-
this.host = host;
104-
}
105-
106-
@Override
107-
public Optional<UUID> call() {
108-
Host h = findHost(host);
109-
if (h.id == null) {
110-
return Optional.empty();
83+
if (knownHost.isPresent()) {
84+
return knownHost.get();
11185
}
11286

113-
return Optional.of(h.id);
114-
}
115-
}
116-
117-
private final class GetOrCreateLoader implements Callable<Optional<UUID>> {
118-
119-
private final String host;
87+
// insert in db and update cache
88+
UUID id = dao.insert(hostNormalizer.normalize(host));
89+
hostCache.put(host, Optional.of(id));
12090

121-
private GetOrCreateLoader(String host) {
122-
this.host = host;
91+
return id;
92+
} catch (Exception e) {
93+
throw new RuntimeException(e);
12394
}
95+
}
12496

125-
@Override
126-
public Optional<UUID> call() {
127-
Host h = findHost(host);
128-
if (h.id != null) {
129-
return Optional.of(h.id);
130-
}
131-
132-
return Optional.of(dao.insert(h.normalizedHost));
133-
}
97+
private UUID findHost(String host) {
98+
String normalizedHost = hostNormalizer.normalize(host);
99+
return dao.getId(normalizedHost);
134100
}
135101
}

server/plugins/noderoster/impl/src/main/java/com/walmartlabs/concord/server/plugins/noderoster/cfg/NodeRosterEventsConfiguration.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ public class NodeRosterEventsConfiguration implements Serializable {
4444
@Config("noderoster.events.fetchLimit")
4545
private int fetchLimit;
4646

47+
@Inject
48+
@Config("noderoster.events.hostCacheSize")
49+
private long hostCacheSize;
50+
51+
@Inject
52+
@Config("noderoster.events.hostCacheDuration")
53+
private Duration hostCacheDuration;
54+
4755
private final Instant startTimestamp;
4856

4957
@Inject
@@ -59,6 +67,14 @@ public int getFetchLimit() {
5967
return fetchLimit;
6068
}
6169

70+
public long getHostCacheSize() {
71+
return hostCacheSize;
72+
}
73+
74+
public Duration getHostCacheDuration() {
75+
return hostCacheDuration;
76+
}
77+
6278
@Nullable
6379
public Instant getStartTimestamp() {
6480
return startTimestamp;

server/plugins/noderoster/impl/src/main/java/com/walmartlabs/concord/server/plugins/noderoster/processor/ProcessHostsProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public ProcessHostsPartitioner() {
141141
}
142142

143143
@Value.Immutable
144-
static abstract class ProcessHostItem {
144+
public abstract static class ProcessHostItem {
145145

146146
public abstract UUID instanceId();
147147

0 commit comments

Comments
 (0)