Dubbo Source Learning (v) The process of Dubbo exposing services

Source: Internet
Author: User
Tags unsupported jboss

Beginners Dubbo The source code, only to do the experiment to learn, do for their own study of a record, you crossing if you feel that there is a mistake or understanding of the wrong, please tell me in the message area, learn from each other. I have limited ability, please advise when the great God enters.

Dubbo uses the NIO asynchronous communication, the communication protocol defaults to Netty, of course, you can also choose Mina,grizzy. In the service side (provider) at the start of the main is to turn on Netty Monitoring, register the service node on the zookeeper, processing consumer requests, return to the processing of the message to consumers, consumers use the service is mainly the node of the subscription service, Monitoring Zookeeper node directory, The service side changes when zookeeper will be pushed to the consumer, the consumer re-caches the service address and so on. The service person, the consumer, the zookeeper all are the long connection.

Look at the Dubbo source to see the process of service exposure, service exposed to the entry: Com.alibaba.dubbo.config.serviceconfig#export method, the code is as follows:

Whether to delay exposure        if (delay! = NULL && delay > 0) {            thread thread = new Thread (new Runnable () {public                void Run () {                    try {                        thread.sleep (delay);                    } catch (Throwable e) {                    }                    doexport ()}            );            Thread.setdaemon (true);            Thread.setname ("Delayexportservicethread");            Thread.Start ();        } else {            //No delay exposure, direct exposure to            doexport ();        }
On the code whether it is delayed exposure or direct exposure to the call method is: Doexport (), Doexport will be resolved after the configuration to do another check, the core code you can see Dubbo source, the following list a small number of

/* Check the default settings, if the XML is not configured <dubbo:provider mainly from the system environment variable to find out if there is a corresponding provider configuration */Checkdefault        ();                The content set below is basically null if <dubbo:provider is not configured (provider! = NULL) {if (application = = null) {            application = Provider.getapplication ();            } if (module = = null) {module = Provider.getmodule ();            } if (registries = = NULL) {registries = Provider.getregistries ();            } if (monitor = = null) {monitor = Provider.getmonitor ();            } if (protocols = = NULL) {protocols = Provider.getprotocols ();                }} if (module! = null) {//registries will generally configure if (registries = = null) {            Registries = Module.getregistries ();            } if (monitor = = null) {monitor = Module.getmonitor (); }} if (Application! = null) {//application general also configures if (registries = = NULL) {registries = APPLICATION.G            Etregistries ();            } if (monitor = = null) {monitor = Application.getmonitor ();            }}//Whether generalization is called if (ref instanceof Genericservice) {interfaceclass = Genericservice.class;            if (Stringutils.isempty (generic)) {generic = Boolean.TRUE.toString (); }} else {try {interfaceclass = Class.forName (InterfaceName, True, Thread.CurrentThread            (). Getcontextclassloader ());            } catch (ClassNotFoundException e) {throw new IllegalStateException (E.getmessage (), E); }/* Check the method configuration of the interface that is about to be exposed, check if the method exists in the interface is generally not configured so methods is generally null <dub Bo:service > <dubbo:method/> </dubbo:serivce> * * CheckinterfaCeandmethods (Interfaceclass, methods);            /* Check that the reference to the interface is not empty and must implement the interface to be exposed */checkref ();        Generic = Boolean.FALSE.toString (); }

After all the checks are passed, the Com.alibaba.dubbo.config.serviceconfig#doexporturls method is called: Because the Dubbo supports multiple communication protocols, it is exposed, so you can see in the code

/* Convert            the registration agreement into a URL            registry://45.119.68.23:2181/com.alibaba.dubbo.registry.registryservice?            application=test-dubbo&dubbo=2.5.3&pid=7648&registry=zookeeperxtamp=1462349748801         */        List <URL> Registryurls = Loadregistries (true);        When configuring a multi-communication protocol, expose for        (Protocolconfig protocolconfig:protocols) {            Doexporturlsfor1protocol (protocolconfig, registryurls);        }
Doexporturlsfor1protocol all the configuration into a map, and then the map into a Dubbo unified URL, the final exposed Dubbo service is the unified URL, this URL will be registered to zookeeper node, Some of the code is as follows:

/* Set the properties in the non-nullable configuration object to map the values for the configuration settings in the XML configuration file are all converted to Map{side=provider, Application=alijk-dubbo, accepts=1000,dubbo= 2.5.3, threads=100, pid=7236, interface=cn.eoncloud.account.sdk.export.accountservice,threadpool=fixed, version= 1.0.0, timeout=500, Anyhost=true, timestamp=1462347843960} */appendparameters (map, application); AppendParameters ( Map, module); appendparameters (map, provider, Constants.default_key); appendparameters (map, protocolconfig); Appendparameters (map, this), ..... ....... .............. /* Convert the configuration information into a URL, mainly based on the data in the previous map assembly into a URL call url#buildstring method dubbo://10.6.13.137:9998/ cn.eoncloud.account.sdk.export.accountservice?accepts=1000&anyhost=true&application=test-dubbo& Dubbo=2.5.3&interface=cn.eoncloud.account.sdk.export.accountservice&methods=getaccountname,getalltest &pid=7236&revision=1.0.0&side=provider&threadpool=fixed&threads=100&timeout=500xtamp= 1462347843960&version=1.0.0 */url url = new URL (name, host, port, ContextPath = = Null | | Contextpath.length () = = 0? "": ContextPath + "/") + path, map); if (Extensionloader.getextensionloader (Configuratorfactory.class). Hasextension ( Url.getprotocol ())) {URL = Extensionloader.getextensionloader (configuratorfactory.class). GetExtension ( Url.getprotocol ()). Getconfigurator (URL). Configure (URL);} ..... ..... .............. invoker<?> Invoker = Proxyfactory.getinvoker (ref, (Class) Interfaceclass, registryurl.addparameterandencoded ( Constants.export_key, Url.tofullstring ()));//com.alibaba.dubbo.registry.integration.registryprotocol#export Imminent exposure exporter<?> exporter = Protocol.export (invoker);

The above code core exposes a line of code: Protocol.export (Invoker); The value of this protocol is: Registryprotocol, that is, exposure will jump to: Registryprotocol.exprot to deal with, Registryprotocol.exprot mainly do two things: 1, Open the Netty server. 2, create the Zookeeper service node. Here's a look at the Registryprotocol.export method, the code below:

Public <T> exporter<t> Export (final invoker<t> origininvoker) throws rpcexception {//export Invo Ker Dolocalexport call Dubboprotocol.export Open Netty Service listening final exporterchangeablewrapper<t> exporter = DoLocalExpor        T (Origininvoker);        Registry Provider Final Registry Registry = GetRegistry (Origininvoker);        Final URL Registedproviderurl = Getregistedproviderurl (Origininvoker);        Call Zodoregister's doregister to create the Zookeeper service node Registry.register (registedproviderurl);        When subscribing to the override data//FIXME provider subscription, it affects the same JVM, which exposes the service and refers to the scenario of the same service, because subscribed is overwriting the subscription information with a key that is cached by the service name.        Final URL Overridesubscribeurl = Getsubscribedoverrideurl (Registedproviderurl);        Final Overridelistener Overridesubscribelistener = new Overridelistener (Overridesubscribeurl);        Overridelisteners.put (Overridesubscribeurl, Overridesubscribelistener);        Subscribe to Registry.subscribe (Overridesubscribeurl, Overridesubscribelistener); GuaranteeEach export returns a new exporter instance return new Exporter<t> () {public invoker<t> Getinvoker () {            return Exporter.getinvoker ();            } public void Unexport () {try {exporter.unexport ();                } catch (Throwable t) {Logger.warn (T.getmessage (), t);                } try {registry.unregister (registedproviderurl);                } catch (Throwable t) {Logger.warn (T.getmessage (), t);                } try {overridelisteners.remove (overridesubscribeurl);                Registry.unsubscribe (Overridesubscribeurl, Overridesubscribelistener);                } catch (Throwable t) {Logger.warn (T.getmessage (), t);    }            }        }; }
The above code has a particularly important, critical code in Dolocalexport:

Final invoker<?> invokerdelegete = new Invokerdelegete<t> (Origininvoker, Getproviderurl (OriginInvoker)) ;//Here protol is Dubboprotocolexporter = new exporterchangeablewrapper<t> ((exporter<t>) Protocol.export ( Invokerdelegete), Origininvoker);
From the above code can be seen to call Dubboprotocol's export to the service exposure, the export is the ultimate goal is to open the netty of the monitoring, the following Dubbo is how to turn the step-by-step Netty

 private void openserver (URL url) {//Find server. Ip:port String key = Url.getaddress ();        The client can also expose a service that only the server can invoke.        Boolean isserver = Url.getparameter (constants.is_server_key,true);        if (isserver) {ExchangeServer server = Servermap.get (key);        if (server = = NULL) {//Create server Servermap.put (key, Createserver (URL));        } else {//server supports reset, with the override function using Server.reset (URL); }}} private ExchangeServer createserver (url url) {//default on server shutdown when sending readonly event URL = URL.        Addparameterifabsent (Constants.channel_readonlyevent_sent_key, Boolean.TRUE.toString ()); Default on HEARTBEAT url = url.addparameterifabsent (Constants.heartbeat_key, string.valueof (constants.default_heartbeat        ));        The default uses Netty String str = url.getparameter (Constants.server_key, constants.default_remoting_server); if (str! = null && str.length () > 0 &AMP;&AMP;! Extensionloader.getextensionloader (Transporter.class). Hasextension (str)) throw new Rpcexception ("Unsupported se        RVer type: "+ str +", url: "+ url"; The default is to use the Dubbo protocol encoding URL = url.addparameter (Constants.codec_key, version.iscompatibleversion ()?        COMPATIBLE_CODEC_NAME:DubboCodec.NAME);        ExchangeServer server; Try {//headerexchangeserver has opened Netty server for listening server = Exchangers.bind (URL, requesthandler) here        ; } catch (RemotingException e) {throw new Rpcexception ("Fail to start server (URL:" + URL + ")" + e.getmessage        (), E);        } str = Url.getparameter (Constants.client_key); if (str! = null && str.length () > 0) {set<string> supportedtypes = Extensionloader.getextensi            Onloader (Transporter.class). Getsupportedextensions ();            if (!supportedtypes.contains (str)) {throw new Rpcexception ("Unsupported client type:" + str);        }} return server; }
In the code above: Exchangers.bind (URL, RequestHandler) defaults to: Headerexchanger.bind ()

Public exchangeserver bind (URL url, exchangehandler handler) throws RemotingException {        // Transporters defaults to Nettytransporter        return new Headerexchangeserver (Transporters.bind (URL, new Decodehandler (new Headerexchangehandler (handler)));    }
Code to run here can see the transmission mode, Dubbo default mode of communication is Nettytransporter, and then see Nettytransporter.bind method

public static final String NAME = "Netty";        Public Server bind (URL url, Channelhandler listener) throws RemotingException {        return new Nettyserver (URL, listener) ;    }

Already can see the Nettyserver, Dubbo in exposes the service finally opens the Netty service listens, listens the consumer sends the request, through the reflection call method obtains the result through the TCP/IP network transmission returns to the consumer. And then into the nettyserver we can see the very traditional code that opens the Netty service.

protected void Doopen () throws Throwable {nettyhelper.setnettyloggerfactory ();        Executorservice boss = Executors.newcachedthreadpool (New Namedthreadfactory ("Nettyserverboss", true));        Executorservice worker = Executors.newcachedthreadpool (New Namedthreadfactory ("Nettyserverworker", true)); The last parameter is the maximum number of NIO worker threads ChannelFactory channelfactory = new Nioserversocketchannelfactory (boss, worker, GetUrl (). Getp        Ositiveparameter (Constants.io_threads_key, constants.default_io_threads));                Netty Server Launcher bootstrap = new Serverbootstrap (ChannelFactory);        Final Nettyhandler Nettyhandler = new Nettyhandler (GETURL (), this);        Channels = Nettyhandler.getchannels (); https://issues.jboss.org/browse/NETTY-365//https://issues.jboss.org/browse/NETTY-379//FINAL Timer Tim        ER = new Hashedwheeltimer (New Namedthreadfactory ("Nettyidletimer", true));    Bootstrap.setpipelinefactory (New Channelpipelinefactory () {        Public Channelpipeline Getpipeline () {Nettycodecadapter adapter = new Nettycodecadapter (Getcodec ()                , GetUrl (), nettyserver.this);                Channelpipeline pipeline = Channels.pipeline ();                /*int idleTimeout = Getidletimeout ();  if (IdleTimeout > 10000) {pipeline.addlast ("Timer", new Idlestatehandler (timer, idletimeout/1000,                0, 0));                }*/pipeline.addlast ("Decoder", Adapter.getdecoder ());                Pipeline.addlast ("Encoder", Adapter.getencoder ());                Pipeline.addlast ("handler", Nettyhandler);            return pipeline;        }        });    Creates a new channel bound to the specified address, that is, the binding IP, the Port statement client Connection Channel = Bootstrap.bind (Getbindaddress ()); }
After the execution of the above code, the service side of Netty has been opened, can receive the connection of the client, but how to handle the client connection? How to handle the message receiving and sending? All of the processing is in the Nettyhandler class of the code above, Nettyhandler inherits the Simplechannelhandler in the Netty package

Rewrite the methods of channelconnected, channeldisconnected, messagereceived, and so on, but we may be concerned about the Messagereceived method, how to handle the message when it is received, But for the time being, I won't look at Dubbo. If you are handling messages, just look at exposure, how message processing implements asynchronous communication next section.

/** *     trigger when message is received     * @param ctx     * @param e     * @throws Exception    */@Override public void Messagereceived (Channelhandlercontext ctx, messageevent e) throws Exception {        Nettychannel channel = Nettychannel.getoraddchannel (Ctx.getchannel (), URL, handler);        try {            handler.received (channel, E.getmessage ());        } finally {            Nettychannel.removechannelifdisconnected (Ctx.getchannel ());        }    }
Know from the front, open Netty service is in the Registryprotocol.export Dolocalexport, after the Netty service is opened, is to register the service node on the zookeeper, Consumers in the consumer services will be based on the consumption of the interface name to find the corresponding Zookeeper node directory, to monitor the directory, receive push

Registry Providerfinal Registry Registry = GetRegistry (Origininvoker); final URL Registedproviderurl = Getregistedproviderurl (Origininvoker);//Call Zodoregister Doregister to create the Zookeeper service node Registry.register ( Registedproviderurl);//Subscribe to the Override data//FIXME provider subscription, which affects the same JVM that exposes the service and references the same service scenario, because the subscribed takes the service name as a cached key, which causes the subscription information to be overwritten. Final URL Overridesubscribeurl = Getsubscribedoverrideurl (Registedproviderurl); final Overridelistener Overridesubscribelistener = new Overridelistener (overridesubscribeurl); Overridelisteners.put (OVERRIDESUBSCRIBEURL , overridesubscribelistener);//Subscribe Registry.subscribe (Overridesubscribeurl, Overridesubscribelistener);

The node registration for the Dubbo service on zookeeper is: Com.alibaba.dubbo.registry.support.failbackregistry#register

@Override public    void register (url url) {        super.register (URL);        Failedregistered.remove (URL);        Failedunregistered.remove (URL);        try {            //Send Registration request            doregister (URL) to server side;
Because Doregister is an abstract method, viewing his implementation can be seen as:



From can see Doregister implementation has Dubbo, Redis, zookeeper, this is also in our configuration often see the configuration of the registration protocol, the most commonly used is zookeeper, so look at Zookeeperregistry code, See what his doregistry is doing here.

protected void doregister (URL url) {        try {        zkclient.create (tourlpath (URL)), Url.getparameter ( Constants.dynamic_key, True));        }  catch (Throwable e) {            throw new Rpcexception ("Failed to register" + URL + "to zookeeper" + GETURL () + ", Cause:" + E.getmessage (), E);        }    }
In fact, from the above can be seen in the zookeeper above the creation of nodes, the default is not grouped under the circumstances, the service structure is as follows:/dubbo/xxxxservice/consumers, providers

At this point, Dubbo's exposure has basically been completed, opened the Netty service, registered zookeeper node, waiting for consumers to connect to use. The next section describes the implementation of Dubbo's message sending and receiving,NIO asynchronous communication.


Dubbo Source Learning (v) The process of Dubbo exposing services

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.