0
# Service Discovery and Naming
1
2
Service registration, discovery, and health monitoring with event-driven updates. Essential for microservices architectures, load balancing, and dynamic service topology management.
3
4
## Capabilities
5
6
### NamingService
7
8
Main interface for service discovery and registration operations. Provides comprehensive functionality for managing service instances, health monitoring, and event-driven service updates.
9
10
```java { .api }
11
/**
12
* Main interface for service discovery and registration
13
*/
14
interface NamingService {
15
/**
16
* Register service instance with simple parameters
17
* @param serviceName Service name
18
* @param ip Instance IP address
19
* @param port Instance port
20
* @throws NacosException If registration fails
21
*/
22
void registerInstance(String serviceName, String ip, int port) throws NacosException;
23
24
/**
25
* Register service instance with group
26
* @param serviceName Service name
27
* @param groupName Service group name
28
* @param ip Instance IP address
29
* @param port Instance port
30
* @throws NacosException If registration fails
31
*/
32
void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException;
33
34
/**
35
* Register service instance with detailed configuration
36
* @param serviceName Service name
37
* @param instance Instance details including metadata
38
* @throws NacosException If registration fails
39
*/
40
void registerInstance(String serviceName, Instance instance) throws NacosException;
41
42
/**
43
* Register service instance with group and detailed configuration
44
* @param serviceName Service name
45
* @param groupName Service group name
46
* @param instance Instance details including metadata
47
* @throws NacosException If registration fails
48
*/
49
void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException;
50
51
/**
52
* Batch register multiple instances
53
* @param serviceName Service name
54
* @param groupName Service group name
55
* @param instances List of instances to register
56
* @throws NacosException If batch registration fails
57
*/
58
void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;
59
60
/**
61
* Deregister service instance
62
* @param serviceName Service name
63
* @param ip Instance IP address
64
* @param port Instance port
65
* @throws NacosException If deregistration fails
66
*/
67
void deregisterInstance(String serviceName, String ip, int port) throws NacosException;
68
69
/**
70
* Deregister service instance with group
71
* @param serviceName Service name
72
* @param groupName Service group name
73
* @param ip Instance IP address
74
* @param port Instance port
75
* @throws NacosException If deregistration fails
76
*/
77
void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException;
78
79
/**
80
* Deregister service instance with detailed configuration
81
* @param serviceName Service name
82
* @param instance Instance to deregister
83
* @throws NacosException If deregistration fails
84
*/
85
void deregisterInstance(String serviceName, Instance instance) throws NacosException;
86
87
/**
88
* Deregister service instance with group and detailed configuration
89
* @param serviceName Service name
90
* @param groupName Service group name
91
* @param instance Instance to deregister
92
* @throws NacosException If deregistration fails
93
*/
94
void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException;
95
96
/**
97
* Batch deregister multiple instances
98
* @param serviceName Service name
99
* @param groupName Service group name
100
* @param instances List of instances to deregister
101
* @throws NacosException If batch deregistration fails
102
*/
103
void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;
104
105
/**
106
* Get all instances for a service
107
* @param serviceName Service name
108
* @return List of all service instances
109
* @throws NacosException If query fails
110
*/
111
List<Instance> getAllInstances(String serviceName) throws NacosException;
112
113
/**
114
* Get all instances for a service with group
115
* @param serviceName Service name
116
* @param groupName Service group name
117
* @return List of all service instances
118
* @throws NacosException If query fails
119
*/
120
List<Instance> getAllInstances(String serviceName, String groupName) throws NacosException;
121
122
/**
123
* Get all instances with cluster filtering
124
* @param serviceName Service name
125
* @param groupName Service group name
126
* @param clusters List of cluster names to filter
127
* @return List of filtered service instances
128
* @throws NacosException If query fails
129
*/
130
List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters) throws NacosException;
131
132
/**
133
* Get instances filtered by health status
134
* @param serviceName Service name
135
* @param healthy Whether to return only healthy instances
136
* @return List of filtered instances
137
* @throws NacosException If query fails
138
*/
139
List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;
140
141
/**
142
* Get instances filtered by health status with group
143
* @param serviceName Service name
144
* @param groupName Service group name
145
* @param healthy Whether to return only healthy instances
146
* @return List of filtered instances
147
* @throws NacosException If query fails
148
*/
149
List<Instance> selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException;
150
151
/**
152
* Get instances with cluster and health filtering
153
* @param serviceName Service name
154
* @param groupName Service group name
155
* @param clusters List of cluster names
156
* @param healthy Whether to return only healthy instances
157
* @return List of filtered instances
158
* @throws NacosException If query fails
159
*/
160
List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy) throws NacosException;
161
162
/**
163
* Select one healthy instance using load balancing
164
* @param serviceName Service name
165
* @return Single healthy instance or null if none available
166
* @throws NacosException If selection fails
167
*/
168
Instance selectOneHealthyInstance(String serviceName) throws NacosException;
169
170
/**
171
* Select one healthy instance with group
172
* @param serviceName Service name
173
* @param groupName Service group name
174
* @return Single healthy instance or null if none available
175
* @throws NacosException If selection fails
176
*/
177
Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException;
178
179
/**
180
* Select one healthy instance with cluster filtering
181
* @param serviceName Service name
182
* @param groupName Service group name
183
* @param clusters List of cluster names
184
* @return Single healthy instance or null if none available
185
* @throws NacosException If selection fails
186
*/
187
Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters) throws NacosException;
188
189
/**
190
* Subscribe to service change events
191
* @param serviceName Service name
192
* @param listener Event listener for service changes
193
* @throws NacosException If subscription fails
194
*/
195
void subscribe(String serviceName, EventListener listener) throws NacosException;
196
197
/**
198
* Subscribe to service change events with group
199
* @param serviceName Service name
200
* @param groupName Service group name
201
* @param listener Event listener for service changes
202
* @throws NacosException If subscription fails
203
*/
204
void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException;
205
206
/**
207
* Subscribe with cluster filtering
208
* @param serviceName Service name
209
* @param groupName Service group name
210
* @param clusters List of cluster names
211
* @param listener Event listener for service changes
212
* @throws NacosException If subscription fails
213
*/
214
void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener) throws NacosException;
215
216
/**
217
* Unsubscribe from service change events
218
* @param serviceName Service name
219
* @param listener Event listener to remove
220
* @throws NacosException If unsubscription fails
221
*/
222
void unsubscribe(String serviceName, EventListener listener) throws NacosException;
223
224
/**
225
* Unsubscribe with group
226
* @param serviceName Service name
227
* @param groupName Service group name
228
* @param listener Event listener to remove
229
* @throws NacosException If unsubscription fails
230
*/
231
void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException;
232
233
/**
234
* Fuzzy watch services with group pattern (3.0+)
235
* @param groupNamePattern Group name pattern (supports wildcards)
236
* @param listener Event listener for pattern matches
237
* @throws NacosException If watch setup fails
238
*/
239
void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;
240
241
/**
242
* Fuzzy watch services with service and group patterns (3.0+)
243
* @param serviceNamePattern Service name pattern (supports wildcards)
244
* @param groupNamePattern Group name pattern (supports wildcards)
245
* @param listener Event listener for pattern matches
246
* @throws NacosException If watch setup fails
247
*/
248
void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;
249
250
/**
251
* Fuzzy watch with service key retrieval (3.0+)
252
* @param groupNamePattern Group name pattern
253
* @param listener Event listener
254
* @return Future containing matched service keys
255
* @throws NacosException If operation fails
256
*/
257
Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;
258
259
/**
260
* Get services list with pagination
261
* @param pageNo Page number (1-based)
262
* @param pageSize Page size
263
* @return Paginated list of services
264
* @throws NacosException If query fails
265
*/
266
ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException;
267
268
/**
269
* Get services with group and pagination
270
* @param pageNo Page number (1-based)
271
* @param pageSize Page size
272
* @param groupName Service group name
273
* @return Paginated list of services
274
* @throws NacosException If query fails
275
*/
276
ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException;
277
278
/**
279
* Get services with group and selector
280
* @param pageNo Page number (1-based)
281
* @param pageSize Page size
282
* @param groupName Service group name
283
* @param selector Service selector for filtering
284
* @return Paginated list of services
285
* @throws NacosException If query fails
286
*/
287
ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector) throws NacosException;
288
289
/**
290
* Get subscribed services information
291
* @return List of subscribed services
292
* @throws NacosException If query fails
293
*/
294
List<ServiceInfo> getSubscribeServices() throws NacosException;
295
296
/**
297
* Get server status
298
* @return Server status string
299
*/
300
String getServerStatus();
301
302
/**
303
* Shutdown naming service
304
* @throws NacosException If shutdown fails
305
*/
306
void shutDown() throws NacosException;
307
}
308
```
309
310
### Instance Model
311
312
Service instance model containing all metadata and configuration for a registered service instance.
313
314
```java { .api }
315
/**
316
* Service instance model
317
*/
318
class Instance implements Serializable {
319
/** Unique instance identifier */
320
private String instanceId;
321
322
/** Instance IP address */
323
private String ip;
324
325
/** Instance port */
326
private int port;
327
328
/** Instance weight for load balancing (default: 1.0) */
329
private double weight = 1.0D;
330
331
/** Health status (default: true) */
332
private boolean healthy = true;
333
334
/** Whether instance is enabled (default: true) */
335
private boolean enabled = true;
336
337
/** Whether instance is ephemeral (default: true) */
338
private boolean ephemeral = true;
339
340
/** Cluster name */
341
private String clusterName;
342
343
/** Service name */
344
private String serviceName;
345
346
/** Custom metadata */
347
private Map<String, String> metadata;
348
349
/**
350
* Default constructor
351
*/
352
public Instance();
353
354
/**
355
* Get unique instance identifier
356
*/
357
public String getInstanceId();
358
359
/**
360
* Set instance identifier
361
*/
362
public void setInstanceId(String instanceId);
363
364
/**
365
* Get instance IP address
366
*/
367
public String getIp();
368
369
/**
370
* Set instance IP address
371
*/
372
public void setIp(String ip);
373
374
/**
375
* Get instance port
376
*/
377
public int getPort();
378
379
/**
380
* Set instance port
381
*/
382
public void setPort(int port);
383
384
/**
385
* Get instance weight for load balancing
386
*/
387
public double getWeight();
388
389
/**
390
* Set instance weight
391
*/
392
public void setWeight(double weight);
393
394
/**
395
* Check if instance is healthy
396
*/
397
public boolean isHealthy();
398
399
/**
400
* Set health status
401
*/
402
public void setHealthy(boolean healthy);
403
404
/**
405
* Check if instance is enabled
406
*/
407
public boolean isEnabled();
408
409
/**
410
* Set enabled status
411
*/
412
public void setEnabled(boolean enabled);
413
414
/**
415
* Check if instance is ephemeral
416
*/
417
public boolean isEphemeral();
418
419
/**
420
* Set ephemeral flag
421
*/
422
public void setEphemeral(boolean ephemeral);
423
424
/**
425
* Get cluster name
426
*/
427
public String getClusterName();
428
429
/**
430
* Set cluster name
431
*/
432
public void setClusterName(String clusterName);
433
434
/**
435
* Get service name
436
*/
437
public String getServiceName();
438
439
/**
440
* Set service name
441
*/
442
public void setServiceName(String serviceName);
443
444
/**
445
* Get metadata map
446
*/
447
public Map<String, String> getMetadata();
448
449
/**
450
* Set metadata map
451
*/
452
public void setMetadata(Map<String, String> metadata);
453
454
/**
455
* Add single metadata entry
456
* @param key Metadata key
457
* @param value Metadata value
458
*/
459
public void addMetadata(String key, String value);
460
461
/**
462
* Get instance address as "ip:port"
463
*/
464
public String toInetAddr();
465
466
/**
467
* Convert instance to JSON string
468
*/
469
@Override
470
public String toString();
471
}
472
```
473
474
### Event Listeners and Events
475
476
Event-driven system for monitoring service changes with different listener implementations.
477
478
```java { .api }
479
/**
480
* Base event listener interface for service changes
481
*/
482
interface EventListener {
483
/**
484
* Handle service change event
485
* @param event Service change event
486
*/
487
void onEvent(Event event);
488
}
489
490
/**
491
* Abstract event listener implementation
492
*/
493
abstract class AbstractEventListener implements EventListener {
494
/**
495
* Abstract method to be implemented by subclasses
496
*/
497
@Override
498
public abstract void onEvent(Event event);
499
}
500
501
/**
502
* Naming service event containing service change information
503
*/
504
class NamingEvent implements Event {
505
/** Service name that changed */
506
private String serviceName;
507
508
/** Group name */
509
private String groupName;
510
511
/** Cluster names */
512
private String clusters;
513
514
/** Current instances */
515
private List<Instance> instances;
516
517
/**
518
* Constructor for naming event
519
*/
520
public NamingEvent(String serviceName, List<Instance> instances);
521
522
/**
523
* Get service name
524
*/
525
public String getServiceName();
526
527
/**
528
* Set service name
529
*/
530
public void setServiceName(String serviceName);
531
532
/**
533
* Get group name
534
*/
535
public String getGroupName();
536
537
/**
538
* Set group name
539
*/
540
public void setGroupName(String groupName);
541
542
/**
543
* Get cluster names
544
*/
545
public String getClusters();
546
547
/**
548
* Set cluster names
549
*/
550
public void setClusters(String clusters);
551
552
/**
553
* Get current instances
554
*/
555
public List<Instance> getInstances();
556
557
/**
558
* Set instances
559
*/
560
public void setInstances(List<Instance> instances);
561
}
562
```
563
564
### Service Information and Lists
565
566
Models for service metadata and paginated lists of services.
567
568
```java { .api }
569
/**
570
* Service information including instances and metadata
571
*/
572
class ServiceInfo implements Serializable {
573
/** Service name */
574
private String name;
575
576
/** Group name */
577
private String groupName;
578
579
/** Cluster names */
580
private String clusters;
581
582
/** Cache milliseconds */
583
private long cacheMillis = 1000L;
584
585
/** Service instances */
586
private List<Instance> hosts;
587
588
/** Last refresh time */
589
private long lastRefTime = 0L;
590
591
/** Checksum */
592
private String checksum = "";
593
594
/** All instances including unhealthy ones */
595
private volatile boolean allIPs = false;
596
597
/**
598
* Default constructor
599
*/
600
public ServiceInfo();
601
602
/**
603
* Constructor with service name and clusters
604
*/
605
public ServiceInfo(String name, String clusters);
606
607
/**
608
* Get service name
609
*/
610
public String getName();
611
612
/**
613
* Set service name
614
*/
615
public void setName(String name);
616
617
/**
618
* Get group name
619
*/
620
public String getGroupName();
621
622
/**
623
* Set group name
624
*/
625
public void setGroupName(String groupName);
626
627
/**
628
* Get cluster names
629
*/
630
public String getClusters();
631
632
/**
633
* Set cluster names
634
*/
635
public void setClusters(String clusters);
636
637
/**
638
* Get service instances
639
*/
640
public List<Instance> getHosts();
641
642
/**
643
* Set service instances
644
*/
645
public void setHosts(List<Instance> hosts);
646
647
/**
648
* Get cache validity in milliseconds
649
*/
650
public long getCacheMillis();
651
652
/**
653
* Set cache validity
654
*/
655
public void setCacheMillis(long cacheMillis);
656
657
/**
658
* Get last refresh time
659
*/
660
public long getLastRefTime();
661
662
/**
663
* Set last refresh time
664
*/
665
public void setLastRefTime(long lastRefTime);
666
667
/**
668
* Get checksum
669
*/
670
public String getChecksum();
671
672
/**
673
* Set checksum
674
*/
675
public void setChecksum(String checksum);
676
677
/**
678
* Check if service data is expired
679
*/
680
public boolean expired();
681
682
/**
683
* Validate service data
684
*/
685
public boolean validate();
686
}
687
688
/**
689
* Paginated list view for services
690
*/
691
class ListView<T> implements Serializable {
692
/** Total count of items */
693
private int count;
694
695
/** List of items in current page */
696
private List<T> data;
697
698
/**
699
* Default constructor
700
*/
701
public ListView();
702
703
/**
704
* Get total count
705
*/
706
public int getCount();
707
708
/**
709
* Set total count
710
*/
711
public void setCount(int count);
712
713
/**
714
* Get data list
715
*/
716
public List<T> getData();
717
718
/**
719
* Set data list
720
*/
721
public void setData(List<T> data);
722
}
723
```
724
725
### Health Checking
726
727
Health checking system with support for different protocols and custom health checkers.
728
729
```java { .api }
730
/**
731
* Abstract base class for health checkers
732
*/
733
abstract class AbstractHealthChecker implements Serializable {
734
/** Health checker type */
735
private String type;
736
737
/**
738
* Get health checker type
739
*/
740
public String getType();
741
742
/**
743
* Set health checker type
744
*/
745
public void setType(String type);
746
747
/**
748
* Clone health checker
749
*/
750
public abstract AbstractHealthChecker clone() throws CloneNotSupportedException;
751
}
752
753
/**
754
* Health check type definitions
755
*/
756
class HealthCheckType {
757
/** TCP health check */
758
public static final String TCP = "TCP";
759
760
/** HTTP health check */
761
public static final String HTTP = "HTTP";
762
763
/** MySQL health check */
764
public static final String MYSQL = "MYSQL";
765
766
/** No health check */
767
public static final String NONE = "NONE";
768
}
769
770
/**
771
* HTTP health checker implementation
772
*/
773
class Http extends AbstractHealthChecker {
774
/** HTTP path for health check */
775
private String path = "";
776
777
/** HTTP headers */
778
private String headers = "";
779
780
/** Expected response code */
781
private int expectedResponseCode = 200;
782
783
/**
784
* Default constructor
785
*/
786
public Http();
787
788
/**
789
* Get health check path
790
*/
791
public String getPath();
792
793
/**
794
* Set health check path
795
*/
796
public void setPath(String path);
797
798
/**
799
* Get HTTP headers
800
*/
801
public String getHeaders();
802
803
/**
804
* Set HTTP headers
805
*/
806
public void setHeaders(String headers);
807
808
/**
809
* Get expected response code
810
*/
811
public int getExpectedResponseCode();
812
813
/**
814
* Set expected response code
815
*/
816
public void setExpectedResponseCode(int expectedResponseCode);
817
}
818
819
/**
820
* TCP health checker implementation
821
*/
822
class Tcp extends AbstractHealthChecker {
823
/**
824
* Default constructor
825
*/
826
public Tcp();
827
}
828
829
/**
830
* MySQL health checker implementation
831
*/
832
class Mysql extends AbstractHealthChecker {
833
/** Database user */
834
private String user;
835
836
/** Database password */
837
private String pwd;
838
839
/** SQL command to execute */
840
private String cmd;
841
842
/**
843
* Default constructor
844
*/
845
public Mysql();
846
847
/**
848
* Get database user
849
*/
850
public String getUser();
851
852
/**
853
* Set database user
854
*/
855
public void setUser(String user);
856
857
/**
858
* Get database password
859
*/
860
public String getPwd();
861
862
/**
863
* Set database password
864
*/
865
public void setPwd(String pwd);
866
867
/**
868
* Get SQL command
869
*/
870
public String getCmd();
871
872
/**
873
* Set SQL command
874
*/
875
public void setCmd(String cmd);
876
}
877
```
878
879
## Usage Examples
880
881
### Basic Service Registration and Discovery
882
883
```java
884
import com.alibaba.nacos.api.NacosFactory;
885
import com.alibaba.nacos.api.PropertyKeyConst;
886
import com.alibaba.nacos.api.naming.NamingService;
887
import com.alibaba.nacos.api.naming.pojo.Instance;
888
import java.util.Properties;
889
import java.util.List;
890
891
// Create naming service
892
Properties properties = new Properties();
893
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
894
properties.setProperty(PropertyKeyConst.NAMESPACE, "production");
895
NamingService namingService = NacosFactory.createNamingService(properties);
896
897
// Simple service registration
898
namingService.registerInstance("user-service", "192.168.1.100", 8080);
899
900
// Advanced service registration with metadata
901
Instance instance = new Instance();
902
instance.setIp("192.168.1.100");
903
instance.setPort(8080);
904
instance.setWeight(2.0);
905
instance.setHealthy(true);
906
instance.setEnabled(true);
907
instance.setEphemeral(true);
908
instance.setClusterName("default");
909
910
// Add custom metadata
911
instance.addMetadata("version", "1.2.0");
912
instance.addMetadata("region", "us-east-1");
913
instance.addMetadata("zone", "zone-a");
914
instance.addMetadata("protocol", "http");
915
916
namingService.registerInstance("user-service", "microservices", instance);
917
918
// Service discovery
919
List<Instance> instances = namingService.getAllInstances("user-service", "microservices");
920
System.out.println("Found " + instances.size() + " instances");
921
922
for (Instance inst : instances) {
923
System.out.printf("Instance: %s:%d, Weight: %.1f, Healthy: %s%n",
924
inst.getIp(), inst.getPort(), inst.getWeight(), inst.isHealthy());
925
System.out.println("Metadata: " + inst.getMetadata());
926
}
927
928
// Get healthy instances only
929
List<Instance> healthyInstances = namingService.selectInstances("user-service", "microservices", true);
930
931
// Load balanced instance selection
932
Instance selectedInstance = namingService.selectOneHealthyInstance("user-service", "microservices");
933
if (selectedInstance != null) {
934
String serviceUrl = String.format("http://%s:%d",
935
selectedInstance.getIp(), selectedInstance.getPort());
936
System.out.println("Selected service URL: " + serviceUrl);
937
}
938
```
939
940
### Event-Driven Service Discovery
941
942
```java
943
import com.alibaba.nacos.api.naming.listener.EventListener;
944
import com.alibaba.nacos.api.naming.listener.NamingEvent;
945
946
// Service change event listener
947
EventListener serviceListener = new EventListener() {
948
@Override
949
public void onEvent(Event event) {
950
if (event instanceof NamingEvent) {
951
NamingEvent namingEvent = (NamingEvent) event;
952
953
System.out.printf("Service changed: %s in group %s%n",
954
namingEvent.getServiceName(), namingEvent.getGroupName());
955
956
List<Instance> instances = namingEvent.getInstances();
957
System.out.printf("Current instances count: %d%n", instances.size());
958
959
// Update local service registry
960
updateLocalServiceRegistry(namingEvent.getServiceName(), instances);
961
962
// Trigger load balancer update
963
updateLoadBalancer(instances);
964
}
965
}
966
};
967
968
// Subscribe to service changes
969
namingService.subscribe("user-service", "microservices", serviceListener);
970
namingService.subscribe("order-service", "microservices", serviceListener);
971
namingService.subscribe("payment-service", "microservices", serviceListener);
972
973
// Advanced event listener with filtering
974
EventListener clusterAwareListener = new AbstractEventListener() {
975
@Override
976
public void onEvent(Event event) {
977
NamingEvent namingEvent = (NamingEvent) event;
978
979
// Filter instances by cluster
980
List<Instance> clusterInstances = namingEvent.getInstances().stream()
981
.filter(instance -> "production".equals(instance.getClusterName()))
982
.filter(Instance::isHealthy)
983
.filter(Instance::isEnabled)
984
.collect(Collectors.toList());
985
986
if (!clusterInstances.isEmpty()) {
987
System.out.printf("Production cluster instances for %s: %d%n",
988
namingEvent.getServiceName(), clusterInstances.size());
989
990
// Update service mesh configuration
991
updateServiceMesh(namingEvent.getServiceName(), clusterInstances);
992
}
993
}
994
};
995
996
// Subscribe with cluster filtering
997
List<String> clusters = Arrays.asList("production", "staging");
998
namingService.subscribe("api-gateway", "microservices", clusters, clusterAwareListener);
999
```
1000
1001
### Batch Operations and Advanced Management
1002
1003
```java
1004
import java.util.Arrays;
1005
import java.util.concurrent.CompletableFuture;
1006
1007
// Batch registration for horizontal scaling
1008
public void registerServiceCluster(String serviceName, String groupName,
1009
List<String> ipAddresses, int port) throws NacosException {
1010
List<Instance> instances = ipAddresses.stream()
1011
.map(ip -> {
1012
Instance instance = new Instance();
1013
instance.setIp(ip);
1014
instance.setPort(port);
1015
instance.setWeight(1.0);
1016
instance.setHealthy(true);
1017
instance.setEnabled(true);
1018
instance.setClusterName("auto-scale-cluster");
1019
instance.addMetadata("deployment", "auto-scaling");
1020
instance.addMetadata("created", String.valueOf(System.currentTimeMillis()));
1021
return instance;
1022
})
1023
.collect(Collectors.toList());
1024
1025
namingService.batchRegisterInstance(serviceName, groupName, instances);
1026
System.out.printf("Batch registered %d instances for %s%n", instances.size(), serviceName);
1027
}
1028
1029
// Graceful service shutdown
1030
public void gracefulServiceShutdown(String serviceName, String groupName,
1031
String ip, int port) throws NacosException {
1032
// First, mark instance as not ready for new requests
1033
Instance instance = new Instance();
1034
instance.setIp(ip);
1035
instance.setPort(port);
1036
instance.setEnabled(false); // Stop accepting new traffic
1037
instance.addMetadata("status", "draining");
1038
1039
// Update instance to drain traffic
1040
namingService.registerInstance(serviceName, groupName, instance);
1041
1042
// Wait for existing requests to complete
1043
try {
1044
Thread.sleep(30000); // 30 second drain period
1045
} catch (InterruptedException e) {
1046
Thread.currentThread().interrupt();
1047
}
1048
1049
// Finally deregister
1050
namingService.deregisterInstance(serviceName, groupName, ip, port);
1051
System.out.printf("Gracefully shutdown instance %s:%d%n", ip, port);
1052
}
1053
1054
// Service health monitoring
1055
public void monitorServiceHealth(String serviceName, String groupName) {
1056
CompletableFuture.runAsync(() -> {
1057
while (true) {
1058
try {
1059
List<Instance> instances = namingService.getAllInstances(serviceName, groupName);
1060
1061
long healthyCount = instances.stream()
1062
.filter(Instance::isHealthy)
1063
.filter(Instance::isEnabled)
1064
.count();
1065
1066
double healthRatio = (double) healthyCount / instances.size();
1067
1068
System.out.printf("Service %s health: %d/%d instances (%.1f%%)%n",
1069
serviceName, healthyCount, instances.size(), healthRatio * 100);
1070
1071
if (healthRatio < 0.5) {
1072
System.err.printf("WARNING: %s has less than 50%% healthy instances!%n",
1073
serviceName);
1074
// Trigger alerting system
1075
triggerHealthAlert(serviceName, healthRatio);
1076
}
1077
1078
Thread.sleep(10000); // Check every 10 seconds
1079
1080
} catch (Exception e) {
1081
System.err.printf("Health monitoring error for %s: %s%n",
1082
serviceName, e.getMessage());
1083
}
1084
}
1085
});
1086
}
1087
```
1088
1089
### Fuzzy Watch and Pattern-Based Discovery (3.0+)
1090
1091
```java
1092
import com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;
1093
import java.util.concurrent.Future;
1094
1095
// Fuzzy watch for microservices pattern
1096
FuzzyWatchEventWatcher microserviceWatcher = new FuzzyWatchEventWatcher() {
1097
@Override
1098
public void onEvent(FuzzyWatchEvent event) {
1099
System.out.printf("Microservice change: %s in group %s%n",
1100
event.getServiceName(), event.getGroupName());
1101
1102
// Parse service metadata
1103
if (event.getServiceName().endsWith("-api")) {
1104
handleApiServiceChange(event);
1105
} else if (event.getServiceName().endsWith("-worker")) {
1106
handleWorkerServiceChange(event);
1107
} else if (event.getServiceName().endsWith("-db")) {
1108
handleDatabaseServiceChange(event);
1109
}
1110
}
1111
1112
@Override
1113
public Executor getExecutor() {
1114
return Executors.newFixedThreadPool(4);
1115
}
1116
};
1117
1118
// Watch all microservices in specific groups
1119
namingService.fuzzyWatch("microservice-*", microserviceWatcher);
1120
1121
// Watch specific service patterns across groups
1122
namingService.fuzzyWatch("*-api", "production-*", microserviceWatcher);
1123
1124
// Get matched service keys for discovery
1125
Future<ListView<String>> future = namingService.fuzzyWatchWithServiceKeys("microservice-*", microserviceWatcher);
1126
ListView<String> matchedServices = future.get();
1127
1128
System.out.println("Discovered microservices:");
1129
for (String serviceName : matchedServices.getData()) {
1130
System.out.println(" - " + serviceName);
1131
1132
// Get instances for each discovered service
1133
List<Instance> instances = namingService.getAllInstances(serviceName);
1134
System.out.printf(" Instances: %d%n", instances.size());
1135
}
1136
```
1137
1138
### Service Registry with Health Checking
1139
1140
```java
1141
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
1142
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;
1143
1144
// Register service with HTTP health check
1145
public void registerWithHttpHealthCheck(String serviceName, String ip, int port,
1146
String healthPath) throws NacosException {
1147
Instance instance = new Instance();
1148
instance.setIp(ip);
1149
instance.setPort(port);
1150
instance.setHealthy(true);
1151
instance.setEnabled(true);
1152
1153
// Configure HTTP health check
1154
Http httpCheck = new Http();
1155
httpCheck.setPath(healthPath);
1156
httpCheck.setHeaders("User-Agent=Nacos-Health-Check");
1157
httpCheck.setExpectedResponseCode(200);
1158
1159
// Add health check metadata
1160
instance.addMetadata("healthcheck.type", "http");
1161
instance.addMetadata("healthcheck.path", healthPath);
1162
instance.addMetadata("healthcheck.interval", "5000");
1163
1164
namingService.registerInstance(serviceName, instance);
1165
System.out.printf("Registered %s with HTTP health check at %s%n",
1166
serviceName, healthPath);
1167
}
1168
1169
// Register service with TCP health check
1170
public void registerWithTcpHealthCheck(String serviceName, String ip, int port) throws NacosException {
1171
Instance instance = new Instance();
1172
instance.setIp(ip);
1173
instance.setPort(port);
1174
instance.setHealthy(true);
1175
instance.setEnabled(true);
1176
1177
// Configure TCP health check
1178
Tcp tcpCheck = new Tcp();
1179
1180
// Add health check metadata
1181
instance.addMetadata("healthcheck.type", "tcp");
1182
instance.addMetadata("healthcheck.timeout", "3000");
1183
instance.addMetadata("healthcheck.interval", "5000");
1184
1185
namingService.registerInstance(serviceName, instance);
1186
System.out.printf("Registered %s with TCP health check%n", serviceName);
1187
}
1188
```
1189
1190
### Load Balancing and Service Selection
1191
1192
```java
1193
import java.util.Random;
1194
import java.util.concurrent.atomic.AtomicInteger;
1195
1196
public class ServiceLoadBalancer {
1197
1198
private final NamingService namingService;
1199
private final AtomicInteger roundRobinCounter = new AtomicInteger(0);
1200
private final Random random = new Random();
1201
1202
public ServiceLoadBalancer(NamingService namingService) {
1203
this.namingService = namingService;
1204
}
1205
1206
// Round-robin load balancing
1207
public Instance selectRoundRobin(String serviceName, String groupName) throws NacosException {
1208
List<Instance> instances = namingService.selectInstances(serviceName, groupName, true);
1209
1210
if (instances.isEmpty()) {
1211
return null;
1212
}
1213
1214
int index = roundRobinCounter.getAndIncrement() % instances.size();
1215
return instances.get(index);
1216
}
1217
1218
// Weighted random selection
1219
public Instance selectWeightedRandom(String serviceName, String groupName) throws NacosException {
1220
List<Instance> instances = namingService.selectInstances(serviceName, groupName, true);
1221
1222
if (instances.isEmpty()) {
1223
return null;
1224
}
1225
1226
// Calculate total weight
1227
double totalWeight = instances.stream()
1228
.mapToDouble(Instance::getWeight)
1229
.sum();
1230
1231
// Random selection based on weight
1232
double randomWeight = random.nextDouble() * totalWeight;
1233
double currentWeight = 0;
1234
1235
for (Instance instance : instances) {
1236
currentWeight += instance.getWeight();
1237
if (currentWeight >= randomWeight) {
1238
return instance;
1239
}
1240
}
1241
1242
return instances.get(instances.size() - 1);
1243
}
1244
1245
// Select instance by zone preference
1246
public Instance selectByZone(String serviceName, String groupName, String preferredZone) throws NacosException {
1247
List<Instance> instances = namingService.selectInstances(serviceName, groupName, true);
1248
1249
// First try preferred zone
1250
List<Instance> zoneInstances = instances.stream()
1251
.filter(instance -> preferredZone.equals(instance.getMetadata().get("zone")))
1252
.collect(Collectors.toList());
1253
1254
if (!zoneInstances.isEmpty()) {
1255
return zoneInstances.get(random.nextInt(zoneInstances.size()));
1256
}
1257
1258
// Fallback to any available instance
1259
if (!instances.isEmpty()) {
1260
return instances.get(random.nextInt(instances.size()));
1261
}
1262
1263
return null;
1264
}
1265
}