Registry

This article explains how to provide a custom registry implementation by extending the org.apache.dubbo.registry.client.ServiceDiscovery SPI.

In the Service Discovery chapter, we learned about the usage and working principles of several core built-in registry implementations in Dubbo, such as Nacos and Zookeeper. This article explains how to provide a custom registry implementation by extending the org.apache.dubbo.registry.client.ServiceDiscovery and org.apache.dubbo.registry.nacos.NacosServiceDiscoveryFactory SPI.

For the complete source code of this example, please refer to dubbo-registry-etcd. In addition to this example, many registry extension implementations in the core repository apache/dubbo and the extension library apache/dubbo-spi-extensions can serve as references for extensions:

  1. # Common registry implementations supported by Dubbo
  2. nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscoveryFactory
  3. zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory

Task Details

Implement the etcd registry based on extending SPI.

Implementation Method

Code Details

First, implement the ServiceDiscoveryFactory interface by extending AbstractServiceDiscoveryFactory

  1. public class EtcdServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
  2. @Override
  3. protected ServiceDiscovery createDiscovery(URL registryURL) {
  4. return new EtcdServiceDiscovery(applicationModel, registryURL);
  5. }
  6. }

Some key methods and implementations of EtcdServiceDiscovery are as follows:

  1. public class EtcdServiceDiscovery extends AbstractServiceDiscovery {
  2. private final Set<String> services = new ConcurrentHashSet<>();
  3. private final Map<String, InstanceChildListener> childListenerMap = new ConcurrentHashMap<>();
  4. EtcdClient etcdClient;
  5. public EtcdServiceDiscovery(ApplicationModel applicationModel, URL registryURL) {
  6. super(applicationModel, registryURL);
  7. EtcdTransporter etcdTransporter = applicationModel.getExtensionLoader(EtcdTransporter.class).getAdaptiveExtension();
  8. etcdClient = etcdTransporter.connect(registryURL);
  9. etcdClient.addStateListener(state -> {
  10. if (state == StateListener.CONNECTED) {
  11. try {
  12. recover();
  13. } catch (Exception e) {
  14. logger.error(e.getMessage(), e);
  15. }
  16. }
  17. });
  18. this.registryURL = registryURL;
  19. }
  20. @Override
  21. public void doRegister(ServiceInstance serviceInstance) {
  22. try {
  23. String path = toPath(serviceInstance);
  24. etcdClient.putEphemeral(path, new Gson().toJson(serviceInstance));
  25. services.add(serviceInstance.getServiceName());
  26. } catch (Throwable e) {
  27. throw new RpcException("Failed to register " + serviceInstance + " to etcd " + etcdClient.getUrl()
  28. + ", cause: " + (OptionUtil.isProtocolError(e)
  29. ? "etcd3 registry may not be supported yet or etcd3 registry is not available."
  30. : e.getMessage()), e);
  31. }
  32. }
  33. @Override
  34. protected void doUnregister(ServiceInstance serviceInstance) {
  35. try {
  36. String path = toPath(serviceInstance);
  37. etcdClient.delete(path);
  38. services.remove(serviceInstance.getServiceName());
  39. } catch (Throwable e) {
  40. throw new RpcException("Failed to unregister " + serviceInstance + " to etcd " + etcdClient.getUrl() + ", cause: " + e.getMessage(), e);
  41. }
  42. }
  43. @Override
  44. public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException {
  45. for (String serviceName : listener.getServiceNames()) {
  46. registerServiceWatcher(serviceName, listener);
  47. }
  48. }
  49. @Override
  50. public List<ServiceInstance> getInstances(String serviceName) {
  51. List<String> children = etcdClient.getChildren(toParentPath(serviceName));
  52. if (CollectionUtils.isEmpty(children)) {
  53. return Collections.emptyList();
  54. }
  55. List<ServiceInstance> list = new ArrayList<>(children.size());
  56. for (String child : children) {
  57. ServiceInstance serviceInstance = new Gson().fromJson(etcdClient.getKVValue(child), DefaultServiceInstance.class);
  58. list.add(serviceInstance);
  59. }
  60. return list;
  61. }
  62. }

SPI Configuration

Add the following configuration in the resources/META-INF/dubbo/org.apache.dubbo.registry.client.ServiceDiscoveryFactory file:

  1. etcd=org.apache.dubbo.registry.etcd.EtcdServiceDiscoveryFactory

Usage

To enable etcd as the registry, modify the registry configuration in the resources/application.properties file as follows:

  1. dubbo.registry.address=etcd://host:port

Feedback

Was this page helpful?

Yes No

Last modified September 30, 2024: Update & Translate Overview Docs (#3040) (d37ebceaea7)