All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.shardingjdbc.orchestration.reg.etcd.EtcdRegistryCenter Maven / Gradle / Ivy

There is a newer version: 2.0.3
Show newest version
/*
 * Copyright 1999-2015 dangdang.com.
 * 

* 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 io.shardingjdbc.orchestration.reg.etcd; import com.google.common.base.Optional; import com.google.protobuf.ByteString; import etcdserverpb.KVGrpc; import etcdserverpb.KVGrpc.KVFutureStub; import etcdserverpb.LeaseGrpc; import etcdserverpb.LeaseGrpc.LeaseFutureStub; import etcdserverpb.Rpc.RangeRequest; import etcdserverpb.Rpc.RangeResponse; import etcdserverpb.Rpc.PutRequest; import etcdserverpb.Rpc.LeaseGrantRequest; import etcdserverpb.Rpc.WatchCreateRequest; import etcdserverpb.Rpc.WatchRequest; import etcdserverpb.WatchGrpc; import etcdserverpb.WatchGrpc.WatchStub; import io.grpc.Channel; import io.shardingjdbc.orchestration.reg.api.RegistryCenter; import io.shardingjdbc.orchestration.reg.etcd.internal.channel.EtcdChannelFactory; import io.shardingjdbc.orchestration.reg.etcd.internal.keepalive.KeepAlive; import io.shardingjdbc.orchestration.reg.etcd.internal.retry.EtcdRetryEngine; import io.shardingjdbc.orchestration.reg.etcd.internal.watcher.EtcdWatchStreamObserver; import io.shardingjdbc.orchestration.reg.exception.RegException; import io.shardingjdbc.orchestration.reg.listener.EventListener; import mvccpb.Kv.KeyValue; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** * Etcd based registry center. * * @author junxiong */ public final class EtcdRegistryCenter implements RegistryCenter { private final EtcdConfiguration etcdConfig; private final EtcdRetryEngine etcdRetryEngine; private final KVFutureStub kvStub; private final LeaseFutureStub leaseStub; private final WatchStub watchStub; private final KeepAlive keepAlive; public EtcdRegistryCenter(final EtcdConfiguration etcdConfig) { this.etcdConfig = etcdConfig; etcdRetryEngine = new EtcdRetryEngine(etcdConfig); Channel channel = EtcdChannelFactory.getInstance(Arrays.asList(etcdConfig.getServerLists().split(","))); kvStub = KVGrpc.newFutureStub(channel); leaseStub = LeaseGrpc.newFutureStub(channel); watchStub = WatchGrpc.newStub(channel); keepAlive = new KeepAlive(channel, etcdConfig.getTimeToLiveSeconds()); } @Override public String get(final String key) { final RangeRequest request = RangeRequest.newBuilder().setKey(ByteString.copyFromUtf8(key)).build(); return etcdRetryEngine.execute(new Callable() { @Override public String call() throws Exception { RangeResponse response = kvStub.range(request).get(etcdConfig.getTimeoutMilliseconds(), TimeUnit.MILLISECONDS); return response.getKvsCount() > 0 ? response.getKvs(0).getValue().toStringUtf8() : null; } }).orNull(); } @Override public String getDirectly(final String key) { return get(key); } @Override public boolean isExisted(final String key) { return null != get(key); } @Override public List getChildrenKeys(final String key) { String path = key + "/"; final RangeRequest request = RangeRequest.newBuilder().setKey(ByteString.copyFromUtf8(path)).setRangeEnd(getRangeEnd(path)).build(); Optional> result = etcdRetryEngine.execute(new Callable>() { @Override public List call() throws Exception { RangeResponse response = kvStub.range(request).get(etcdConfig.getTimeoutMilliseconds(), TimeUnit.MILLISECONDS); List result = new ArrayList<>(); for (KeyValue each : response.getKvsList()) { String childFullPath = each.getKey().toStringUtf8(); result.add(childFullPath.substring(childFullPath.lastIndexOf("/") + 1)); } return result; } }); return result.isPresent() ? result.get() : Collections.emptyList(); } @Override public void persist(final String key, final String value) { final PutRequest request = PutRequest.newBuilder().setPrevKv(true).setKey(ByteString.copyFromUtf8(key)).setValue(ByteString.copyFromUtf8(value)).build(); etcdRetryEngine.execute(new Callable() { @Override public Void call() throws Exception { kvStub.put(request).get(etcdConfig.getTimeoutMilliseconds(), TimeUnit.MILLISECONDS); return null; } }); } @Override public void update(final String key, final String value) { persist(key, value); } @Override public void persistEphemeral(final String key, final String value) { final Optional leaseId = lease(); if (!leaseId.isPresent()) { throw new RegException("Unable to set up heat beat for key %s", key); } final PutRequest request = PutRequest.newBuilder().setPrevKv(true).setLease(leaseId.get()).setKey(ByteString.copyFromUtf8(key)).setValue(ByteString.copyFromUtf8(value)).build(); etcdRetryEngine.execute(new Callable() { @Override public Void call() throws Exception { kvStub.put(request).get(etcdConfig.getTimeoutMilliseconds(), TimeUnit.MILLISECONDS); return null; } }); } private Optional lease() { final LeaseGrantRequest request = LeaseGrantRequest.newBuilder().setTTL(etcdConfig.getTimeToLiveSeconds()).build(); return etcdRetryEngine.execute(new Callable() { @Override public Long call() throws Exception { long leaseId = leaseStub.leaseGrant(request).get(etcdConfig.getTimeoutMilliseconds(), TimeUnit.MILLISECONDS).getID(); keepAlive.heartbeat(leaseId); return leaseId; } }); } @Override public void watch(final String key, final EventListener eventListener) { WatchCreateRequest createWatchRequest = WatchCreateRequest.newBuilder().setKey(ByteString.copyFromUtf8(key)).setRangeEnd(getRangeEnd(key)).build(); final WatchRequest request = WatchRequest.newBuilder().setCreateRequest(createWatchRequest).build(); etcdRetryEngine.execute(new Callable() { @Override public Void call() throws Exception { watchStub.watch(new EtcdWatchStreamObserver(eventListener)).onNext(request); return null; } }); } @Override public void close() { keepAlive.close(); } private ByteString getRangeEnd(final String key) { byte[] noPrefix = {0}; byte[] endKey = key.getBytes().clone(); for (int i = endKey.length - 1; i >= 0; i--) { if (endKey[i] < 0xff) { endKey[i] = (byte) (endKey[i] + 1); return ByteString.copyFrom(Arrays.copyOf(endKey, i + 1)); } } return ByteString.copyFrom(noPrefix); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy