Distributed application scenarios have high concurrency , High scalability and high performance requirements . Also involves , serialize / Deserialization , The Internet , Problems with multithreading and design patterns . fortunately Dubbo The framework encapsulates the above knowledge , Let programmers focus on the business .
The picture is from Pexels
In order to better understand and use Dubbo, Let's introduce today Dubbo The main components and implementation principle of .
Dubbo It's a high performance Java RPC framework . It implements interface proxy oriented RPC call , Service registration and discovery , Load balancing , Fault tolerance , Expansibility and other functions .
Dubbo It is roughly divided into three layers , Namely ：
The business layer
- Remoting layer
Dubbo The three-tier structure of
As you can see from the above figure , The three-tier structure contains Dubbo Core components . Their basic functions are as follows , For more commonly used components , It will be explained in detail later .
Component function list
Here's a list of these components , To have a perceptual understanding of . Specific development time , Know what components to use .
Dubbo Call workflow
Dubbo Framework is used to deal with distributed system , Service discovery and registration as well as call problems , And manage the calling process .
It says Dubbo Layered framework of , The workflow below shows how they work .
Dubbo Service call flow chart
Workflow involves service providers （Provider）, Registry Center （Registration）, The Internet （Network） And service consumers （Consumer）：
When the service provider starts , The service will be instantiated by reading some configuration .
Proxy Encapsulate the service invocation interface , It is convenient for callers to call . Client acquisition Proxy when , It can be like calling a local service , Call remote service .
Proxy When packaging , Need to call Protocol Define protocol format , for example ：Dubbo Protocol.
take Proxy Encapsulated into Invoker, It's an instance of a real service call .
take Invoker Turn it into Exporter,Exporter Just put Invoker There's a layer of packaging , To expose yourself in the registry , Convenient for consumers to use .
Will be packed Exporter Register with the registry .
Serve consumers and set up good examples , You will go to the service registry to subscribe to the metadata of the service provider . Metadata includes services IP And port and call mode （Proxy）.
Consumers will get it through Proxy To call . Through the service provider packaging process, we can know ,Proxy Actually packed Invoker Entity , So you need to use Invoker To call .
stay Invoker Before you call , adopt Directory Get service provider's Invoker list . The same service may appear in distributed services , Distributed on different nodes .
Learn from routing rules , Which nodes does the service need to get from .
Invoker During invocation , adopt Cluster Fault tolerance , If a failed policy is encountered, try again .
in call , Because multiple services may be distributed to different nodes , Will be through LoadBalance To achieve load balancing .
Invoker You need to go through Filter, It's a filter chain , Used to handle context , Current limiting and counting work .
Generate filtered Invoker.
use Client Data transfer .
Codec Will be based on Protocol Defined protocol , Construct the protocol .
Constructed data , By serializing Serialization To the service provider .
Request Has reached the service provider , It will be allocated to the thread pool （ThreadPool） Intermediate processing .
Server When you get the request, find the corresponding Exporter（ contains Invoker）.
because Export Will also be Filter under wraps
adopt Filter Get later Invoker
Last , Call the service provider entity .
The above call step has gone through so many processes , There is Proxy,Invoker,Exporter,Filter.
In fact, they are different representations of calling entities at different stages , It's essentially the same thing , Use different entities in different scenarios .
for example Proxy Is used to make it easier for callers to call .Invoker Is used when calling a specific entity .Exporter To register with the registry and so on .
We will analyze the specific process later . If you don't have enough time to read the full text , You can save the picture above .
Service exposure implementation principle
In the service call process mentioned above , The start service provider initializes , Will be exposed to other service calls . Service consumers also need to initialize , And register yourself in the registry .
Service providers and service consumers expose Services
First, let's look at the overall mechanism by which service providers expose Services ：
Service providers expose service processes
The big picture at the beginning lists Config Core components , When the service provider initializes , Will pass Config In the component ServiceConfig Read the configuration information of the service .
There are three forms of this configuration information , Namely XML file , annotation （Annoation） And property files （Properties and yaml）.
After reading the configuration file to generate the service entity , Will pass ProxyFactory take Proxy convert to Invoker.
here ,Invoker Will be defined Protocol, And then it's packaged as Exporter. Last ,Exporter It will be sent to the registry , Registration information as a service . The above process is mainly through ServiceConfig Medium doExport complete .
The following is the source code analysis of multi protocol and multi registry ：
doExportUrlsFor1Protocol Method -1
doExportUrlsFor1Protocol Method -2
The above intercepts the code fragment of the service provider exposing the service , From the annotation, the whole exposure process is divided into seven steps ：
Read other configuration information to map in , For the back construction URL.
Read global configuration information .
Configuration is not remote, That is to expose local services .
If the monitoring address is configured , Then the service call information will be reported .
adopt Proxy Turn it into Invoker,RegistryURL It's the address of the registry .
After exposing the service , Register service information with the registry .
There is no registry directly exposing Services .
Once the service is registered with the registry , The registry will pass RegistryProtocol Medium Export Method to expose the service , And do the following in turn ：
Commission specific agreements for service exposure , establish NettyServer Listening port , And keep service instances .
Create a registry object , Create the corresponding TCP Connect .
Register metadata to registry .
subscribe Configurators node .
If you need to destroy the service , Need to close port , Log off service information .
After the exposure of service providers, let's look at service consumers .
Service consumer consumption service mechanism
The service consumer first holds Invoker, And then put Invoker A dynamic proxy reference converted to a user interface .
The entry point of the framework for service reference is in ReferenceBean Medium getObject Method , Will convert the entity to ReferenceBean, It's integrated with ReferenceConfig Class .
Let's have a look here createProxy Source code ：
getProxy code snippet 1
getProxy code snippet 2
As can be seen from the above code fragment , When a consumer service invokes a service provider , Did the following ：
Check if it's the same JVM Internal references .
If it's the same JVM References to , Use it directly injvm The protocol gets instances from memory .
After the registration center address , add to refer Store service consumption metadata information .
Single registry consumption .
Get the registry services in turn , And add to Invokers In the list .
adopt Cluster Will be multiple Invoker Convert to a Invoker.
hold Invoker Convert to interface proxy .
After that, the service was exposed , Let's go back to the registry .Dubbo The registration and discovery of services in distributed environment is realized through the registry .
Its main functions are as follows ：
Dynamic load service . Service providers go through the registry , Expose yourself to the consumer , No need for consumers to update profiles one by one .
Dynamic discovery services . Consumers dynamically perceive the new configuration , New rules and service providers .
Parameter dynamic adjustment . Support dynamic adjustment of parameters , The new parameters are automatically updated to all service nodes .
Unified service configuration . Unified connection to the registry service configuration .
Configuration center workflow
Register call flow chart
Let's take a look at the flowchart of the registry call ：
Provider （Provider） Startup time , Will write their own metadata information to the registry （ Call mode ）.
consumer （Consumer） Startup time , It will also write its own metadata information in the registry , And subscribe to service providers , Routing and configuration metadata information .
Service Governance Center （duubo-admin） Startup time , Will subscribe to all consumers at the same time , Provider , Routing and configuration metadata information .
When a provider leaves or a new provider joins , The registry will inform consumers and service governance centers of changes .
How registry works
Dubbo There are four implementations of registries , Namely ZooKeeper,Redis,Simple and Multicast.
Here is a brief introduction ZooKeeper The implementation of the .ZooKeeper Is responsible for coordinating service applications .
It's stored in a tree file ZNode stay /dubbo/Service There are four directories under the directory , Namely ：
Providers Below directory , Hosting service providers URL And metadata .
Consumers Below directory , Store consumer's URL And metadata .
Routers Below directory , Store the consumer's routing strategy .
Configurators Below directory , Store multiple services for dynamic configuration of service providers URL Metadata information .
The first time the client connects to the registry , Will get the full amount of service metadata , Includes information about service providers and service consumers as well as routing and configuration .
according to ZooKeeper Client-side features , Will be corresponding to ZNode Register a Watcher, At the same time, let the client and registry keep TCP A long connection .
If the metadata information of the service changes , The client will receive the change notification , Then go to the registry to update the metadata information . Change according to ZNode Version changes in the node .
Dubbo Cluster fault tolerance
Cluster,Directory,Router,LoadBalance The core interface
Distributed services are mostly in the form of clusters ,Dubbo No exception . When the consumer service initiates the call , It will involve Cluster,Directory,Router,LoadBalance Several core components .
Cluster,Directory,Router,LoadBalance Calling process
Let's see how they work first ：
① Generate Invoker object . according to Cluster The difference in realization , Generate different types of ClusterInvoker object . adopt ClusertInvoker Medium Invoker Method to start the calling process .
② Get the list of callable Services , Can pass Directory Of List Method to get . Here are two ways to get the list of services .
Namely RegistryDirectory and StaticDirectory：
RegistryDirectory： It's dynamic Directory Realization , Will be automatically updated from the registry Invoker list , Configuration information , The routing list .
StaticDirectory： it yes Directory The static list implementation of , Will the incoming Invoker The list is encapsulated as static Directory object .
stay Directory Get all Invoker After the list , Will call the routing interface （Router）. According to the different policies configured by users, the Invoker List to filter , Only those that conform to the rules are returned Invoker.
Suppose the user configures the interface A Call to , It's all used IP by 192.168.1.1 The node of , be Router It will automatically filter out the rest Invoker, Only return 192.168.1.1 Of Invoker.
Here is an introduction RegistryDirectory The implementation of the , It passes through Subscribe and Notify Method , Subscribe to and listen to registry metadata .
Subscribe, Subscribe to something URL Update of .Notify, Listen according to the subscription information . There are three types of information , To configure Configurators, route Router, as well as Invoker list .
The administrator will pass dubbo-admin modify Configurators The content of ,Notify Listening to this information , Just update the local service Configurators Information .
Empathy , Routing information updated , The service local routing information will also be updated . If Invoker The call information of has changed （ Service provider invocation information ）, Will update the local Invoker Information .
Notify Listen to three types of information
Generated by the first three steps Invoker You need to call the final service , But services may be distributed on different nodes . therefore , Need to go through LoadBalance.
Dubbo There are four load balancing strategies for ：
Random LoadBalance, Random , According to the weight set random probability to do load balancing .
RoundRobinLoadBalance, polling , Set the polling ratio according to the weight after the Convention .
LeastActiveLoadBalance, Call... According to the active number , The number of times of being called is higher if the activity is poor . With the same level of activity Invoker Make random calls .
ConsistentHashLoadBalance, Uniformity Hash, Requests with the same parameters are always sent to the same provider .
The last part RPC call . If an exception occurs in the call , Different fault tolerance strategies are provided for different exceptions .Cluster Interface defined 9 Fault tolerant strategy , These policies are completely transparent to users .
Users can go to <dubbo:service>,<dubbo:reference>,<dubbo:consumer>,<dubbo:provider> Pass on label Cluster Property settings ：
Failover, There was a failure , Try another server now . You can set the number of retries .
Failfast, After the request failed , Return exception result , No retry .
Failsafe, Something unusual happened , Direct to ignore .
Failback, After the request fails , Put the failure record in the failure queue , Scan the queue through timed threads , And try again regularly .
Forking, Try to call multiple identical services , Any one of these services returns , And immediately return the result .
Broadcast, Broadcast calls all services that can be connected , Any service returned an error , On the task call failed .
Mock, When the response fails, a fake response result is returned .
Available, Find all service lists by traversing , Find the first node that can return the result , And return the result .
Mergable, Merge multiple node requests to return .
Dubbo The remote invocation
Service consumers are fault tolerant ,Invoker list , After routing and load balancing , Would be right Invoker To filter , After through Client code , Serialize to the service provider .
Filter , Send a request , code , Serialization is sent to the service provider
As can be seen from the figure above, before and after the service consumer invokes the service provider , Will be called Filter（ filter ）.
The corresponding filters can be configured for consumers and providers , Because the filter is in RPC It will be called during execution , So in order to improve performance, you need to configure .
Dubbo The system has its own system filter , Service providers have 11 individual , Service consumers have 5 individual . Filters can be used by @Activate Notes , Or configuration file implementation .
Configuration files implement filters
The use of filters follows the following rules ：
Filter sequence , Filter execution is sequential . for example , The filtering order of user-defined filter will be after the system filter by default .
For example , Above picture filter=“filter01, filter02”,filter01 Filter execution is in filter02 Before .
Filter failure , If you don't want to use certain filters for certain services or methods , Can pass “-”（ minus sign ） To disable the filter . for example ,filter=“-filter01”.
Filter stack , If both the service provider and the service consumer are configured with filters , Then the two filters will be superimposed .
because , Each service supports multiple filters , And there's a sequence between the filters . So in design Dubbo Using decorator mode , take Invoker Layer by layer , A filter is added to each layer of packaging . When executing the filter, it's like opening one package after another .
After the call request is filtered , Will Invoker In the form of Client To call .Client It's going to be left to the bottom I/O Thread pool processing , It includes processing message read and write , serialize , Deserialization and other logic .
At the same time Dubbo The protocol encodes and decodes .Dubbo Based on the agreement TCP/IP agreement , Including protocol header and protocol body .
The main content of the transport protocol , Its significance is self-evident , It is from 16 Byte long packets consist of , Each byte contains 8 Binary bits .
The contents are as follows ：
0-7 position ,“ Magic number ” High position .
8-15 position ,“ Magic number ” Low position . The first two bytes of “ Magic number ”, Is used to distinguish two different requests . It's like in programming “;”“/” Symbols like that separate the two records .PS： Magic numbers are fixed “0xdabb” Express ,
16 position , The type of packet , because RPC The call is bidirectional ,0 Express Response,1 Express Request.
17 position , Call mode ,0 It means single item ,1 Two way .
18 position , Time signs ,0 To express a request / Respond to ,1 It's a heartbeat bag .
19-23 position , Serializer number , It tells the protocol how to serialize . for example ：Hessian2Serialization wait .
24-31 position , Status bit .20 Express OK,30 Express CLIENT_TIMEOUT Client timeout ,31 Express SERVER_TIMEOUT Server timeout ,40 Express BAD_REQUEST Wrong request ,50 Express BAD_RESPONSE Wrong response .
32-95 position , The unique number of the request , That is to say RPC The only ID.
96-127, The message body includes Dubbo Version number , Service interface name , Version service , Method name , Parameter type , Method name , Parameter type , Method parameter values and request extra parameters .
The service consumer will send the above service message body before calling , according to Dubbo Package the agreement . The framework calls DefaultFuture Object's get Method to wait .
When you're ready to send a request , To create Request object , This object will be stored in a static HashMap in , When the service provider has finished processing Request after , Will return Response Put it back Futures Of HashMap in .
stay HashMap You'll find the corresponding Request object , And back to the service consumer .
Service consumer request and response graph
After the protocol is packaged, the protocol needs to be encoded and serialized . I need to use Dubbo The encoder , The process is to transfer information into a stream of bytes .
Dubbo Protocol coding request objects are divided into use ExchangeCodec Two of them ,encodeRequest Responsible for encoding protocol header and encodeRequestData Encoding protocol body .
Similarly passed encodeResponse Encoding protocol header ,encodeResponseData Encoding protocol body .
Both service consumers and providers use decode and decodeBody Two ways to decode , The difference is that decoding may be in IO Thread or Dubbo Completed in thread pool .
although , The details of encoding and decoding are not expanded here , But the following points need to be noted ：
structure 16 Byte protocol header , In particular, you need to create the first two bytes of magic numbers , That is to say “0xdabb”, It's used to split two different requests .
Generate a unique request / Respond to ID, And according to this ID Identify request and response protocol packages .
Through the... In the agreement header 19-23 Bit description , serialize / Deserialization operation .
In order to improve processing efficiency , Every agreement will be placed in Buffer In dealing with .
When the service provider receives the request protocol package , Put it in first ThreadPool in , Then deal with... In turn .
Since the service provider is in the registry through Exporter The way to expose the service , Service consumers also use Exporter Called as an interface .
Exporter Yes, it will Invoker Packed , Take apart Invoker Conduct Filter After the filter chain is filtered , Then call the service entity . Last , Return information to service consumers .
Let's first understand Dubbo And several core modules , Introduce their responsibilities separately . And then through a simple example , The service consumer invokes the service provider , use Dubbo The workflow of the system connects the modules together .
Here 22 Step by step , Start with the initialization of service providers and service consumers , Yes Config and Proxy as well as Protocol,Invoker.
The registry serves as a bridge between the two , It plays the role of service discovery and registration , And it focuses on how to pass ZooKeeper The principle of implementing registry .
Before the service consumer invokes the provider , Need to pass through Cluster Fault tolerance mechanism ,Directory obtain Invoker list ,Router Find the routing information , Reuse LoadBalance Know the specific service .
Between calling service providers, we have not forgotten to pass Filter To filter , Through decorator mode Filter It can form a filter chain , Filter the conditions in turn .
For remote calls , You need to call the packaging protocol , in the light of Dubbo The agreement describes , And coding for the protocol / Decoding and serializing / The operation of deserialization .
After the service provider receives the request , Will put the request in ThreadPool Deal with one by one . adopt Exporter,Invoker,Filter Step by step , Finally, respond to the request .
Due to the limited space, many functions such as SPI,Merger There was no introduction to , I'll talk to you again when I have time .