Involving a slight source code display, you can refer to it with confidence;
1. Basic introduction
Service registration discovery is the most basic capability in the microservice architecture. The following will analyze the implementation logic and principle from the source code level. Before that, let’s look at the infrastructure of the dependency project, which involves the following core components:
- commons: abstract declaration of service components, this article only analyzes registration discovery and load balancing;
- nacos: a commonly used registry component for service management;
- feign: Inter-service communication and interaction components, which involve load balancing strategies during service requests;
- ribbon: Provides a variety of load balancing strategies for inter-service communication requests;
When you are familiar with the structure of project dependencies, you must also understand the process and principle of interaction between services, so that when analyzing the source code design, you will have a clear idea and outline; how to implement the following service interaction mode, when reading the source code project, Around the following two core logics:
- Registration discovery: how to report service information data during registration, and how to manage these data;
- Load balancing: When there are multiple requested services at the same time, what strategy is used to select the requested service;
Here, let’s briefly talk about the basic ideas of individuals when reading source code projects, such as microservice components: usually from the configuration parameters as the entry point, observe the core objects built based on parameters, and then focus on analyzing the management mode of the object, and the adaptation Expansion capabilities, and finally combined with the application scenarios of the project:
The most important thing in reading the source code is to be patient and look at it slowly, and draw the core process at will. In fact, if you have a certain programming experience, no matter what project source code you are reading, as long as you carefully analyze the implementation principle of a single point, it will not count. It is too complicated, but components usually adapt to a variety of complex scenarios for reuse capabilities, so it is necessary to adopt abstract encapsulation and design patterns, and the complexity of source code projects will naturally increase accordingly. This topic will be discussed in detail later. .
2. Service registration
1. Service configuration
First, start with the Nacos configuration parameters. Here only two parameters for service discovery are set: 1. The server address of the Nacos registry, 2. Load the branch number in the metadata of the service; then let's look at the source code process in detail:
In the process of configuration parameter loading, there are many default default values, so you need to pay attention to the parameter information that will be provided eventually to determine whether custom settings are required.
AutoConfigThe configuration should focus on the instantiated object; the process of breakpoints can be set as follows, here are several core nodes in the configuration loading stage:
- Parameters: NacosDiscoveryProperties#getNacosProperties
- Build: NacosServiceManager#buildNamingService
NamingService is a Nacos service management interface, involving multiple methods such as registration, query, revocation, and inspection, that is, it corresponds to the corresponding API request of the Nacos server, and the usage will be explained in detail in the stage of registration execution.
2. Register the build
After reading the service configuration, look at the registration configuration. For the complex design in the configuration, you need to focus on two pieces of information: ConditionalOn and matchIfMissing, so it is easy to find the default loading:
- Registration: NacosServiceRegistry#register
- Instance: NacosServiceRegistry#getNacosInstanceFromRegistration
When building the core class NacosServiceRegistry for service registration, the registration information of the service is converted into the registered instantiation object, and then the instantiation object is reported through the NamingService interface method; it should be noted that although only the relevant APIs in Nacos are seen here, But in fact, the API implements many interfaces declared in the spring-cloud-commons package, such as Registration, ServiceInstance, etc.
3. Execute report
Usually the registry components of microservices are based on
server-clientArchitecture and deployment method, the client needs to report or cancel the registration according to its own startup status, and the server is responsible for uniformly maintaining the registration data:
- Implementation: NacosNamingService#registerInstance
- Execute: NamingProxy#registerService
- Interface: InstanceController#register
When the service registration is finally performed, the essence of the action is to request a Post method of the Nacos server and report the configuration data, such as IP address, port, metadata, weight, etc.; in this way, the client registration logic is executed, and then look at the service. On the client data visualization interface, you can see the registered client services.
As for how the Nacos server manages these registration data, refer to the deployment version
nacos-namingFor the module source code, read the implementation of the reporting interface and the list loading in the page; note that in the initial configuration file, the added branch parameters are also in the metadata structure.
In the NamingService interface, multiple service management methods are involved, and the execution principle is basically the same, so I will not repeat them. In this way, the client and server of the registry form a communication mechanism. Next, let's look at the communication between the clients.
3. Service Communication
1. Basic configuration
Feign is more complex in configuration and provides adaptation capabilities in multiple scenarios. Here only two common parameters are used as entry points: 1. Communication timeout time, 2. Http selection (using the default value);
- Parameters: FeignClientProperties#getConfig
- Build: FeignClientFactoryBean#getTarget
The focus here is on annotation scanning and registration and container management. To understand the context of Feign, you need to understand the interaction principle between services described above, and then refer to the construction logic in the FeignClientFactoryBean factory class.
2. Communication logic
Although the Feign annotation method can simplify development, it is still the Http request response mode during specific execution. Here you can refer to the execute method in the LoadBalancerFeignClient class:
- Configuration: FeignRibbonClientAutoConfiguration
- Communication build: LoadBalancerFeignClient#execute
- Load balancing: AbstractLoadBalancerAwareClient#executeWithLoadBalancer
Whether it is the Feign component or the Spring framework, the default load balancing strategy adopts the Ribbon implementation. In the above process, the configuration and load balancing commands depend on the Ribbon component. Next, let's look at the service selection strategy.
Fourth, load balancing
1. Command build
The command to call the load balancing interface is constructed here. The ILoadBalancer interface provides related methods of service management, the core of which is the chooseServer method, and then combines the specific policy rules to realize the function of service selection:
- Command build: LoadBalancerCommand.Builder#build
- Load container: LoadBalancerContext#getServerFromLoadBalancer
- Choose interface: ILoadBalancer#chooseServer
2. Policy rules
The load balancing strategy in the Ribbon component has several rules, such as random selection, Key matching, weight skew, etc. The default rule is RoundRobinRule, and the grayscale mode based on Key design is commonly used in work. The simple way is when the service starts. The branch number added in the metadata is used as the matching identifier;
- Rule setting: BaseLoadBalancer#setRule
- Random strategy: RoundRobinRule #choose
- Filtering strategy: PredicateBasedRule#choose
Now go back to the beginning of the process. Nacos components are used for service registration and management, and Feign components are used for service communication based on the Ribbon load balancing strategy. It is easier to understand if you look at the logic of each node component, but the Spring framework is used to communicate between components. When the collaborative scheduling of , the complexity is significantly improved;
If you are just starting to read the source code, you can only focus on the core logic of the corresponding process and selectively ignore the implementation principles of the details. Of course, the key point is to read more about the design of Spring, so you will naturally gain a lot over time.
5. Reference source code
Programming documentation: https://gitee.com/cicadasmile/butte-java-note Application repository: https://gitee.com/cicadasmile/butte-flyer-parent