use of com.palantir.atlasdb.config.LeaderRuntimeConfig in project atlasdb by palantir.
the class Leaders method createInstrumentedLocalServices.
public static LocalPaxosServices createInstrumentedLocalServices(LeaderConfig config, Supplier<LeaderRuntimeConfig> runtime, RemotePaxosServerSpec remotePaxosServerSpec, String userAgent) {
UUID leaderUuid = UUID.randomUUID();
PaxosLeadershipEventRecorder leadershipEventRecorder = PaxosLeadershipEventRecorder.create(AtlasDbMetrics.getMetricRegistry(), leaderUuid.toString());
PaxosAcceptor ourAcceptor = AtlasDbMetrics.instrument(PaxosAcceptor.class, PaxosAcceptorImpl.newAcceptor(config.acceptorLogDir().getPath()));
PaxosLearner ourLearner = AtlasDbMetrics.instrument(PaxosLearner.class, PaxosLearnerImpl.newLearner(config.learnerLogDir().getPath(), leadershipEventRecorder));
Optional<SSLSocketFactory> sslSocketFactory = ServiceCreator.createSslSocketFactory(config.sslConfiguration());
List<PaxosLearner> learners = createProxyAndLocalList(ourLearner, remotePaxosServerSpec.remoteLearnerUris(), sslSocketFactory, PaxosLearner.class, userAgent);
List<PaxosAcceptor> acceptors = createProxyAndLocalList(ourAcceptor, remotePaxosServerSpec.remoteAcceptorUris(), sslSocketFactory, PaxosAcceptor.class, userAgent);
Map<PingableLeader, HostAndPort> otherLeaders = generatePingables(remotePaxosServerSpec.remoteLeaderUris(), sslSocketFactory, userAgent);
InstrumentedExecutorService proposerExecutorService = new InstrumentedExecutorService(PTExecutors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("atlas-proposer-%d").setDaemon(true).build()), AtlasDbMetrics.getMetricRegistry(), MetricRegistry.name(PaxosProposer.class, "executor"));
PaxosProposer proposer = AtlasDbMetrics.instrument(PaxosProposer.class, PaxosProposerImpl.newProposer(ourLearner, acceptors, learners, config.quorumSize(), leaderUuid, proposerExecutorService));
InstrumentedExecutorService leaderElectionExecutor = new InstrumentedExecutorService(PTExecutors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("atlas-leaders-election-%d").setDaemon(true).build()), AtlasDbMetrics.getMetricRegistry(), MetricRegistry.name(PaxosLeaderElectionService.class, "executor"));
PaxosLeaderElectionService paxosLeaderElectionService = new PaxosLeaderElectionServiceBuilder().proposer(proposer).knowledge(ourLearner).potentialLeadersToHosts(otherLeaders).acceptors(acceptors).learners(learners).executor(leaderElectionExecutor).pingRateMs(config.pingRateMs()).randomWaitBeforeProposingLeadershipMs(config.randomWaitBeforeProposingLeadershipMs()).leaderPingResponseWaitMs(config.leaderPingResponseWaitMs()).eventRecorder(leadershipEventRecorder).onlyLogOnQuorumFailure(JavaSuppliers.compose(LeaderRuntimeConfig::onlyLogOnQuorumFailure, runtime)).build();
LeaderElectionService leaderElectionService = AtlasDbMetrics.instrument(LeaderElectionService.class, paxosLeaderElectionService);
PingableLeader pingableLeader = AtlasDbMetrics.instrument(PingableLeader.class, paxosLeaderElectionService);
return ImmutableLocalPaxosServices.builder().ourAcceptor(ourAcceptor).ourLearner(ourLearner).leaderElectionService(leaderElectionService).pingableLeader(pingableLeader).build();
}
use of com.palantir.atlasdb.config.LeaderRuntimeConfig in project atlasdb by palantir.
the class TransactionManagers method createRawLeaderServices.
private static LockAndTimestampServices createRawLeaderServices(LeaderConfig leaderConfig, Consumer<Object> env, com.google.common.base.Supplier<LockService> lock, com.google.common.base.Supplier<TimestampService> time, String userAgent) {
// Create local services, that may or may not end up being registered in an Consumer<Object>.
LeaderRuntimeConfig defaultRuntime = ImmutableLeaderRuntimeConfig.builder().build();
LocalPaxosServices localPaxosServices = Leaders.createAndRegisterLocalServices(env, leaderConfig, () -> defaultRuntime, userAgent);
LeaderElectionService leader = localPaxosServices.leaderElectionService();
LockService localLock = ServiceCreator.createInstrumentedService(AwaitingLeadershipProxy.newProxyInstance(LockService.class, lock, leader), LockService.class);
TimestampService localTime = ServiceCreator.createInstrumentedService(AwaitingLeadershipProxy.newProxyInstance(TimestampService.class, time, leader), TimestampService.class);
env.accept(localLock);
env.accept(localTime);
// Create remote services, that may end up calling our own local services.
ImmutableServerListConfig serverListConfig = ImmutableServerListConfig.builder().servers(leaderConfig.leaders()).sslConfiguration(leaderConfig.sslConfiguration()).build();
LockService remoteLock = new ServiceCreator<>(LockService.class, userAgent).apply(serverListConfig);
TimestampService remoteTime = new ServiceCreator<>(TimestampService.class, userAgent).apply(serverListConfig);
if (leaderConfig.leaders().size() == 1) {
// Attempting to connect to ourself while processing a request can lead to deadlock if incoming request
// volume is high, as all Jetty threads end up waiting for the timestamp server, and no threads remain to
// actually handle the timestamp server requests. If we are the only single leader, we can avoid the
// deadlock entirely; so use PingableLeader's getUUID() to detect this situation and eliminate the redundant
// call.
PingableLeader localPingableLeader = localPaxosServices.pingableLeader();
String localServerId = localPingableLeader.getUUID();
PingableLeader remotePingableLeader = AtlasDbFeignTargetFactory.createRsProxy(ServiceCreator.createSslSocketFactory(leaderConfig.sslConfiguration()), Iterables.getOnlyElement(leaderConfig.leaders()), PingableLeader.class, userAgent);
// Determine asynchronously whether the remote services are talking to our local services.
CompletableFuture<Boolean> useLocalServicesFuture = new CompletableFuture<>();
runAsync.accept(() -> {
int logAfter = LOGGING_INTERVAL;
while (true) {
try {
String remoteServerId = remotePingableLeader.getUUID();
useLocalServicesFuture.complete(localServerId.equals(remoteServerId));
return;
} catch (ClientErrorException e) {
useLocalServicesFuture.complete(false);
return;
} catch (Throwable e) {
if (--logAfter == 0) {
log.warn("Failed to read remote timestamp server ID", e);
logAfter = LOGGING_INTERVAL;
}
}
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
}
});
// Create dynamic service proxies, that switch to talking directly to our local services if it turns out our
// remote services are pointed at them anyway.
LockService dynamicLockService = LocalOrRemoteProxy.newProxyInstance(LockService.class, localLock, remoteLock, useLocalServicesFuture);
TimestampService dynamicTimeService = LocalOrRemoteProxy.newProxyInstance(TimestampService.class, localTime, remoteTime, useLocalServicesFuture);
return ImmutableLockAndTimestampServices.builder().lock(dynamicLockService).timestamp(dynamicTimeService).timelock(new LegacyTimelockService(dynamicTimeService, dynamicLockService, LOCK_CLIENT)).build();
} else {
return ImmutableLockAndTimestampServices.builder().lock(remoteLock).timestamp(remoteTime).timelock(new LegacyTimelockService(remoteTime, remoteLock, LOCK_CLIENT)).build();
}
}
Aggregations