Search in sources :

Example 1 with ChildListener

use of org.apache.dubbo.remoting.etcd.ChildListener in project dubbo by alibaba.

the class EtcdRegistry method doSubscribe.

@Override
public void doSubscribe(URL url, NotifyListener listener) {
    try {
        if (ANY_VALUE.equals(url.getServiceInterface())) {
            String root = toRootPath();
            /*
                 *  if we are interested in all interfaces,
                 *  find out the current container or create one for the url, put or get only once.
                 */
            ConcurrentMap<NotifyListener, ChildListener> listeners = Optional.ofNullable(etcdListeners.get(url)).orElseGet(() -> {
                ConcurrentMap<NotifyListener, ChildListener> container, prev;
                prev = etcdListeners.putIfAbsent(url, container = new ConcurrentHashMap<>());
                return prev != null ? prev : container;
            });
            /*
                 *  if we have no interface watcher listener,
                 *  find the current listener or create one for the current root, put or get only once.
                 */
            ChildListener interfaceListener = Optional.ofNullable(listeners.get(listener)).orElseGet(() -> {
                ChildListener childListener, prev;
                prev = listeners.putIfAbsent(listener, childListener = (parentPath, currentChildren) -> {
                    /*
                                         *  because etcd3 does not support direct children watch events,
                                         *  we should filter not interface events. if we watch /dubbo
                                         *  and /dubbo/interface, when we put a key-value pair {/dubbo/interface/hello hello},
                                         *  we will got events in watching path /dubbo.
                                         */
                    for (String child : currentChildren) {
                        child = URL.decode(child);
                        if (!anyServices.contains(child)) {
                            anyServices.add(child);
                            /*
                                                 *  if new interface event arrived, we watch their direct children,
                                                 *  eg: /dubbo/interface, /dubbo/interface and so on.
                                                 */
                            subscribe(url.setPath(child).addParameters(INTERFACE_KEY, child, CHECK_KEY, String.valueOf(false)), listener);
                        }
                    }
                });
                return prev != null ? prev : childListener;
            });
            etcdClient.create(root);
            /*
                 * at the first time, we want to pull already interface and then watch their direct children,
                 *  eg: /dubbo/interface, /dubbo/interface and so on.
                 */
            List<String> services = etcdClient.addChildListener(root, interfaceListener);
            for (String service : services) {
                service = URL.decode(service);
                anyServices.add(service);
                subscribe(url.setPath(service).addParameters(INTERFACE_KEY, service, CHECK_KEY, String.valueOf(false)), listener);
            }
        } else {
            List<URL> urls = new ArrayList<>();
            for (String path : toCategoriesPath(url)) {
                /*
                     *  if we are interested in special categories (providers, consumers, routers and so on),
                     *  we find out the current container or create one for the url, put or get only once.
                     */
                ConcurrentMap<NotifyListener, ChildListener> listeners = Optional.ofNullable(etcdListeners.get(url)).orElseGet(() -> {
                    ConcurrentMap<NotifyListener, ChildListener> container, prev;
                    prev = etcdListeners.putIfAbsent(url, container = new ConcurrentHashMap<>());
                    return prev != null ? prev : container;
                });
                /*
                     *  if we have no category watcher listener,
                     *  we find out the current listener or create one for the current category, put or get only once.
                     */
                ChildListener childListener = Optional.ofNullable(listeners.get(listener)).orElseGet(() -> {
                    ChildListener watchListener, prev;
                    prev = listeners.putIfAbsent(listener, watchListener = (parentPath, currentChildren) -> EtcdRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChildren)));
                    return prev != null ? prev : watchListener;
                });
                etcdClient.create(path);
                /*
                     * at the first time, we want to pull already category and then watch their direct children,
                     *  eg: /dubbo/interface/providers, /dubbo/interface/consumers and so on.
                     */
                List<String> children = etcdClient.addChildListener(path, childListener);
                if (children != null) {
                    urls.addAll(toUrlsWithEmpty(url, path, children));
                }
            }
            notify(url, listener, urls);
        }
    } catch (Throwable e) {
        throw new RpcException("Failed to subscribe " + url + " to etcd " + getUrl() + ", cause: " + (OptionUtil.isProtocolError(e) ? "etcd3 registry may not be supported yet or etcd3 registry is not available." : e.getMessage()), e);
    }
}
Also used : ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) RpcException(org.apache.dubbo.rpc.RpcException) ArrayList(java.util.ArrayList) URL(org.apache.dubbo.common.URL) NotifyListener(org.apache.dubbo.registry.NotifyListener)

Example 2 with ChildListener

use of org.apache.dubbo.remoting.etcd.ChildListener in project dubbo by alibaba.

the class EtcdServiceDiscovery method registerServiceWatcher.

protected void registerServiceWatcher(String serviceName) {
    String path = root + File.separator + serviceName;
    /*
         *  if we have no category watcher listener,
         *  we find out the current listener or create one for the current category, put or get only once.
         */
    ChildListener childListener = Optional.ofNullable(childListenerMap.get(serviceName)).orElseGet(() -> {
        ChildListener watchListener, prev;
        prev = childListenerMap.putIfAbsent(serviceName, watchListener = (parentPath, currentChildren) -> dispatchServiceInstancesChangedEvent(serviceName));
        return prev != null ? prev : watchListener;
    });
    etcdClient.create(path);
    etcdClient.addChildListener(path, childListener);
}
Also used : ChildListener(org.apache.dubbo.remoting.etcd.ChildListener)

Example 3 with ChildListener

use of org.apache.dubbo.remoting.etcd.ChildListener in project dubbo by alibaba.

the class JEtcdClientTest method test_watch_on_recoverable_connection.

@Test
public void test_watch_on_recoverable_connection() throws InterruptedException {
    String path = "/dubbo/com.alibaba.dubbo.demo.DemoService/connection";
    String child = "/dubbo/com.alibaba.dubbo.demo.DemoService/connection/demoService1";
    final CountDownLatch notNotified = new CountDownLatch(1);
    final CountDownLatch notTwiceNotified = new CountDownLatch(2);
    final Holder notified = new Holder();
    ChildListener childListener = (parent, children) -> {
        notTwiceNotified.countDown();
        switch(notified.increaseAndGet()) {
            case 1:
                {
                    notNotified.countDown();
                    Assertions.assertEquals(1, children.size());
                    Assertions.assertEquals(child.substring(child.lastIndexOf("/") + 1), children.get(0));
                    break;
                }
            case 2:
                {
                    Assertions.assertEquals(0, children.size());
                    Assertions.assertEquals(path, parent);
                    break;
                }
            default:
                Assertions.fail("two many callback invoked.");
        }
    };
    client.addChildListener(path, childListener);
    client.createEphemeral(child);
    // make sure first time callback successfully
    Assertions.assertTrue(notNotified.await(15, TimeUnit.SECONDS));
    // connection error causes client to release all resources including current watcher
    JEtcdClient.EtcdWatcher watcher = client.getChildListener(path, childListener);
    watcher.onError(Status.UNAVAILABLE.withDescription("temporary connection issue").asRuntimeException());
    // trigger delete after unavailable
    client.delete(child);
    Assertions.assertTrue(notTwiceNotified.await(15, TimeUnit.SECONDS));
    client.removeChildListener(path, childListener);
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) ClosedClientException(io.etcd.jetcd.common.exception.ClosedClientException) Client(io.etcd.jetcd.Client) WatchEvent(io.etcd.jetcd.watch.WatchEvent) ManagedChannel(io.grpc.ManagedChannel) Watch(io.etcd.jetcd.Watch) Disabled(org.junit.jupiter.api.Disabled) WatchRequest(io.etcd.jetcd.api.WatchRequest) URL(org.apache.dubbo.common.URL) StreamObserver(io.grpc.stub.StreamObserver) SESSION_TIMEOUT_KEY(org.apache.dubbo.remoting.etcd.Constants.SESSION_TIMEOUT_KEY) ByteSequence(io.etcd.jetcd.ByteSequence) ReflectUtils(org.apache.dubbo.common.utils.ReflectUtils) ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) Status(io.grpc.Status) Method(java.lang.reflect.Method) WatchResponse(io.etcd.jetcd.api.WatchResponse) WatchCancelRequest(io.etcd.jetcd.api.WatchCancelRequest) UTF_8(java.nio.charset.StandardCharsets.UTF_8) WatchGrpc(io.etcd.jetcd.api.WatchGrpc) WatchCreateRequest(io.etcd.jetcd.api.WatchCreateRequest) Field(java.lang.reflect.Field) ByteString(com.google.protobuf.ByteString) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicLong(java.util.concurrent.atomic.AtomicLong) AfterEach(org.junit.jupiter.api.AfterEach) Event(io.etcd.jetcd.api.Event) Assertions(org.junit.jupiter.api.Assertions) ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) ByteString(com.google.protobuf.ByteString) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Example 4 with ChildListener

use of org.apache.dubbo.remoting.etcd.ChildListener in project dubbo by alibaba.

the class JEtcdClientTest method test_watch_when_create_path.

@Test
public void test_watch_when_create_path() throws InterruptedException {
    String path = "/dubbo/com.alibaba.dubbo.demo.DemoService/providers";
    String child = "/dubbo/com.alibaba.dubbo.demo.DemoService/providers/demoService1";
    final CountDownLatch notNotified = new CountDownLatch(1);
    ChildListener childListener = (parent, children) -> {
        Assertions.assertEquals(1, children.size());
        Assertions.assertEquals(child.substring(child.lastIndexOf("/") + 1), children.get(0));
        notNotified.countDown();
    };
    client.addChildListener(path, childListener);
    client.createEphemeral(child);
    Assertions.assertTrue(notNotified.await(10, TimeUnit.SECONDS));
    client.removeChildListener(path, childListener);
    client.delete(child);
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) ClosedClientException(io.etcd.jetcd.common.exception.ClosedClientException) Client(io.etcd.jetcd.Client) WatchEvent(io.etcd.jetcd.watch.WatchEvent) ManagedChannel(io.grpc.ManagedChannel) Watch(io.etcd.jetcd.Watch) Disabled(org.junit.jupiter.api.Disabled) WatchRequest(io.etcd.jetcd.api.WatchRequest) URL(org.apache.dubbo.common.URL) StreamObserver(io.grpc.stub.StreamObserver) SESSION_TIMEOUT_KEY(org.apache.dubbo.remoting.etcd.Constants.SESSION_TIMEOUT_KEY) ByteSequence(io.etcd.jetcd.ByteSequence) ReflectUtils(org.apache.dubbo.common.utils.ReflectUtils) ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) Status(io.grpc.Status) Method(java.lang.reflect.Method) WatchResponse(io.etcd.jetcd.api.WatchResponse) WatchCancelRequest(io.etcd.jetcd.api.WatchCancelRequest) UTF_8(java.nio.charset.StandardCharsets.UTF_8) WatchGrpc(io.etcd.jetcd.api.WatchGrpc) WatchCreateRequest(io.etcd.jetcd.api.WatchCreateRequest) Field(java.lang.reflect.Field) ByteString(com.google.protobuf.ByteString) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicLong(java.util.concurrent.atomic.AtomicLong) AfterEach(org.junit.jupiter.api.AfterEach) Event(io.etcd.jetcd.api.Event) Assertions(org.junit.jupiter.api.Assertions) ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) ByteString(com.google.protobuf.ByteString) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Example 5 with ChildListener

use of org.apache.dubbo.remoting.etcd.ChildListener in project dubbo by alibaba.

the class EtcdRegistry method doUnsubscribe.

@Override
public void doUnsubscribe(URL url, NotifyListener listener) {
    ConcurrentMap<NotifyListener, ChildListener> listeners = etcdListeners.get(url);
    if (listeners != null) {
        ChildListener etcdListener = listeners.remove(listener);
        if (etcdListener != null) {
            if (ANY_VALUE.equals(url.getServiceInterface())) {
                String root = toRootPath();
                etcdClient.removeChildListener(root, etcdListener);
            } else {
                // maybe url has many subscribed paths
                for (String path : toUnsubscribedPath(url)) {
                    etcdClient.removeChildListener(path, etcdListener);
                }
            }
        }
        if (listeners.isEmpty()) {
            etcdListeners.remove(url);
        }
    }
}
Also used : ChildListener(org.apache.dubbo.remoting.etcd.ChildListener) NotifyListener(org.apache.dubbo.registry.NotifyListener)

Aggregations

ChildListener (org.apache.dubbo.remoting.etcd.ChildListener)9 URL (org.apache.dubbo.common.URL)7 ByteString (com.google.protobuf.ByteString)6 ByteSequence (io.etcd.jetcd.ByteSequence)6 Client (io.etcd.jetcd.Client)6 Watch (io.etcd.jetcd.Watch)6 Event (io.etcd.jetcd.api.Event)6 WatchCancelRequest (io.etcd.jetcd.api.WatchCancelRequest)6 WatchCreateRequest (io.etcd.jetcd.api.WatchCreateRequest)6 WatchGrpc (io.etcd.jetcd.api.WatchGrpc)6 WatchRequest (io.etcd.jetcd.api.WatchRequest)6 WatchResponse (io.etcd.jetcd.api.WatchResponse)6 ClosedClientException (io.etcd.jetcd.common.exception.ClosedClientException)6 WatchEvent (io.etcd.jetcd.watch.WatchEvent)6 ManagedChannel (io.grpc.ManagedChannel)6 Status (io.grpc.Status)6 StreamObserver (io.grpc.stub.StreamObserver)6 Field (java.lang.reflect.Field)6 Method (java.lang.reflect.Method)6 UTF_8 (java.nio.charset.StandardCharsets.UTF_8)6