com.netflix.eureka2.server.replication.ReplicationService Maven / Gradle / Ivy
/*
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.eureka2.server.replication;
import com.netflix.eureka2.client.resolver.ServerResolver;
import com.netflix.eureka2.client.resolver.ServerResolver.Server;
import com.netflix.eureka2.client.resolver.ServerResolverFilter;
import com.netflix.eureka2.registry.InstanceInfo;
import com.netflix.eureka2.server.EurekaBootstrapConfig;
import com.netflix.eureka2.server.WriteClusterResolverProvider;
import com.netflix.eureka2.server.metric.WriteServerMetricFactory;
import com.netflix.eureka2.server.registry.EurekaServerRegistry;
import com.netflix.eureka2.server.service.SelfRegistrationService;
import com.netflix.eureka2.transport.EurekaTransports.Codec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Func1;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Tomasz Bak
*/
@Singleton
public class ReplicationService {
enum STATE {Idle, Connected, Closed}
private static final Logger logger = LoggerFactory.getLogger(ReplicationService.class);
// TODO: make this dynamic properties
private static final long reconnectDelay = 30000;
private final AtomicReference state = new AtomicReference<>(STATE.Idle);
private final EurekaServerRegistry eurekaRegistry;
private final SelfRegistrationService selfRegistrationService;
private final WriteClusterResolverProvider writeClusterResolverProvider;
private final WriteServerMetricFactory metricFactory;
private final Codec codec;
private final Map replicationWatchdogs = new HashMap<>();
private Subscription resolverSubscription;
@Inject
public ReplicationService(EurekaBootstrapConfig config,
EurekaServerRegistry eurekaRegistry,
SelfRegistrationService selfRegistrationService,
WriteClusterResolverProvider writeClusterResolverProvider,
WriteServerMetricFactory metricFactory) {
this.eurekaRegistry = eurekaRegistry;
this.selfRegistrationService = selfRegistrationService;
this.writeClusterResolverProvider = writeClusterResolverProvider;
this.metricFactory = metricFactory;
this.codec = config.getCodec();
}
@PostConstruct
public void connect() {
logger.info("Starting replication service");
if (!state.compareAndSet(STATE.Idle, STATE.Connected)) {
if (state.get() == STATE.Connected) {
logger.info("Replication service already started; ignoring subsequent connect");
return;
}
throw new IllegalStateException("ReplicationService already closed");
}
resolverSubscription = selfRegistrationService.resolve()
.flatMap(new Func1>() {
@Override
public Observable call(InstanceInfo instanceInfo) {
return writeClusterResolverProvider.get().resolve().lift(ServerResolverFilter.filterOut(instanceInfo, true));
}
})
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
logger.debug("Replication server resolver stream completed - write cluster server list will no longer be updated");
}
@Override
public void onError(Throwable e) {
logger.error("Replication server resolver stream error - write cluster server list will no longer be updated", e);
}
@Override
public void onNext(Server server) {
InetSocketAddress address = new InetSocketAddress(server.getHost(), server.getPort());
if (!replicationWatchdogs.containsKey(address)) {
logger.debug("Adding replication channel to server {}", address);
String targetName = address.toString();
ReplicationChannelMonitor monitor = new ReplicationChannelMonitor(
targetName,
eurekaRegistry,
new ReplicationTransportClient(address, codec, metricFactory
.getReplicationServerConnectionMetrics()),
reconnectDelay
);
replicationWatchdogs.put(address, monitor);
}
//TODO: We need a better abstraction for this server list.
}
});
}
@PreDestroy
public void close() {
logger.info("Closing replication service");
if (!state.compareAndSet(STATE.Connected, STATE.Closed)) {
return;
}
resolverSubscription.unsubscribe();
for (ReplicationChannelMonitor watchdog : replicationWatchdogs.values()) {
watchdog.close();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy