Click “like” to see, form a habit, wechat search [three prince Aobing] pay attention to the programmer who likes to write feelings.

This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.

In the last article, we have understood the whole process of Dubbo service exposure. In this article, I will take you to see the whole process of Dubbo service introduction. After the introduction of this service, we will come to a full link through.

In the process of writing the article, C also found a small problem in the official website, which will be mentioned below.

Without further ado, let’s cut to the chase.

Service reference flow diagram

We already know that providers expose their services and register with the registry, while consumers simply learn about the Provider from the registry through a wave of operations and then encapsulate a calling class to communicate with the Provider in depth.

As I mentioned in the previous article, one of the executables in Dubbo is Invoker, and all calls need to be Invoker. Therefore, it can be inferred that you should be an Invoker, and since the framework needs to evolve in a way that does not intrude on business code, Our Consumer needs to invoke the remote interface without awareness, so we need to create a proxy class that wraps and shields the underlying details.

The general process is as follows:

Timing of service introduction

The introduction of the service is the same as the exposure of the service, and the corresponding Bean is generated by parsing through spring’s custom tag mechanism. The Provider Service parses the ServiceBean and the Consumer Reference parses the ReferenceBean.

The timing of service exposure is analyzed in the previous article. It starts after the Spring container is refreshed, and there are two types of service introduction timing, the first is hungry, and the second is lazy.

By implementing the afterPropertiesSet method in Spring’s InitializingBean interface, the container introduces the service by calling the afterPropertiesSet method of the ReferenceBean.

The lazy style is to start the import process only when the service is injected into other classes, that is to say, service import is not started until it is used.

By default, Dubbo uses lazy to import services. If you need to use lazy to import services, you can configure Dubbo :reference’s init property to enable this function.

We can see that ReferenceBean also implements the FactoryBean interface. Here’s a surface pilot for Spring that I’ll walk you through.

BeanFactory, FactoryBean, ObjectFactory

BeanFactory and ObjectFactory are factories and FactoryBean is beans.

BeanFactory is actually an IOC container, and there are many implementation classes that I will not analyze. Simply speaking, it manages beans in Spring, and FactoryBean is also Bean, so it is also managed by BeanFactory.

So what exactly is a FactoryBean? It simply wraps a layer around the Bean you actually want. When you actually want to get the Bean, the container calls the FactoryBean#getObject() method, where you can do some complex assembly.

This method encapsulates the complex creation process of the actual desired object.

In the case where the actual Bean creation is complicated, or where third-party beans are difficult to modify, factoryBeans are used to encapsulate a layer, shielding the details of the underlying creation, and facilitating the use of beans.

ObjectFactory is a lazy look-up scenario. It is a normal factory. When you get an ObjectFactory object, the Bean has not been created.

It is mainly used to temporarily obtain A Bean Holder object. If it is loaded prematurely, it may cause some unexpected situations. For example, when Bean A depends on Bean B, if it is initialized prematurely, the state in B may be in the intermediate state.

To sum up, BeanFactory is IOC container, FactoryBean is a special Bean used to encapsulate and create complex objects, while ObjectFactory is mainly used for delayed search scenarios and delayed instantiation of objects.

There are three ways to introduce services

The introduction of services is divided into three types, the first is local introduction, the second is direct connection to introduce remote services, and the third is through the registry to introduce remote services.

Injvm protocol (scope = remote, no local reference) is used for each service, because there is a situation where the server is both Provider and Consumer. Then it is possible to call its own service, so a local import is made, which avoids the overhead of remote network calls.

So service import goes to the local cache first to see if there are any local services.

Directly connect to the remote import service, this is actually used in daily test situations, do not need to start the registry, the Consumer directly configure the Provider to write the address, and then directly connect to the Provider.

The registry introduces remote services, which is the key point. Consumers learn relevant information about providers through the registry, and then introduce services, including multiple registries, multiple providers of the same service, how to choose how to encapsulate, how to carry out load balancing, fault tolerance and make users feel nothing. It’s a skill job.

This article uses a single registry to introduce remote services, so let’s see how Dubbo does it.

Service introduction process resolution

The default is lazy, so the entry the service introduces is the getObject method of the ReferenceBean.

As you can see, it’s very simple, just call the get method, and if you don’t already have that reference then init.

A quick question on the website

If (ref == null) {if (ref == null) {if (ref == null) {if (ref == null)}} The toString method is used to get information about the object.

AbstractConfig#toString is called AbstractConfig#toString, and this method calls the ReferenceBean’s getObject method via reflection, triggering the import service action. = null.

You can see that the reflection call is made by the method name, and getObject starts with get, so it gets called.

So this guy proposed a PR, but it was not accepted at the beginning. One Member thought it was not a bug, idea should be set to not call toString.

However, another Member thought this PR was quite good, and beiwei 30, the second-generation leader of Dubbo project, also spoke, so this PR was accepted.

So far we have known about this little problem, and the website is actually quite clear.

In my previous post, I mentioned that my source version was 2.6.5, and it was released in Github releases. I knew about the toString problem quite a long time ago. I thought I had a steady release of 2.6.5, but it crashed.

When I was debugging, INIT was not included because ref was not null. I was surprised to see that toString was not changed in 2.6.5. GetObject is not filtered, so it gets called anyway.

I opened the 2.7.5 version of the code again and found that it was a modified judgment.

I went to the 2.6.6 code and found that it was also changed, so the change is not released with 2.6.5, but 2.6.6, unless IT is a fake package. This is what I call a small problem, but not a big one.

In fact, mentioned this section of the main want to say is that PR, as an open source software exporter, a lot of details are also very important, this problem is actually affecting the source code debugging, because the code is not familiar, will certainly be a face confused, who knows whether which background thread asynchronous introduction.

It took PR two hours to figure out the real reason, so it was not a bug, but it affected those who wanted to know more about the internal structure of Dubbo. It was not desirable to change the configuration to adapt. Fortunately, the final solution was to change the code.

Okay, so let’s get back to today’s topic, and the next thing I want to analyze is the init method that won’t let me in.

Source code analysis

The init method is a long one, but most of it is just checking the configuration and building the configuration into a map, so I’m not going to go through that, but let’s just look at what the map looks like.

CreateProxy (createProxy); createProxy (createProxy); createProxy (createProxy)

Refer, this method will be analyzed later, the local introduction is not in-depth, that is, go to the previous exporterMap service exposed to get services.

If it is not local, it must be remote. Next, it is to determine whether to directly connect the provider point-to-point or to get the provider information through the registry and then connect the provider. We analyze the situation of configuring the URL. That’s the address of the registry.

Then there is the case where the URL is not configured, which is where the registry must introduce remote services.

The resulting URL will look something like this.

As you can see, this part is actually assembling the URL based on various parameters, because our adaptive extension needs to be based on the parameters of the URL.

So let me draw a picture here, just to give you a sense of it.

This is actually the whole process, a brief description is to check the configuration, build a map through the configuration, then use the map to build THE URL, and then use the protocol on the URL to call the corresponding protocol. Refer using the adaptive extension mechanism to get the corresponding invoker.

When there are multiple urls, the invoker is iterated and then encapsulated by a StaticDirectory, and then merged through the cluster to expose only one invoker.

It then builds the proxy that encapsulates the invoker return service reference, which Comsumer then calls.

From the diagram and the summary above, we can see the general process of service introduction, but there are still many details, such as how to get the address of the Provider from the registry, what is inside the invoker? Don’t worry, let’s keep watching.

As you can see in the previous screenshot, the protocol is registry, so RegistryProtocol#refer is used. Let’s look at this method.

Basically, get the registry instance and call doRefer for the actual refer.

This method is critical because you can see that the RegistryDirectory generated plugs the registry instance and implements the NotifyListener interface itself, so the registry listening is actually handled by this guy.

We register our information with the registry and subscribe to the Providers node, Configurators node, and Routers node. Once we subscribe to the Registry, the Registry will receive the information from these nodes. This triggers the generation of DubboInvoker, the Invoker for remote calls.

The Invoker is then rewrapped by the Cluster, so that a service may have multiple providers, eventually logging this information in the ProviderConsumerRegTable, and then returning to the Invoker.

So we know that Conusmer registers its information with the registry in RegistryProtocol#refer and subscribes to some information about the Provider and configuration. Let’s look at the information returned by subscription.

DubboProtocol# refer can be triggered by listening on the Provider after receiving the message. (Dubbo protocol is used here)

Finally, we get the information about the remote Provider from the registry and introduce the service.

The focus here is on getClients, which is ultimately used to make network calls to remote services. GetClients is used to obtain an ExchangeClient client instance that relies on Netty for network communication, and as you can see, the default is shared connections.

GetSharedClient, I’m not going to analyze it, is to find the client by the remote address, the client has a reference count function, if the remote address does not have a client call initClient, let’s look at the initClient method.

And this connect ultimately returns HeaderExchange lient with the NettyClient encapsulated inside.

Then the resulting Invoker looks like this. You can see that a lot of information is recorded, and basically it has all the information you need. I’m going to take the case where the corresponding service has only one URL, and multiple urls are just another layer of encapsulation using Directory and cluster.

Return (T) proxyFactory.getProxy(invoker); Returns a proxy object, which I won’t analyze.

At this point, the whole process is analyzed, I don’t know if you are clear? Let me supplement the previous diagram to give you a complete process again.

summary

I believe that the analysis of the whole process is not difficult, summed up is nothing more than through the configuration of THE URL, and then get the implementation of the service through adaptive introduction of classes, if it is a registry will register their own information to the registry, and then subscribe to the registry related information, get the REMOTE provider IP and other information, The netty client is used for connection.

In addition, directory and cluster are used to shield, fault tolerance and load balancing of multiple service providers at the bottom level, which will be analyzed in detail later in the article. Finally, invoker is encapsulated and then proxy class is obtained through dynamic proxy encapsulation, so that interface callers can call methods without awareness.

The last

Today look down this article believe that everyone on the introduction of the service should have a clear understanding, but still many details I don’t have a analysis, such as some of the filter chain assembly, this is actually inside the services exposed articles have already said, the same service reference also have a filter chain, but space is not opened, grasp the main line matters.

So far, I have taken you through the overall concept and general process of Dubbo, introduced the Dubbo SPI mechanism, and analyzed the service exposure process and service introduction process. The specific details still need to be explored by ourselves. I have talked about the general process almost.

Dubbo series is coming to an end. Although I know that every time I write about hardcore technology, I still want to finish this series. Thank you for your support.

I’m Aobing, and the more you know, the more you don’t know, and I’ll see you next time!

Talented people’s [three lian] is the biggest power of aobing’s creation, if there are any mistakes and suggestions in this blog, welcome talented people to leave a message!


This article is constantly updated. You can search “Santaizi Aobing” on wechat and read it for the first time. Reply [Information] There are the interview materials and resume templates for first-line big factories prepared by me.