Article directory
We know that after the service is registered with Nacos, Nacos needs to save the service instance information, so how does Nacos save it?
First, let's analyze the structure of the Nacos registry.
We know that Nacos has three levels of namespace, group, and cluster, and they are all used for isolation.
Among them, the Cluster is divided into persistent instances and temporary instances. They are both Set types.
The persistent instance will not be deleted from the registry even if the service is disconnected, while the temporary instance will be, but the temporary instance will be registered in the registry again every time the service is restarted.
Therefore, for the Nacos registry, the approximate structure can be guessed as a three-layer Map structure. The approximate structure is as follows:
Map<namespace, Map<group, Map<clusterName, Cluster>(serviceName)>>
can be analyzed, and the Nacos registry The structure is that a namespace will have multiple groups, and each group has multiple specific services. These services appear in the form of clusters, so in the cluster cluster, the last specific instance will be included.
So now that we have a general understanding, let's see how this three-layer Map structure is created.
When we send an HTTP request to Nacos to request to register an instance, the Nacos server will call the following method:
and this method will finally call the following method, which is used to create a Servic instance.
The first is the innermost Map<ClusterName, Cluster>. It can be found that the inside of the Cluster is the two Set collections that store temporary and persistent instances we just mentioned.
And the structure of this Service is
And we can see that at the beginning, we will first call the following method to determine whether the Service has been created, and if it has been created, it can be reused directly.
It can be found that the returned result here is Service, that is, the current String is actually our group.
In the serviceMap structure below, the first String is actually our namespace.
The second String is actually our group. There can be multiple Services in a group, and there can be multiple service clusters in a Service.
Then we start to see how to put specific methods into the Service
The putService method here is to put our service into the Map structure.
It can be found that in order to ensure concurrency safety in multi-threaded situations, Nacos even uses double retrieval
Then the last line gets the corresponding group from the previous Map<group,Service> structure, and then puts the service name into this group: service instance.
Then let's look at the init method. This init method is actually to initialize the heartbeat of all instances of the cluster in all services.
This will create a timed task, which will get all the instances and judge whether the heartbeat is sent back within 15s. If not, it will set the healthy state of the instance to false, and if it exceeds 30s, then the current Instances will be culled.
After understanding the above process and creating the Service, we can inject the corresponding instance into the Service after we get the Service.
Adding instances here is a full addition, first get all the existing instances, and then add the current new instance.
Here is a Datum, the key is the instance name, and the value is the specific information of the instance.
And this allIps can get all the instances in the Cluster
And here begins to distinguish whether to use CP or AP.
At this point, all instances have been obtained from the Cluster, so we just need to perform some processing and conversion on it, and then we have obtained the information of all instances in the memory.
Pay special attention to the idea of a CopyOnWrite.
We know that the instance information is stored in memory. At this time, he first gets all the instances, and then creates a new collection to store the instances, instead of directly modifying and adding to the Set in memory.
After this method is executed, we have obtained both the newly added instance and the existing instance in memory.
After that, we will put all these instances into the cluster, but we still have to choose two modes of instances.
And here is obviously a delegate method, using the DelegateConsistencyServiceImpl class. To call Distro or Raft, you need to judge the instance type.
At this time, according to the type of the key, it will be judged whether to put it into the temporary or persistent service.
Here, if you choose a temporary instance, then use Distro to create it, that is, use the AP protocol, and if it is a persistent instance, use Raft.
Because we know that both Raft and Paxos are consensus protocols, and they both choose CP.
//AP:EphemeralConsistencyService --->Distro
//CP:PersistentConsistencyService --->Raft
Therefore, our differences have already arisen here. The specific use of AP or CP depends on the protocol you use.
At this point, we first analyze the situation of using the AP protocol, that is, the situation of using Distro.
Since availability is guaranteed rather than consistency, we can actually use scheduled tasks or queues to load these instances asynchronously.
And Nacos does exactly that.
Here you can see that Datum is used again, where the value is all the corresponding instances, and the key is the service.
There are so many operations here, in fact, these instances are only operated in another memory, and these new instances have not been put into our memory, which is the set structure of Nacos, the set that stores specific instance information middle. That is, the registration of the instance has not yet been completed at this time.
The notifier seen above is the real place to start executing the registration event.
In the run method of the notifier, when the CHANGE event is triggered, the following method will be called, because the blocking queue has received the task at this time, and the logic will be executed immediately, and if the blocking queue has not received the task, it will always Blocks but does not consume performance.
The following picture is a specific example of updating the memory, and will also publish a service change event.
After entering this step, you can judge whether it should be put into the temporary or persistent Set collection according to whether it is a temporary node.
When the service discovers the temporary strength, it will get it from the ephemeralInstances of the cluster.