preface

Dubbo’s service exposure, reference and consumption, as well as Dubbo’s SPI mechanism, were briefly introduced in the last article

Of course, some technical points are only a glimpse, such as service exposure, we just said what this thing means, what it represents, many fairies may still be confused, don’t worry, your confused points I will introduce one by one, take you away from the fog to see the light of day

Today we are going to analyze the service exposure process of Dubbo. This process is one of the core processes of Dubbo, because the general process of Dubbo is service exposure -> service reference -> service consumption. Of course, it also involves registration discovery, load balancing, cluster fault tolerance, etc. We will from the source point of view to give you the analysis of the service exposed process, of course, we do not have to worry about, we will not put the code analysis so fine, WE do not have the time and energy, so we do not worry about reading do not understand, I will also say with you about the concluding words to help you to understand

Dubbo can be called in three ways:

1. Annotation @reference calls (this is the most common)

@reference (version = "1.0.0")private UserService UserService;Copy the code

2. Specify dubbo’s service port for the call

String url = "dubbo: / / 192.168.1.102:10086 / ccom. Dayu. API. The business. The cache. IMerchantRedisCache? Version = "1.0.0; // Change different Dubbo service exposed IP address & port ReferenceBean<IMerchantRedisCache> ReferenceBean = new ReferenceBean<IMerchantRedisCache>(); referenceBean.setApplicationContext(applicationContext); referenceBean.setInterface(IMerchantRedisCache.class); referenceBean.setUrl(url); try { referenceBean.afterPropertiesSet(); IMerchantRedisCache merchantRedisCache = referenceBean.get(); PlaneResDto<MerchantItem> resDto = merchantRedisCache.getInDubbo(419248146L); JsonPrinter.printJson(resDto); Assert.assertTrue(SysCode.SUCCESS.equals(resDto.getRspCd())); } catch (Exception e) { e.printStackTrace(); }Copy the code

3. Obtain the information about the service provider from Zookeeper and invoke the service

ZkClient ZkClient = new ZkClient (ZKServers, 10000100, 00, new SerializableSerializer ()); List<String> lists = zkClient.getChildren("/dubbo/com.yc.api.business.cache.ICacheFacade/providers");Copy the code

URL

Meaning of URL unified model

Most of us are familiar with the concept of URLS until we talk about Dubbo. Uniform Resource Locators are probably the best known RFC specification. They are very simple to define. Available resources on the Internet can be expressed as simple strings. Uniform Resource Locator (URL)

A standard URL format can contain at most the following sections

protocol://username:password@host:port/path? key=value&key=valueCopy the code

Let’s look at the URL in Dubbo:

public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) { if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(password)) { throw new IllegalArgumentException("Invalid url, password without username!" ); } this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); this.urlParam = URLParam.parse(parameters); }Copy the code

Protocol: Indicates various protocols in Dubbo, such as Dubbo, Thrift, HTTP, and ZK

Username /password: indicates the username and password

Host /port: indicates the IP address or port number of the host

Path: indicates the interface name

Parameter: indicates a parameter key-value pair

For URL in Dubbo, some people understand it as configuration bus, while others understand it as unified configuration model. Although the terms are different, they both express the same meaning. Such URL is regarded as a public contract in Dubbo, and all extension point parameters contain URL parameters. Urls serve as context information throughout the extension point design architecture.

Before there is no URL, Parameters can only be passed as a string, constantly parsed and assembled, resulting in the same type of interface, Parameters sometimes Map, sometimes Parameters class wrapped:

export(String url) createExporter(String host, int port, Parameters params)
Copy the code

Using the URL consistency model:

export(URL url) createExporter(URL url)
Copy the code

In the latest Dubbo code, we can see a lot of use of urls to pass contextual information, and the benefits are obvious:

1. Coding specification, making the code easy to write and read

2. Strong scalability, URL is equivalent to a set of parameters (equivalent to a Map)

3. Unified model, which can be used by all extension modules as the expression of parameters

Services expose the main process

Service exposure main process, can be roughly divided into two perspectives to analyze the process, we first simple understanding, I take you step by step to see the source code:

Objective process perspective:

Front work, mainly used to check parameters, URL assembly.

Exporting services includes exposing services to local (JVM) and exposing services to remote.

Register services with a registry for service discovery.

Object conversion Angle:

First, the implementation of the service is encapsulated as an Invoker, which encapsulates the implementation class of the service.

Encapsulate the Invoker as a Exporter and cache it, using the Invoker URL as the key.

The Server starts, listening on the port.

Initialization, it belongs to the entrance, we’ll look at the ServiceBean use this class, here say a small episode, is found by comparing the latest inherited ApplicationEventPublisherAware interface, Older versions inherit the ApplicationListener interface

By the way, the source address is:gitee.com/dayumm

Most of the blog videos show that the export method exposed by the service is rooted in the Export method of ServiceConfig. ServiceBean inherits ServiceConfig, The export method of ServiceConfig is finally called using the onApplicationEvent method that implements the ApplicationListener interface

However, the latest version of the implementation of ApplicationEventPublisherAware didn’t call the export ServiceConfig method, just ServiceBean upon completion of export when using this interface to issue a exported event, The post-exposure event is not the exposure event

So new inheritance ApplicationEventPublisherAware this interface if there is no direct effect on service exposure process. Where does the ServiceConfig export method get called?

Traced back found DubboBootstrapApplicationListener, this class inherits the ApplicationListener and ApplicationContextAware, and the last call to DubboBootStrap method

Find it in the start method, there is a line exportServices, as the name indicates the export service or expose service, click to see exportServices

ExportServices calls the export method of ServiceConfigBase. Let’s see what ServiceConfigBase is

Open the structure diagram of ServiceConfig and take a look:

This is an abstract method that calls the export method in ServiceConfig. We are going to focus on the doExport method in Export

As you can see, Dubbo supports multiple registries and supports multiple protocols. A service that has multiple protocols needs to be exposed, such as Dubbo and Hessian, so that the service needs to be exposed to multiple registries (if any) using both protocols.

Let’s go to doExportUrlsFor1Protocol, which is a long method, so we won’t look at it step by step, slide to the end of the method here:

Local exposure and remote exposure

Keep reading the source code. It’s almost over. Go

** Local exposure: invoked services are directly called locally by the same JVM

The export method of Protocol is annotated with @Adaptive annotation, so the proxy class will be generated. Then the proxy class will know the specific Protocol according to the URL parameter in Invoker, and then select the corresponding implementation class to export through the Dubbo SPI mechanism. This method calls InjvmProtocol#export

InjvmProtocol: Invoker is actually created by Javassist. The process of creating Invoker proxyFactory.getInvoker is not discussed. Why dubbo uses JavAssist instead of JDK dynamic proxies is because JavAssist is fast

Why encapsulate invoker: The purpose of encapsulating Invoker is to mask the details of the call and expose an executable so that the caller can simply use it and invoke it. It may be a local implementation, a remote implementation, or a cluster implementation

Local exposure exists because it is possible for the same JVM to have internal references to its own services, so exposed local services can consume services of the same JVM directly when invoked internally, avoiding network communication.

Take a look at the sequence diagram for a wave of exportLocal:

** Remote exposure: The service of this machine is exposed to consumers of other machines **

Looking at the DubboProtocol#export method and its internal openServer() method, you can see that the key here is to open the Server. RPC must be called remotely, and we are using NettyServer to listen for the service.

To a more detailed place I will not analyze, you are interested in pulling the code to see, to understand the general process and the design idea is the most critical

conclusion

Well, that’s all. I’m xiaoyuxian, your learning partner

I hope that one day I can support myself by writing, and I am still honing my skills. This time may be many years. Thank you for being my original reader and communicator. Please believe that as long as you give me a love, I will eventually return you a page of love.

Thank you again for reading here, I will continue to update the technical articles and some records of the soul of life articles, if you feel good, think [big fish students] something, please like, pay attention to, share three

Oh, right! The subsequent update of the article I will be put here in time, welcome to click to watch, are dry articles ah, suggest collection, at any time to check

Github.com/DayuMM2021/…