CMDB is used to store metadata related to large-scale machines, devices, applications, and services. Basic attributes, such as the IP address, host name, room, application, and location of the machine, are generally entered into the CMDB during machine deployment.

When a microservice instance is deployed in multiple rooms or regions, the latency of cross-region microservice access is usually high. The typical network latency between rooms in a city is about 1ms, while that between rooms in a city is about 20ms, for example, between Nanjing and Shanghai. How to enable service consumers and service providers to access the same territory. In practice, this requirement is fulfilled through communication with the CMDB. In the service discovery component, interconnect with the CMDB and then implement same-domain priority from service consumers to service providers by routing access rules configured by the component.

Same-region access of services is preferred

To support nearby access, you need to be able to obtain the environment information of the IP address from somewhere. The deployment information can be queried from the CMDB of the enterprise or obtained from the metadata center.

CMDB plug-in mechanism

First, the CMDB data in Nacos is retrieved in some way. A better strategy would be to use an SPI mechanism, where the abstract calling interface of CMDB is agreed, and each enterprise adds its own CMDB plug-in, which can be plugged into the enterprise CMDB in a running state without any code rebuild.

Nacos CMDB SPI mechanism principle

Nacos defines an SPI interface that contains methods contracted with third-party CMDB. After the user implements corresponding SPI interface according to the convention, the data connection between Nacos and CMDB can be realized.

SPI is defined

Here is a detailed description of the concepts and interfaces of the CMDB mechanism.

CMDB abstract concepts

Entity

An entity is the bearer of data in the CMDB. In the general CMDB, an entity can refer to an IP, application, or service. This entity will have many attributes, such as IP room information, service version information and so on.


Entity Type

We do not limit the entity to be an IP, an application, or a service, depending on the actual business scenario. Currently, the entity types required for Service discovery are IP and Service.


Label

Label is the Entity property abstracted by us. Label is defined as a K-V key-value pair describing the Entity property. The value range of the key and value of a Label is defined in advance. When a new key or value needs to be added to a Label, a separate interface needs to be invoked and corresponding events are triggered. A common example of Label is IP room information. We think that site is the key of the Label, and the set of rooms (site1, site2, site3) is the value of the Label. The definition of the Label is site: Site3} {site1 and site2.


Entity Events

Change event for the entity’s label. When CMDB entity attributes change, an event mechanism is required to notify all subscribers. To ensure that the change information carried by the entity event is up-to-date and accurate, the event will only contain the identity of the changed entity and the type of the change event, not the value of the changed label.


CMDB convention interface

When designing the interaction interface with CMDB, we discussed with external customers by referring to the internal access interface to CMDB. We have finalized the following interfaces that require third-party CMDB plug-ins to implement:


Get tag list

Set<String> getLabelNames(a);
Copy the code

This method will return the set of tag names in the CMDB that need to be recognized by Nacos, and the CMDB plug-in can decide which tag Nacos to return on demand. Tags that are not in the collection will be ignored by Nacos, even if they appear in attributes of entities. We allow the collection to change dynamically at run time, and Nacos periodically calls the interface to refresh the collection of labels.

Getting the entity Type

Set<String> getEntityTypes(a);
Copy the code

Gets the set of types of entities in the CMDB. Entities that are not in the set are ignored by Nacos. The entity required by the service discovery module is similar to IP. If you want to achieve advanced load balancing of the service through the CMDB data, please be sure to include “IP” in the return set.

Obtain label Details

Label getLabel(String labelName);
Copy the code

Gets label details. The returned Label class contains a collection of Label names and Label values. If the tag value of an entity is not in the tag value set, it will be considered invalid.

Query the label value of an entity

String getLabelValue(String entityName, String entityType, String labelName);
Map<String, String> getLabelValues(String entityName, String entityType);
Copy the code

There are two methods: one is to get the value corresponding to a tag name of the entity, and the other is to get the key-value pairs of all tags of the entity. The parameter contains the value and type of the entity. Note that this method is not invoked every time a query is triggered within Nacos. Nacos has a cache of CMDB data that is accessed only if the cache is invalid or nonexistent. To keep the CMDB plug-in as simple as possible, we implemented the corresponding cache and refresh logic inside Nacos.

Query entity

Map<String, Map<String, Entity>> getAllEntities();
Entity getEntity(String entityName, String entityType);
Copy the code

Querying entities consists of two methods: querying all entities and querying a single entity. Querying for a single entity is currently querying for all of the tags of that entity, but we distinguish this method from getting all of the tags because querying for a single entity may later be extended to get more information than querying for all of the tags.

Querying all entities pulls all the data from the CMDB at once, which can be a performance drain for both Nacos and CMDB. Nacos internally invokes this method with a strategy of periodically pulling all data through a configurable periodic task cycle. When implementing the CMDB plug-in, pay attention to the performance of the CMDB service and adopt an appropriate strategy.

Querying Entity Events

List<EntityEvent> getEntityEvents(long timestamp);
Copy the code

The purpose of this method is to get the change message of the entity in the last period of time, and to incrementally pull the changed entity. Because Nacos does not access the CMDB plug-in to query entities in real time, this method of pulling events is needed to get updates to entities. Timestamp in the parameter is the time of the last pull event, which the CMDB plug-in can choose to use or ignore.

CMDB plug-in development process

The specific steps are as follows:

  1. Create a Maven project and introduce dependencies on nacos-API:
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-api</artifactId>
    <version>0.7.0</version>
</dependency>
Copy the code
  1. Introducing packaged plug-ins:
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
      <descriptorRefs>
 <descriptorRef>jar-with-dependencies</descriptorRef>  </descriptorRefs>  </configuration> </plugin> Copy the code
  1. Define the implementation class, inheritance com. Alibaba. Nacos. API. CMDB. CmdbService, and implement relevant methods.
public class ExampleCmdbServiceImple implements CmdbService{
 private int index =1 ;
}
Copy the code
  1. Create a new directory: meta-INF /services under SRC /main/resource/

  1. In SRC/main/resources/meta-inf/services directory file new com. Alibaba. Nacos. API. CMDB. CmdbService, and in the file will be created in step 3 the implementation class name written to the file:

  2. Execute command to pack:

mvn package assembly:single -Dmaven.test.skip=true
Copy the code
  1. Upload the jar package containing the dependencies from the target directory to the nacos CMDB plugin directory:
{nacos.home}/plugins/cmdb
Copy the code
  1. In nacOS application. Properties, turn on the plug-in loading switch:
nacos.cmdb.loadDataAtStart=true
Copy the code
  1. Restart the nacOS Server and load the NACOS-CMDB plug-in you implement to get your CMDB data.

Use Selector for same-room priority access

Multiple flexible load balancing strategies can be implemented using CMDB data. The following examples illustrate how CMDB data and selectors can be used to implement nearby access.

  1. Nacos obtains IP equipment room information from the CMDB. The corresponding label information is as follows:
11.11.11.11
    site: x11

22.22.22.22
    site: x12
 33.33.33.33  site: x11  44.44.44.44  site: x12  55.55.55.55  site: x13 Copy the code
  1. 11.11.11.11, 22.22.22.22, 33.33.33.33, 44.44.44.44, and 55.55.55.55 all contain tag sites, and their corresponding values are x11, X12, x11, x12, and x13, respectively.

  2. Let’s register a service and mount IP11.11.11.11 and 22.22.22.22.


  1. Then we modify the “service Route Type” of the service and configure the service route based on the same site preference:

5. Here we set the service route type to tag and enter the tag expression:

CONSUMER.label.site = PROVIDER.label.site
Copy the code
  1. The format of this expression is related to our abstract Selector mechanism, which will be described in another article. What you need to remember here is any expression of the following format:
CONSUMER.label.labelName = PROVIDER.label.labelName
Copy the code
  1. It will be able to implement load balancing policies based on the same labelName priority.

  2. Then assume that service consumers with IP addresses of 33.33.33.33, 44.44.44.44 and 55.55.55.55 are querying the list of service instances using the following interface:

naming.selectInstances("nacos.test.1", true)
Copy the code
  1. So different consumers will get a different list of instances. 33.33.33.33 gets 11.11.11.11, 44.44.44.44 gets 22.22.22.22, and 55.55.55.55 gets both 11.11.11.11 and 22.22.22.22.

Like & follow!

In the future, more in-depth combat and architecture design documents will be released, and the contents of Nacos will be as follows: