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:

  1. Eureka Server no longer removes services from the registry that should expire because they have not received heartbeats for a long time.
  2. 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.
  3. 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:

  1. Script + Interval
  2. HTTP + Interval
  3. TCP + Interval
  4. Time to Live (TTL)
  5. Docker + Interval
  6. gRPC + Interval
  7. H2ping + Interval
  8. 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:

  1. Get all the service names
  2. 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

  1. Obtain all service names from DiscoveryClient
  2. Obtain the corresponding service instance list based on the service name list
  3. 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

  1. Implement service stry
  2. 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

  1. Consul official introduction www.consul.io/docs/intro
  2. Spring Cloud Consul github.com/spring-clou…
  3. Spring Cloud Commons github.com/spring-clou…
  4. Nacos document https://nacos.io
  5. Github.com/Netflix/eur…