Service Discovery
With the increasing popularity of micro-services, after the system split, the various service modules between the provider and consumer need to be able to find each other, we call service discovery.
In soa/distributed systems, services need to find each other. i.e. a Web service might need to find a caching service, etc. DNS can be used for this but it's nowhere near flexible enough for services, is constantly changing. A Service Discovery system provides a mechanism for:services to register their availability locating a single instance of A particular service notifying when the instances of a service change curator service Discovery
Curator Service discovery is to solve this problem, it is abstracted out of the serviceinstance, ServiceProvider, servicediscovery three interfaces, With it we can easily implement service Discovery. Practice
If we need to provide a service (Com.bytebeats.service.HelloService), in order to ensure that the service of the highly available line HelloService service deployed on N machines, now consumer want to request this service, How to ensure that the helloservice can be flexibly deployed (arbitrarily Add/remove machines). Ideas
First, HelloService provider to register the service name , port number , and address provided to zookeeper on startup Consumer start by querying zookeeper get to the service provider list, and then through the load balancing algorithm (random, roundrobin, consistent hash) Select a machine to invoke the service.
Code Implementation
Maven Dependency
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId> curator-x-discovery</artifactid>
<version>2.11.1</version>
</dependency>
Serverapp.java
Package com.bytebeats.zookeeper.curator.discovery;
Import Com.bytebeats.zookeeper.curator.CuratorUtils;
Import Com.bytebeats.zookeeper.curator.discovery.domain.ServerPayload;
Import Com.bytebeats.zookeeper.util.JsonUtils;
Import Org.apache.curator.framework.CuratorFramework;
Import org.apache.curator.x.discovery.serviceinstance;
Import Org.apache.curator.x.discovery.urispec;
Import java.util.Collection;
Import Java.util.concurrent.TimeUnit; /** * Analog Service Provider * * @author Ricky Fung * @create 2016-12-08 19:24 * * public class Serverapp {public static final
String Base_path = "Services";
public static final String service_name = "Com.bytebeats.service.HelloService";
public static void Main (string[] args) {curatorframework client = null;
Serviceregistry serviceregistry = null;
try{client = Curatorutils.getcuratorclient ();
Client.start ();
Serviceregistry = new Serviceregistry (client, Base_path); SeRviceregistry.start ();
Registration of two service instances serviceinstance<serverpayload> host1 = Serviceinstance.<serverpayload>builder ()
. ID ("Host1"). Name (service_name). Port (21888) . Address ("10.99.10.1"). Payload (New Serverpayload ("HZ", 5)). Urispec (New Urispe
C ("{Scheme}://{address}:{port}")). Build ();
Serviceregistry.registerservice (host1); serviceinstance<serverpayload> host2 = Serviceinstance.<serverpayload>builder (). ID ("Host2
"). Name (service_name). Port (21888). Address (" 10.99.1.100 ") . Payload (New Serverpayload ("QD", 3)). Urispec (New Urispec ("{Scheme}://{address}:{por
T} "). Build ();
Serviceregistry.registerservice (HOST2);SYSTEM.OUT.PRINTLN ("Register service success ...");
TimeUnit.MINUTES.sleep (1);
collection<serviceinstance<serverpayload>> list = serviceregistry.queryforinstances (SERVICE_NAME); if (List!=null && list.size () >0) {System.out.println ("service:" +service_name+ "Provider list:"
+ Jsonutils.tojson (list));
} else {System.out.println ("service:" +service_name+ "Provider is empty ...");
}} catch (Exception e) {e.printstacktrace ();
} finally {if (serviceregistry!=null) {try {serviceregistry.close ();
} catch (Exception e) {e.printstacktrace ();
}} client.close ();
}
}
}
Serviceregistry.java
Package com.bytebeats.zookeeper.curator.discovery;
Import Com.bytebeats.zookeeper.curator.discovery.domain.ServerPayload;
Import Org.apache.curator.framework.CuratorFramework;
Import Org.apache.curator.x.discovery.servicediscovery;
Import Org.apache.curator.x.discovery.servicediscoverybuilder;
Import org.apache.curator.x.discovery.serviceinstance;
Import Org.apache.curator.x.discovery.details.jsoninstanceserializer;
Import java.util.Collection; /** * Service Registration * * @author Ricky Fung * @create 2016-12-08 19:16 * * public class Serviceregistry {private Servicedi
Scovery<serverpayload> Servicediscovery;
Private final curatorframework client;
Public Serviceregistry (Curatorframework client, String basepath) {this.client = client; Servicediscovery = Servicediscoverybuilder.builder (serverpayload.class). Client (client). s
Erializer (New jsoninstanceserializer<> (Serverpayload.class)). BasePath (BasePath) . build (); } public void Updateservice (serviceinstance<serverpayload> instance) throws Exception {Servicediscover
Y.updateservice (instance); } public void Registerservice (serviceinstance<serverpayload> instance) throws Exception {Servicediscov
Ery.registerservice (instance); } public void Unregisterservice (serviceinstance<serverpayload> instance) throws Exception {Servicedisc
Overy.unregisterservice (instance);
} public collection<serviceinstance<serverpayload>> queryforinstances (String name) throws Exception {
return servicediscovery.queryforinstances (name); } Public serviceinstance<serverpayload> Queryforinstance (string name, String id) throws Exception {RET
Urn Servicediscovery.queryforinstance (name, id);
} public void Start () throws Exception {Servicediscovery.start (); } public void Close () throws Exception {serviceDiscovery.close ();
}
}
Consumer
Package com.bytebeats.zookeeper.curator.discovery;
Import Com.bytebeats.zookeeper.curator.CuratorUtils;
Import Com.bytebeats.zookeeper.curator.discovery.domain.ServerPayload;
Import Org.apache.curator.framework.CuratorFramework;
Import org.apache.curator.x.discovery.serviceinstance;
Import java.io.IOException;
Import Java.util.concurrent.TimeUnit; /** * Analog Service consumer * * @author Ricky Fung * @create 2016-12-08 20:13 * * public class ClientApp {public static void M
Ain (string[] args) {curatorframework client = null;
Servicediscover servicediscover = null;
try{client = Curatorutils.getcuratorclient ();
Client.start (); Servicediscover = new Servicediscover (client, Serverapp.base_path);
Service discovery Servicediscover.start (); for (int i=0;i<10;i++) {serviceinstance<serverpayload> instance = Servicediscover.getserviceprovi
Der (Serverapp.service_name); System.out.pRINTLN ("Service:" +serverapp.service_name+ "Instance ID:" +instance.getid () + ", NAME:" +instance.getn
Ame () + ", Address:" +instance.getaddress () + ", Port:" +instance.getport ());
TimeUnit.SECONDS.sleep (3);
}} catch (Exception e) {e.printstacktrace ();
} finally {if (servicediscover!=null) {try {servicediscover.close ();
} catch (IOException e) {e.printstacktrace ();
}} client.close ();
}
}
}
Servicediscover.java
Package com.bytebeats.zookeeper.curator.discovery;
Import Com.bytebeats.zookeeper.curator.discovery.domain.ServerPayload;
Import Org.apache.curator.framework.CuratorFramework;
Import Org.apache.curator.x.discovery.servicediscovery;
Import Org.apache.curator.x.discovery.servicediscoverybuilder;
Import org.apache.curator.x.discovery.serviceinstance;
Import Org.apache.curator.x.discovery.serviceprovider;
Import Org.apache.curator.x.discovery.details.jsoninstanceserializer;
Import Org.apache.curator.x.discovery.strategies.randomstrategy;
Import java.io.IOException;
Import Java.util.Map;
Import Java.util.concurrent.ConcurrentHashMap; /** * Service Discovery * * @author Ricky Fung * @create 2016-12-08 20:04 * * public class Servicediscover {private Servicedis
Covery<serverpayload> Servicediscovery; Private final concurrenthashmap<string, serviceprovider<serverpayload>> serviceprovidermap = new
Concurrenthashmap<> (); Public Servicediscover (Curatorframework ClienT, String basepath) {servicediscovery = Servicediscoverybuilder.builder (serverpayload.class). CLI ENT (client). BasePath (BasePath). Serializer (New jsoninstanceserializer<> (Serverpaylo
Ad.class)). Build (); }/** * Note:when using curator 2.x (Zookeeper 3.4.x) It ' s essential that service provider objects is cached B
Y your application and reused. * Since The internal Namespacewatcher objects added by the service provider cannot is removed in Zookeeper 3.4.x, * C
Reating a fresh service provider for each call to the same service would eventually exhaust the memory of the JVM. */Public serviceinstance<serverpayload> GetServiceProvider (String serviceName) throws Exception {Servi
Ceprovider<serverpayload> Provider = Serviceprovidermap.get (ServiceName);
if (Provider = = null) {Provider = Servicediscovery.serviceproviderbuilder (). ServiceName (ServiceName).
Providerstrategy (New Randomstrategy<serverpayload> ()). build ();
serviceprovider<serverpayload> Oldprovider = serviceprovidermap.putifabsent (serviceName, provider);
if (Oldprovider! = null) {Provider = Oldprovider;
}else {Provider.start ();
}} return Provider.getinstance ();
} public void Start () throws Exception {Servicediscovery.start (); } public void Close () throws IOException {for (map.entry<string, Serviceprovider<serverpayload>> ;
Me:serviceProviderMap.entrySet ()) {try{me.getvalue (). Close ();
}catch (Exception e) {e.printstacktrace ();
}} servicediscovery.close ();
}
}
Click here to download the full demo:https://github.com/tifg/zookeeper-samples
Reference
Service discovery:http://curator.apache.org/curator-x-discovery/index.html