My sister asked me: Dubbo cluster fault-tolerant load balancing

Preface

I believe that after the previous few articles, everyone has a clear understanding of the overall Dubbo process, including how the service is exposed, when the service is registered in the registry, how the service is introduced, the overall invocation process of the service, and so on.

However, there is another very important point that has not been discussed in depth, which is Dubbo's cluster fault tolerance.

Online services must be deployed in clusters. At least two are required to back up each other. Then the question is, which provider should the service consumer choose to call? What should I do if the call fails?

At this time, the cluster fault tolerance function comes in handy. Today we will analyze a wave of Dubbo cluster fault tolerance in depth.
My sister asked me: Dubbo cluster fault-tolerant load balancing

What is an invoker?

In fact, I have said this before, and I will review it again today, because it is really important.

In Dubbo, the invoker is actually an object with a calling function. What is encapsulated on the service exposure side is the real service implementation, and the real service implementation is encapsulated into an invoker.

At the service introduction end, the configuration information of the service provider is obtained from the registry, and then a piece of configuration information is encapsulated into an invoker. This invoker has the ability to remotely call. Of course, if the injvm protocol is used, the real or local call is taken.

Then there is a ClusterInvoker, which is also an invoker, which encapsulates the invokers generated by the service introduction and gives the cluster fault tolerance and other capabilities. This invoker is the invoker exposed to consumers.

So Dubbo is a unified model that encapsulates all the service objects that can be called into an invoker.

Today we are mainly talking about serving consumers, because cluster fault tolerance is implemented on the consumer side.
My sister asked me: Dubbo cluster fault-tolerant load balancing

What exactly is a service catalog?

The service directory is also the Directory. In fact, it was introduced before, but it was not described separately. It may not be clear to everyone. Let's take a look at it today.

What exactly is a service catalog? It seems that the name is a service catalog, through which remote services can be found?

Half right! You can find remote services through the service directory, but it is not a "directory", in fact it is a collection of a bunch of invokers,

As mentioned earlier, service providers will be deployed in clusters. All the same services will have multiple providers. Therefore, we will set up a service catalog to gather them. When you want to choose, you will choose from the service catalog.

And service providers are not static. For example, if a service provider is added to the cluster, then an invoker needs to be added to the corresponding service catalog, a service provider is offline, and the corresponding invoker needs to be deleted from the catalog. Modified configuration must also be updated.

So this service directory actually implements the function of monitoring the registry (referring to RegistryDirectory).
My sister asked me: Dubbo cluster fault-tolerant load balancing

This Node is left alone. It mainly depends on Directory. For normal operation, an abstract class is used to implement the Directory interface. The abstract class implements some public methods and defines the logic. Then the specific implementation is completed by the subclass. You can see that there are two The sub-categories are StaticDirectory and RegistryDirectory.

RegistryDirectory

Let's take a look at RegistryDirectory first, it is a dynamic directory, let's take a look at the specific structure.
My sister asked me: Dubbo cluster fault-tolerant load balancing

From the screenshot, you can see that RegistryDirectory stores the two service provider URLs of DemoService and the corresponding invokers.

And from the above inheritance structure, it can also be seen that it implements the NotifyListener interface, so it can monitor changes in the registry. When the configuration of the service center changes, RegistryDirectory can receive a notification of the change, and then refresh its Invoker list according to the configuration .

So there are three functions of RegistryDirectory:

  1. Get the list of invokers
  2. Monitor changes in the registry
  3. Refresh the invokers.

To get the list of invokers, the parent class abstract method doList implemented by RegistryDirectory aims to get the list of invokers, and its internal implementation is mainly to filter the layer method names and find the corresponding invokers by the method name.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Monitor the changes in the registry and realize the data changes in the registry by implementing the NotifyListener interface. This is actually subscribed when the service is introduced.

 public void subscribe(URL url) {
        setConsumerUrl(url);
        registry.subscribe(url, this); //订阅
    }

RegistryDirectory defines three collections, namely, invokerUrls, routerUrls, and configuratorUrls to process the corresponding configuration changes, and then convert them into objects.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Refreshing the Invoker list is actually doing a wave of operations based on the InvokerUrls that monitor changes, refreshInvoker(invokerUrls), and update the Invokers according to the configuration.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Simply put, first decide whether to disable all invokers based on the number of invokerUrls and whether the protocol header is empty. If not, convert the url to Invoker to get the mapping relationship of <url, Invoker>.

Then perform the conversion to obtain the mapping relationship of <method name, Invoker list>, then merge the Invokers of the same group, and assign the merged result to methodInvokerMap. This methodInvokerMap is the Map used in doList above.

So the methodInvokerMap is constructed during refreshInvoker, and then the methodInvokerMap is read when calling, and finally the useless invoker is destroyed.

StaticDirectory

StaticDirectory, this is used in multiple registries. It is a static directory, that is, it is fixed and will not increase or decrease. All Invokers are passed in through the constructor.

It can be simply understood that a reference we configured under a single registry may correspond to multiple providers, and then generate multiple invoices, we store them in the RegistryDirectory for management, in order to facilitate the call, only one invoice is exposed to the outside to encapsulate Internal multi-invoker situation.

The multiple registries will have multiple encapsulated invokers, which again faces a choice, so we use StaticDirectory to store these invokers for management, and then encapsulate them to expose only one invoker for easy calling.

It is static because multiple registries are written in the configuration, unlike services that can be changed dynamically.

The internal logic of StaticDirectory is very simple, that is, a list stores these invokers, and then the method of implementing the parent class simply returns the list without doing any operation.
My sister asked me: Dubbo cluster fault-tolerant load balancing

What is service routing?

Service routing is actually routing rules, which specify which service providers can be called by service consumers. Dubbo has three routes: ConditionRouter, ScriptRouter, and TagRouter.

The most commonly used is conditional routing, we will analyze conditional routing.

Conditional routing is composed of two conditions, in the format [service consumer matching condition] => [service provider matching condition], for example, the official website is host = 10.20.153.10 => host = 10.20.153.11.

This rule indicates that service consumers with IP 10.20.153.10 can only call services on machines with IP 10.20.153.11 and cannot call services on other machines.

This is called routing.

The routing configuration is also updated and constructed through the notify of RegistryDirectory, and then the routing call is to refresh the invoker, specifically when toMethodInvokers is called, service-level routing and method-level routing will be performed.
My sister asked me: Dubbo cluster fault-tolerant load balancing

The specific routing matching and expression parsing will not be in-depth. Interested students will understand by themselves. In fact, they know what this function does. Anyway, after routing filtering, consumers get remote services that can be called.

What is the use of Dubbo's Cluster?

We have already said that there is a service catalog, and the catalog has been filtered by routing rules. At this time, we still have a bunch of invokers. Consumers need to make a decision. So which invoker should I call?

What should I do if the selected invoker makes an error? As we mentioned earlier, this is the time for the cluster to appear. It will encapsulate this bunch of invokers into clusterInovker, and only one invoker will be called to consumers.

Then you can do various operations inside the clusterInovker, such as selecting an invoker, changing one if the call fails, and so on.

These details are encapsulated, and consumers cannot feel this complexity, so cluster is an intermediate layer that shields consumers from the service provider and simplifies the use of consumers.

It is also more convenient to replace various cluster fault tolerance measures.

There are many default cluster implementations of Dubbo, mainly the following:
My sister asked me: Dubbo cluster fault-tolerant load balancing

Each Cluster actually returns XXXClusterInvoker. Let me give you an example of FailoverCluster.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Just come down and we will go through each Cluster.

FailoverClusterInvoker

This cluster implements the automatic failover function. Simply put, if a remote call fails, it will immediately change to another one, of course, there are retries.
My sister asked me: Dubbo cluster fault-tolerant load balancing

You can see that the doInvoke method first obtains the number of retries, and then makes a loop call based on the number of retries, catching the exception, and then retrying after failure.

Each cycle will select an Invoker through load balancing, and then make remote calls through this Invoker. If it fails, it will record the exception and try again.

This select actually has a sticky process, that is, it will record the last selected invoker, so that each call will not always change the invoker. If there is no invoker last time, or the previous invoker goes offline, load balancing will be performed select.

FailfastClusterInvoker

This cluster will only make one remote call. If an exception is thrown immediately after failure, it will fail quickly. It is suitable for calls that do not support idempotence.
My sister asked me: Dubbo cluster fault-tolerant load balancing

As you can see from the code, it is very simple to select an invoker through load balancing, then initiate the call, and throw an error if it fails.

FailsafeClusterInvoker

This cluster is a failure-safe cluster, that is, the call error is only recorded in the log, and then an empty result is returned, which is suitable for operations such as writing to the audit log.
My sister asked me: Dubbo cluster fault-tolerant load balancing

As you can see, the code is very simple. If you throw an error, it will log and return an empty result.

FailbackClusterInvoker

This cluster will record the call after the call fails, and then return an empty result to the service consumer, and will retune the failed call through a scheduled task.

Suitable for best-effort scenarios such as message notification.
My sister asked me: Dubbo cluster fault-tolerant load balancing

It looks like a lot of code, but the logic is very simple.

When the call fails, it returns an empty result and adds it to failed, and there will be a timed task that will periodically call the call in failed. If the call is successful, remove the call from failed.

ForkingClusterInvoker

This cluster will make concurrent calls to all invokers through the thread pool at runtime. As long as a service provider successfully returns the result, the doInvoke method will immediately end its operation.

It is suitable for read operations with high real-time requirements.
My sister asked me: Dubbo cluster fault-tolerant load balancing

BroadcastClusterInvoker

This cluster will call all the invokers one by one at runtime, and then at the end it will judge if one of the calls throws an error, it will throw an exception.

It is suitable for notifying all providers to update local resource information such as cache or log.
My sister asked me: Dubbo cluster fault-tolerant load balancing

AbstractClusterInvoker

This is actually their parent class, but AvailableCluster internally returns AbstractClusterInvoker. This is mainly used in multiple registries. It is simpler, just use whichever works.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Summary Cluster

You can see that there are many cluster implementations above, which are applicable to different scenarios. This is actually a good abstraction. The addition of this middle layer shields the service consumers from the details of the cluster call, and you can choose more appropriate in different scenarios. achieve.

Of course, you can customize the implementation and extend it yourself to customize the link call scheme suitable for your business.

Load balancing in Dubbo

Load balancing is actually divided into hardware load balancing and software load balancing. Everyone should be familiar with software load balancing, such as Nginx.

Dubbo also has its own load balancing, LoadBalance. As we mentioned earlier, service providers are generally deployed in clusters. Although this cluster exposes an invoker for consumers to call, it has to judge when it is actually called. Specifically, which service provider is to be called, then load balancing is on the scene.

Therefore, load balancing in Dubbo is used to select a suitable service provider to call consumers. By default, Dubbo provides a variety of load balancing algorithms:
My sister asked me: Dubbo cluster fault-tolerant load balancing

Let's look at it one by one. Although this involves algorithms, it has little effect. It is okay to understand the meaning roughly. Of course, it is best to understand everything. Let's first look at the parent class of these implementation classes.

AbstractLoadBalance

These implementation classes all inherit from this class, which implements the LoadBalance interface and encapsulates some common logic. It is also a template method and familiar recipe.
My sister asked me: Dubbo cluster fault-tolerant load balancing

The logic is very simple. Let’s take a look at the method of calculating weights. This is a common logic. In fact, it is for service preheating. We know that the cache has preheating, and the JIT also has preheating. The response to the service is that the service needs to be preheated.

When the service is just started, you can't let it load too high next time, you have to let it warm up slowly, plus load, so this method will judge the running time of the service to reduce the power of the service, which is an optimization method.
My sister asked me: Dubbo cluster fault-tolerant load balancing

RandomLoadBalance

This algorithm is weighted random, and the idea is actually very simple. Let me give an example: Suppose there are two servers A and B. I want 70% of requests to fall on A and 30% of requests to B. This At that time, I just need to create a random number generation range in [0,10), this 10 is derived from 7+3.

Then if the random number obtained is in [0,7), server A is selected, and if it is in [7,10), server B is selected. Of course, the probability will be correct if the random number is well distributed.
My sister asked me: Dubbo cluster fault-tolerant load balancing

Now let's take a look at how Dubbo is realized. The thought is the above thought.
My sister asked me: Dubbo cluster fault-tolerant load balancing

It can be seen that it is quite simple. For example, if the random number is 5, then 5-7 <0, so A is selected. If the random number is 8, then 8-7 is greater than 1, and then 1-3 is less than 0. So this When I chose B.

This is the load balancing implementation adopted by Dubbo by default.

LeastActiveLoadBalance

This is the least active load balancer. You can know from the name to select the provider with the least active calls to make calls. The fewer active calls means it is now very easy, and the active numbers are all added up from 0 to make a request The number of actives is +1, and the number of actives for a request is processed is -1, so a small number of actives can also show that the processing is faster.

This is actually the idea of ​​the least active number, and Dubbo uses the weight to judge when the active number is equal. This weight is actually the same as the implementation of RandomLoadBalance.

I won’t post the code. Simply put, the process is to first traverse the list of invokers to find the Invoker with the smallest number of actives. If there are multiple Invokers with the same minimum active number, record the subscripts of these Invokers and add their weights. For weight selection.

If there is only one invoker with the smallest active number, just return directly.

ConsistentHashLoadBalance

This is a consistent Hash load balancing algorithm. The consistent Hash must be familiar to everyone. The common consistent Hash algorithm is proposed by Karger, which is to set the hash value space to [0, 2^32-1], and it is a loop Ring shape.

Generate a hash value from the server's IP and other information, project this value on the ring as a node, and then when the key is searched, find the first node with a hash value greater than or equal to this key clockwise.

Generally speaking, virtual nodes will be introduced to make the data more dispersed and avoid data tilt overwhelming a node. Take a look at a graph on the official website.

My sister asked me: Dubbo cluster fault-tolerant load balancing
The overall implementation is not difficult, it is the logic mentioned above, and the circle is implemented using treeMap, through tailMap to find the first invoice greater than or equal to, if not find the instructions to take the first one, directly assign The firstEntry of treeMap.

Then Dubbo has 160 virtual nodes by default. The overall hash is method level, that is, each method of a service has a ConsistentHashSelector, and the hash is performed according to the parameter value, which means that the load balancing logic is only affected by the parameter value , Requests with the same parameter value will be assigned to the same service provider.

Let's first look at the implementation of consistent hash, this virtualInvokers is TreeMap.
My sister asked me: Dubbo cluster fault-tolerant load balancing
Then let's take a look at how to obtain the invoker through consistent hash.
My sister asked me: Dubbo cluster fault-tolerant load balancing

RoundRobinLoadBalance

This is a weighted round-robin load balancing. We all know that round-robin. This weighting is also weighted round-robin. For example, there are two servers A and B. The order of polling calls is A, B, A, B. ..., if the weight is added, the weight of A to B is 3:1, then the current calling order is A, A, A, B, A, A, A, B...

The reason for weighting is that individual servers have better performance, so I want to poll more.

However, in this way, you can see that A is requested for the first three times, and then B. It is not even. Assume that it is 90:80. The first 90 times hit A. A is too busy and B is out of space. So it needs to be smoothed.

This kind of smooth weighted polling is better, such as A, B, A, A, B, A.... Simply put, it is polling in disorder.

Dubbo's weighted polling has gone through the above-mentioned weighted polling to smooth weighted polling process.

The specific code is not analyzed, it is more convoluted. Anyway, it means this. Dubbo refers to the smooth weighted polling done by Nginx.

I personally think this is similar to the first RandomLoadBalance.

Concatenate them

So far, including service catalogs, clusters, and load balancing. I think everyone already knows what they are used for. Then there are the differences and applicable scenarios of Dubbo's default implementation classes. Let me talk about this in series. Several cooperate to complete the cluster fault-tolerant load balancing function.

First look at this picture on the official website, it is very clear, and then I will use words to explain it again.
My sister asked me: Dubbo cluster fault-tolerant load balancing

First, when the service is introduced, multiple remote calls are stuffed into the Directory, and then the directory is encapsulated through Cluster, which provides various fault tolerance functions, such as FailOver, FailFast, etc., and finally exposed to consumers is one invoker.

Then when consumers call, they will get the list of invokers in the directory. Of course, they will be filtered by routing. After these invokers are obtained, loadBalance will perform load balancing to select an invoker and finally initiate the call.

This process is actually initiated within the Cluster, so various fault-tolerant measures can be used in the case of an error in the initiation of the call.

At last

My sister asked me: Dubbo cluster fault-tolerant load balancing

At this point, the entire Dubbo system should be familiar. You can look back at the previous article to consolidate it, and go over it again in your mind. This entire system has been established in your mind and is basically stable.

In the follow-up Dubbo, I will put out the last interview dry goods version to end. In fact, the period of writing dubbo is very tangled for me, because there are really few people who write technical dry goods, but I still want to keep writing it, saying To be honest, let’s not say that you don’t like to read it. I’m very dry in writing. Sometimes it’s really hard to stick to it. But I think that when you want to read it in the future, I think that Ao Bing seems to have written it, and it’s enough to look through the historical records. Up.

I don’t care about everlasting time, I only care about having it once and loving it. I’m Ao Bing. Thank you for your Sanlian. The more you know, the more you don’t know. See you next time.

Guess you like

Origin blog.51cto.com/14689292/2545233