The registry
The principle of CAP
CAP principle, also known as CAP theorem, refers to Consistency, Availability and Partition tolerance in a distributed system. These three elements can only achieve two points at most at the same time, but not all of them.
CAP | Applicable scenario | explain |
---|---|---|
CA | Almost nonexistent | In a distributed system, P must exist unless it applies to a single machine. To improve the reliability of partitions, it is necessary to improve the reliability of infrastructure |
CP | Distributed database (Redis, HBase, ZK, ETCD) | Distributed databases prioritize data consistency in extreme cases |
AP | Most scenarios have no strict requirements for data consistency | Service availability is a priority |
BASE
BASE is short for Basically Available, Soft state, and Eventually consistent.
BASE is the result of tradeoff between consistency and availability in CAP. It comes from the conclusion of distributed practice of large-scale Internet system and is gradually evolved based on CAP theorem. Its core idea is that even though Strong consistency cannot be achieved, each application can be based on its own business characteristics. Adopt an appropriate approach to achieving Eventual consistency. Next, we will focus on the three elements of BASE in detail. Basic availability: The ability of a distributed system to lose some of its availability in the event of unforeseen failures.
Common registry comparison
Zookeeper | Eureka | Consul | Nacos | Etcd | |
---|---|---|---|---|---|
Data consistency | CP | AP | CP | AP/CP | CP |
Health check | Keep Alive | ClientBeat | TCP/HTTP/grpc/Cmd | TCP/HTTP/MySql/ClientBeat | ClientBeat |
Load Balancing Policy | Ribbon | Fabio | Weight/metadata/Selector | ||
Avalanche protection | There is no | There are | There is no | There are | |
Automatic logout instance | Square root | x | Square root | ||
Access protocol | TCP | HTTP | HTTP/DNS | HTTP/DNS | HTTP |
Listening to the support | Square root | Square root | Square root | Square root | Square root |
Multi-data center | x | Square root | Square root | Square root | |
Synchronization across registries | x | x | Square root | Square root | |
Spring Cloud integration | Square root | Square root | Square root | Square root | |
Dubbo integration | Square root | x | x | Square root | |
K8s integration | x | x | Square root | Square root | Square root |
Deployment difficulty | 4 | 1 | 3 | 2 | 4 |
Development of language | Java | Java | Go | Java | Go |
function | Distributed data collaboration | Service discovery based on HTTP protocol | Multiple mechanisms for service discovery and KV storage | Multi-mechanism service discovery, KV storage, configuration center, large and complete functionality | Distributed data collaboration |
timeliness | Second level | It depends on the configuration. By default, service instance information is updated in 30s, and failed nodes are removed in 90s. In this configuration, it may take 2 minutes to obtain the latest configuration | Depending on the configuration | In normal cases, it is seconds. The exception depends on the configuration. The default 15 s |
A basic registry needs the following four basic functions:
- Registers service instance information
- heartbeat
- Delete failed service instances
- Query service instance information
zookeeper
Zk itself is not intended to be a registry, but it provides a common tree storage structure and a ZNode machine that indirectly performs the necessary functions of service discovery. Let’s say we have two services A and B
/ Heavy Exercises a heavy exercises a heavy exercisesCopy the code
In this way, you can query node A to obtain instance information under service A.
In ZK, temporary nodes such as A1, A2 and B1 can be used to store service instance information. When the service instance is shut down or communication is abnormal, ZooKeeper can automatically delete these temporary nodes, thus realizing the elimination mechanism.
Zk, once the service fails, ZK will sense and notify the timeliness of other services. After the service is registered with ZK, zK will notify the timeliness of other services. Will there be temporary problems in availability after the leader fails
** Registration mechanism: ** Clients actively create temporary nodes
** Heartbeat mechanism: ** Since you are creating temporary nodes, you rely on zK’s own session mechanism
** Deletion mechanism: The temporary node is automatically deleted after the invalid session
** Query mechanism: ** Use the ZK protocol to query nodes
Eureka
In contrast to ZooKeeper, Eureka is designed to be a registry and provides all the functions needed by the registry itself. It provides an SDK and HTTP interface to access Eureka Server.
Part of the API is below, see Eureka REST Operations for more
Operation | HTTP action | Description |
---|---|---|
Register new application instance | POST /eureka/v2/apps/appID | Input: JSON/XML payload HTTP Code: 204 on success |
De-register application instance | DELETE /eureka/v2/apps/appID/instanceID | HTTP Code: 200 on success |
Send application instance heartbeat | PUT /eureka/v2/apps/appID/instanceID | HTTP Code: * 200 on success * 404 if instanceIDDoesn ‘t exist |
Query for all instances | GET /eureka/v2/apps | HTTP Code: 200 on success Output: JSON/XML |
Query for all appID instances | GET /eureka/v2/apps/appID | HTTP Code: 200 on success Output: JSON/XML |
Query for a specific appID/instanceID | GET /eureka/v2/apps/appID/instanceID | HTTP Code: 200 on success Output: JSON/XML |
If you don’t want to use the HTTP interface, you can use the Java SDK provided by Eureka directly
Eureka focuses more on AP, which can preserve most node information in case of network abnormality through self-protection mechanism to prevent avalanche
If the Eureka server detects that a larger than expected number of registered clients have terminated their connections in an inappropriate manner while waiting for eviction, they will go into self-protection mode. This is done to ensure that a catastrophic network event does not clean up eureka registry data and propagate it downward to all clients.
The self-protection mechanism works as follows: If more than 85% of the client nodes have no normal heartbeat within 15 minutes, Eureka considers that the network between the client and the registry is faulty, and the Eureka Server automatically enters the self-protection mechanism. The following situations occur:
- Eureka Server no longer removes services from the registry that should expire because they have not received heartbeats for a long time.
- Eureka Server can still accept registration and query requests for new services, but will not be synchronized to other nodes to ensure that the current node is still available.
- When the network becomes stable, the new registration information of the current Eureka Server is synchronized to other nodes.
Server Self Preservation Mode
When Eureka is in the self-protection mode, service instances cannot be deleted. In this case, the Client may query information about failed instances.
Eureka is in peer-to-peer mode, and it may die before the data is synchronized. At this point, it can continue to pull the registry from other machines, but the data is not the latest, but it ensures availability, strong consistency, and final consistency
** Registration mechanism: ** Client actively creates node information (using SDK or HTTP interface)
** Heartbeat mechanism: ** The client actively maintains reporting (using SDK or HTTP interface, and reports every 30 seconds by default)
** Deletion mechanism: ** If the server does not receive three heartbeats from the client, it will delete the server
** Query mechanism: ** Client actively queries node information (using SDK or HTTP interface)
Consul
Consul versus Other registries because Consul itself is documented and there is no reference to Consul VS Other
Consul itself provides the Go SDK and HTTP interface, including apis for service registration, health check, service query, KV operation, etc. Although there is no official SDK for other languages, there are some personal packages. It may be possible to use unofficial or self-encapsulating HTTP interfaces.
In contrast to Eureka, Consul offers a variety of heartbeat mechanisms, including:
- Script + Interval
- HTTP + Interval
- TCP + Interval
- Time to Live (TTL)
- Docker + Interval
- gRPC + Interval
- H2ping + Interval
- Alias
** Registration mechanism: ** Client actively creates node information (using SDK or HTTP interface)
** Heartbeat mechanism: ** The server tests the heartbeat of the client based on your heartbeat mechanism (unlike Eureka and ZK, the server initiates the heartbeat to the client)
** Deletion mechanism: ** The server deletes the heartbeat response when the server fails to detect it
** Query mechanism: ** Client actively queries node information (using SDK or HTTP interface)
Nacos
Nacos supports DNs-based and RPC-based service discovery. After a Service provider registers a Service using a native SDK, OpenAPI, or a separate Agent TODO, Service consumers can use DNS TODO or HTTP&API to find and discover services.
Nacos provides real-time health checks on services to prevent requests from being sent to unhealthy hosts or service instances. Nacos supports health checks at the transport layer (PING or TCP) and the application layer (e.g. HTTP, MySQL, user-defined). Nacos provides two health check modes: Agent report mode and server active check mode for complex cloud environments and network topologies, such as VPCS and edge networks. Nacos also provides a unified health check dashboard to help you manage service availability and traffic based on health status.
** Registration mechanism: ** Client actively creates node information (using SDK or HTTP interface)
** Heartbeat mechanism: ** The client actively maintains reporting (using SDK or HTTP interface, and reports every 30 seconds by default)
** Deletion mechanism: ** If the server does not receive three heartbeats from the client, it will delete the server
** Query mechanism: ** Client actively queries node information (using SDK or HTTP interface)
How does Spring Cloud implement service governance
Spring Cloud Commons service Governance analysis
Spring is often designed to make it easier to extend and eliminate boilerplate code, and Spring Clond does the same.
Spring Cloud Commons is the most important project in the Spring Cloud architecture, which defines service registration, service discovery, load balancing interfaces, and some common components. By looking at this project, We can briefly understand the core process of Spring Cloud registration discovery.
The following project structure is provided in the Spring Clond Commons project (some code files and structure are omitted here)
└ ─ ─ the SRC ├ ─ ─ the main │ ├ ─ ─ Java │ │ └ ─ ─ org │ │ └ ─ ─ springframework │ │ └ ─ ─ cloud │ │ ├ ─ ─ client │ │ │ ├ ─ ─ DefaultServiceInstance. Java │ │ │ ├ ─ ─ ServiceInstance. Java Spring Cloud definition of service instance information │ │ │ ├ ─ ─ the discovery service discovery related │ │ │ │ ├ ─ ─ DiscoveryClient. Java │ │ │ │ ├ ─ ─ EnableDiscoveryClient. Java │ │ │ │ ├ ─ ─ EnableDiscoveryClientImportSelector. Java │ │ │ │ ├ ─ ─ ManagementServerPortUtils. Java │ │ │ │ ├ ─ ─ ReactiveDiscoveryClient. Java │ │ │ │ ├ ─ ─ composite │ │ │ │ │ ├ ─ ─ CompositeDiscoveryClient. Java │ │ │ │ │ ├ ─ ─ CompositeDiscoveryClientAutoConfiguration. Java │ │ │ │ │ └ ─ ─ reactive │ │ │ │ │ ├ ─ ─ ReactiveCompositeDiscoveryClient. Java │ │ │ │ │ └ ─ ─ ReactiveCompositeDiscoveryClientAutoConfiguration. Java │ │ │ │ ├ ─ ─ the health checkup related │ │ │ │ ├ ─ ─ DiscoveryClientHealthIndicator. Java │ │ │ │ ├ ─ ─ DiscoveryClientHealthIndicatorProperties. Java │ │ │ │ ├ ─ ─ DiscoveryCompositeHealthContributor. Java │ │ │ │ ├ ─ ─ DiscoveryHealthIndicator. Java │ │ │ │ └ ─ ─ reactive │ │ │ │ ├ ─ ─ ReactiveDiscoveryClientHealthIndicator. Java │ │ │ │ ├ ─ ─ ReactiveDiscoveryCompositeHealthContributor. Java │ │ │ │ └ ─ ─ ReactiveDiscoveryHealthIndicator. Java │ │ │ ├ ─ ─ Loadbalancer below this load balancing is related to the logical │ │ │ └ ─ ─ serviceregistry service registry related │ │ │ ├ ─ ─ AbstractAutoServiceRegistration. Java │ │ │ ├ ─ ─ AutoServiceRegistration. Java │ │ │ ├ ─ ─ AutoServiceRegistrationAutoConfiguration. Java │ │ │ ├ ─ ─ AutoServiceRegistrationConfiguration. Java │ │ │ ├ ─ ─ AutoServiceRegistrationProperties. Java │ │ │ ├ ─ ─ Registration. Java │ │ │ ├ ─ ─ ServiceRegistry. Java │ │ │ ├ ─ ─ ServiceRegistryAutoConfiguration. Java │ │ ├ ─ ─ Commons │ │ ├ ─ ─ httpclient HTTP The factory class, In the configuration can choose to use Apache Http or OKHttp │ │ │ ├ ─ ─ ApacheHttpClientFactory. Java │ │ │ └ ─ ─ OkHttpClientFactory. Java │ │ └ ─ ─ util │ │ ├ ─ ─ IdUtils. Java generated by this tool class instance id │ │ └ ─ ─ InetUtils. Java Spring Cloud is through this utility class is to get the IP address of the service project │ └ ─ ─ resources │ └ ─ ─ Meta-inf │ ├ ─ ─ additional - spring - the configuration - metadata. Json │ └ ─ ─ spring. Factories └ ─ ─ the test ├ ─ ─ Java test codeCopy the code
In the project structure, you can see the corresponding source code for each part. In service governance, the first is the service information ServiceInstance, which includes
- The service name is ServiceId. This is our similar xxx-server (spring.application.name).
- InstanceId Unique identifier of the service instance
- host
- port
- Some extended information metadata, which is mainly used to add the following extended information to a three-party implementation
// Some comments have been deleted to shorten the length
public interface ServiceInstance {
default String getInstanceId(a) {
return null;
}
String getServiceId(a);
String getHost(a);
int getPort(a);
boolean isSecure(a);
URI getUri(a);
Map<String, String> getMetadata(a);
default String getScheme(a) {
return null; }}Copy the code
The service registry
Registration is a Registration implementation provided by Spring Cloud
public interface Registration extends ServiceInstance {
// There is no real code in this
}
Copy the code
The actual interface for service registration is ServiceRegistry
public interface ServiceRegistry<R extends Registration> {
/**
* Registers the registration. A registration typically has information about an
* instance, such as its hostname and port.
* @param registration registration meta data
*/
void register(R registration);
/**
* Deregisters the registration.
* @param registration registration meta data
*/
void deregister(R registration);
/** * Closes the ServiceRegistry. This is a lifecycle method. */
void close(a);
/**
* Sets the status of the registration. The status values are determined by the
* individual implementations.
* @param registration The registration to update.
* @param status The status to set.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
void setStatus(R registration, String status);
/**
* Gets the status of a particular registration.
* @param registration The registration to query.
* @param <T> The type of the status.
* @return The status of the registration.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
<T> T getStatus(R registration);
}
Copy the code
You can implement a simple ServiceRegistry function by implementing ServiceRegistry
Service discovery
DiscoveryClient and ReactiveDiscoveryClient exist in Discovery
It provides the following functions:
- Get all the service names
- Obtain a list of service instances based on the service name
public interface DiscoveryClient extends Ordered {
/** * Default order of the discovery client. */
int DEFAULT_ORDER = 0;
/**
* A human-readable description of the implementation, used in HealthIndicator.
* @return The description.
*/
String description(a);
/**
* Gets all ServiceInstances associated with a particular serviceId.
* @param serviceId The serviceId to query.
* @return A List of ServiceInstance.
*/
List<ServiceInstance> getInstances(String serviceId);
/ * * *@return All known service IDs.
*/
List<String> getServices(a);
/**
* Default implementation for getting order of discovery clients.
* @return order
*/
@Override
default int getOrder(a) {
returnDEFAULT_ORDER; }}Copy the code
You can discover services by implementing DiscoveryClient
Health detection
ReactiveDiscoveryClientHealthIndicator provides health detection
- Obtain all service names from DiscoveryClient
- Obtain the corresponding service instance list based on the service name list
- Health checks are performed on each instance and UP if the response is successful otherwise DOWN
public class ReactiveDiscoveryClientHealthIndicator
implements ReactiveDiscoveryHealthIndicator.Ordered.ApplicationListener<InstanceRegisteredEvent<? >>{
private final ReactiveDiscoveryClient discoveryClient;
private final DiscoveryClientHealthIndicatorProperties properties;
private final Log log = LogFactory.getLog(ReactiveDiscoveryClientHealthIndicator.class);
private AtomicBoolean discoveryInitialized = new AtomicBoolean(false);
private int order = Ordered.HIGHEST_PRECEDENCE;
public ReactiveDiscoveryClientHealthIndicator(ReactiveDiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
this.discoveryClient = discoveryClient;
this.properties = properties;
}
@Override
public void onApplicationEvent(InstanceRegisteredEvent
event) {
if (this.discoveryInitialized.compareAndSet(false.true)) {
this.log.debug("Discovery Client has been initialized"); }}@Override
public Mono<Health> health(a) {
if (this.discoveryInitialized.get()) {
return doHealthCheck();
}
else {
return Mono.just(
Health.status(new Status(Status.UNKNOWN.getCode(), "Discovery Client not initialized")).build()); }}private Mono<Health> doHealthCheck(a) {
// @formatter:off
return Mono.justOrEmpty(this.discoveryClient)
.flatMapMany(ReactiveDiscoveryClient::getServices)
.collectList()
.defaultIfEmpty(emptyList())
.map(services -> {
ReactiveDiscoveryClient client = this.discoveryClient;
String description = (this.properties.isIncludeDescription())
? client.description() : "";
return Health.status(new Status("UP", description))
.withDetail("services", services).build();
})
.onErrorResume(exception -> {
this.log.error("Error", exception);
return Mono.just(Health.down().withException(exception).build());
});
// @formatter:on
}
@Override
public String getName(a) {
return discoveryClient.description();
}
@Override
public int getOrder(a) {
return this.order;
}
public void setOrder(int order) {
this.order = order; }}Copy the code
Through the above interface definition and built-in health check logic can be seen to do a service governance needs to implement the simplest logic
- Implement service stry
- The DiscoveryClient function is enabled
Spring Cloud Consul implementation
implementationServiceRegistryfunction
In Spring Cloud Consul, the Registration implementation is customized first
NewService indicates some service instance information defined by Consul
public class ConsulRegistration implements Registration {
private final NewService service;
private ConsulDiscoveryProperties properties;
public ConsulRegistration(NewService service, ConsulDiscoveryProperties properties) {
this.service = service;
this.properties = properties;
}
public NewService getService(a) {
return this.service;
}
protected ConsulDiscoveryProperties getProperties(a) {
return this.properties;
}
public String getInstanceId(a) {
return getService().getId();
}
public String getServiceId(a) {
return getService().getName();
}
@Override
public String getHost(a) {
return getService().getAddress();
}
@Override
public int getPort(a) {
return getService().getPort();
}
@Override
public boolean isSecure(a) {
return this.properties.getScheme().equalsIgnoreCase("https");
}
@Override
public URI getUri(a) {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata(a) {
returngetService().getMeta(); }}Copy the code
NewService
Consul contains basic information about the service and Consul provides some unique functions such as Tags and Check
// Remove generic getters, setters, toString methods
public class NewService {
@SerializedName("ID")
private String id;
@SerializedName("Name")
private String name;
@SerializedName("Tags")
private List<String> tags;
@SerializedName("Address")
private String address;
@SerializedName("Meta")
private Map<String, String> meta;
@SerializedName("Port")
private Integer port;
@SerializedName("EnableTagOverride")
private Boolean enableTagOverride;
@SerializedName("Check")
private NewService.Check check;
@SerializedName("Checks")
private List<NewService.Check> checks;
public NewService(a) {}public static class Check {
@SerializedName("Script")
private String script;
@SerializedName("DockerContainerID")
private String dockerContainerID;
@SerializedName("Shell")
private String shell;
@SerializedName("Interval")
private String interval;
@SerializedName("TTL")
private String ttl;
@SerializedName("HTTP")
private String http;
@SerializedName("Method")
private String method;
@SerializedName("Header")
private Map<String, List<String>> header;
@SerializedName("TCP")
private String tcp;
@SerializedName("Timeout")
private String timeout;
@SerializedName("DeregisterCriticalServiceAfter")
private String deregisterCriticalServiceAfter;
@SerializedName("TLSSkipVerify")
private Boolean tlsSkipVerify;
@SerializedName("Status")
private String status;
@SerializedName("GRPC")
private String grpc;
@SerializedName("GRPCUseTLS")
private Boolean grpcUseTLS;
public Check(a) {}}}Copy the code
ConsulServiceRegistry implementation ServiceRegistry
public class ConsulServiceRegistry implements ServiceRegistry<ConsulRegistration> {
private static Log log = LogFactory.getLog(ConsulServiceRegistry.class);
private final ConsulClient client;
private final ConsulDiscoveryProperties properties;
private final TtlScheduler ttlScheduler;
private final HeartbeatProperties heartbeatProperties;
public ConsulServiceRegistry(ConsulClient client, ConsulDiscoveryProperties properties, TtlScheduler ttlScheduler, HeartbeatProperties heartbeatProperties) {
this.client = client;
this.properties = properties;
this.ttlScheduler = ttlScheduler;
this.heartbeatProperties = heartbeatProperties;
}
@Override
public void register(ConsulRegistration reg) {
log.info("Registering service with consul: " + reg.getService());
try {
Consul is also used to register services through the API interface provided by Consul
this.client.agentServiceRegister(reg.getService(), this.properties.getAclToken());
NewService service = reg.getService();
if (this.heartbeatProperties.isEnabled() && this.ttlScheduler ! =null&& service.getCheck() ! =null&& service.getCheck().getTtl() ! =null) {
this.ttlScheduler.add(reg.getInstanceId()); }}catch (ConsulException e) {
if (this.properties.isFailFast()) {
log.error("Error registering service with consul: " + reg.getService(), e);
ReflectionUtils.rethrowRuntimeException(e);
}
log.warn("Failfast is false. Error registering service with consul: "+ reg.getService(), e); }}@Override
public void deregister(ConsulRegistration reg) {
if (this.ttlScheduler ! =null) {
this.ttlScheduler.remove(reg.getInstanceId());
}
if (log.isInfoEnabled()) {
log.info("Deregistering service with consul: " + reg.getInstanceId());
}
this.client.agentServiceDeregister(reg.getInstanceId(), this.properties.getAclToken());
}
@Override
public void close(a) {}@Override
public void setStatus(ConsulRegistration registration, String status) {
if (status.equalsIgnoreCase(OUT_OF_SERVICE.getCode())) {
this.client.agentServiceSetMaintenance(registration.getInstanceId(), true);
}
else if (status.equalsIgnoreCase(UP.getCode())) {
this.client.agentServiceSetMaintenance(registration.getInstanceId(), false);
}
else {
throw new IllegalArgumentException("Unknown status: "+ status); }}// Service instance status
@Override
public Object getStatus(ConsulRegistration registration) {
String serviceId = registration.getServiceId();
Response<List<Check>> response = this.client.getHealthChecksForService(serviceId,
HealthChecksForServiceRequest.newBuilder().setQueryParams(QueryParams.DEFAULT).build());
List<Check> checks = response.getValue();
for (Check check : checks) {
if (check.getServiceId().equals(registration.getInstanceId())) {
if (check.getName().equalsIgnoreCase("Service Maintenance Mode")) {
returnOUT_OF_SERVICE.getCode(); }}}returnUP.getCode(); }}Copy the code
ConsulDiscoveryClient implementation DiscoveryClient
The discovery logic is also queried through the API interface provided by Consul
public class ConsulDiscoveryClient implements DiscoveryClient {
private final ConsulClient client;
private final ConsulDiscoveryProperties properties;
public ConsulDiscoveryClient(ConsulClient client, ConsulDiscoveryProperties properties) {
this.client = client;
this.properties = properties;
}
@Override
public String description(a) {
return "Spring Cloud Consul Discovery Client";
}
@Override
public List<ServiceInstance> getInstances(final String serviceId) {
return getInstances(serviceId, new QueryParams(this.properties.getConsistencyMode()));
}
public List<ServiceInstance> getInstances(final String serviceId, final QueryParams queryParams) {
List<ServiceInstance> instances = new ArrayList<>();
addInstancesToList(instances, serviceId, queryParams);
return instances;
}
private void addInstancesToList(List<ServiceInstance> instances, String serviceId, QueryParams queryParams) {
HealthServicesRequest.Builder requestBuilder = HealthServicesRequest.newBuilder()
.setPassing(this.properties.isQueryPassing()).setQueryParams(queryParams)
.setToken(this.properties.getAclToken());
String queryTag = this.properties.getQueryTagForService(serviceId);
if(queryTag ! =null) {
requestBuilder.setTag(queryTag);
}
HealthServicesRequest request = requestBuilder.build();
Response<List<HealthService>> services = this.client.getHealthServices(serviceId, request);
for (HealthService service : services.getValue()) {
instances.add(newConsulServiceInstance(service, serviceId)); }}public List<ServiceInstance> getAllInstances(a) {
List<ServiceInstance> instances = new ArrayList<>();
Response<Map<String, List<String>>> services = this.client
.getCatalogServices(CatalogServicesRequest.newBuilder().setQueryParams(QueryParams.DEFAULT).build());
for (String serviceId : services.getValue().keySet()) {
addInstancesToList(instances, serviceId, QueryParams.DEFAULT);
}
return instances;
}
@Override
public List<String> getServices(a) {
CatalogServicesRequest request = CatalogServicesRequest.newBuilder().setQueryParams(QueryParams.DEFAULT)
.setToken(this.properties.getAclToken()).build();
return new ArrayList<>(this.client.getCatalogServices(request).getValue().keySet());
}
@Override
public int getOrder(a) {
return this.properties.getOrder(); }}Copy the code
conclusion
A brief overview of Spring Cloud Consul’s service governance logic goes something like this, but of course Spring Cloud Consul has a lot of detail to deal with and a lot of code
Consul does not provide the function of forwarding service requests in the Spring Cloud system, but only provides the function of saving, querying, and eliminating health detection of service information
reference
- Consul official introduction www.consul.io/docs/intro
- Spring Cloud Consul github.com/spring-clou…
- Spring Cloud Commons github.com/spring-clou…
- Nacos document https://nacos.io
- Github.com/Netflix/eur…