Dubbo's article is enough: from introduction to actual combat

Posted by mandred on Sat, 19 Feb 2022 09:32:33 +0100

catalogue

 

Why do I need dubbo

II. Dubbo technical architecture

Third, Dubbo starts getting started

3.1 server

3.2 consumer side

4. Join zookeeper as the registration center

4.1 server

4.2 consumer side

Five configurations

5.1 API configuration mode

5.2 annotation configuration mode

Six common scenarios

6.1 check at startup

6.2 cluster fault tolerance

6.3 load balancing

6.4 direct provider

6.5 subscription only

6.6 registration only

6.7 multi protocol mechanism

6.8 multiple registration centers

6.9 multiple versions

6.10 log management

VII. Summary

Transferred from: https://segmentfault.com/a/1190000019896723

Why do I need dubbo

Many times, when we use this technology, we may use it because of the needs of the project. However, we may not know why we need to use this technology. However, in fact, understanding the origin and background knowledge of the technology is still helpful to understand a technology, How did dubbo get on the agenda?

In the development of the Internet, in the past, we only needed a server to package all the programs. However, with the increase of traffic, the conventional vertical application architecture can no longer cope with it. Therefore, the architecture has evolved.

1 single application architecture

2. Separate deployment of application and database

3 application and database cluster deployment

4. The pressure on the database increases and the read-write is separated

5 use cache technology to speed up

6 database sub database sub table

7. Applications are divided into different types

At this stage of development, we found that the relationship between applications has become very complex, and the following problems will appear (excerpted from the official website below):

① When there are more and more services, the service URL configuration management becomes very difficult, and the single point pressure of F5 hardware load balancer is also increasing.
② With further development, the dependency relationship between services becomes complex, and it is even unclear which application should be started before which application. Architects can not completely describe the architectural relationship of applications.
③ Then, with the increasing number of service calls, the problem of service capacity is exposed. How many machines does this service need to support? When should I add machines?

In order to solve several problems caused by the evolution of architecture, dubbo came into being. Of course, the technology to solve this problem is not just dubbo.

From Dubbo's service governance diagram above, we can see that Duboo has solved some problems above.

Therefore, when your system architecture develops to this stage, you need to consider using Dubbo.

II. Dubbo technical architecture

We already know very clearly why we need Dubbo technology in our system. Next, let's talk about Dubbo's architecture.

First, the previous picture (from the official website).

After seeing the figure, you may still be confused about the above concepts and have no way to start. Next, let's show you what these roles mean?

Node role description

nodeRole description
ProviderService provider of exposed services
ConsumerThe service consumer that invokes the remote service
RegistryRegistry for service registration and discovery
MonitorThe monitoring center that counts the number and time of service calls
ContainerService run container

After reading these concepts, it seems that Dubbo's architecture is also very simple (its implementation details are complex). Why do you say so? Have you found that it is actually very similar to the producer consumer model. Only in this model, the registration center and monitoring center are added to manage the url provided by the provider and the whole process.

Then, the whole publish subscribe process is very simple.

  • Start the container, load and run the service provider.
  • When a service provider starts, it publishes and registers its own services in the registry.
  • Service consumers subscribe to the services they need in the registry when they start.

If you consider failure or change, you need to consider the following process.

  • The registry returns the service provider address list to the consumer. If there is any change, the registry will push the change data to the consumer based on the long connection.
  • From the provider address list, the service consumer selects one provider to call based on the soft load balancing algorithm. If the call fails, it selects another provider to call.
  • Service consumers and providers accumulate call times and call times in memory, and regularly send statistical data to the monitoring center every minute.

Through this explanation, I believe we are familiar with Dubbo's structure. Let's start directly and drive.

Third, Dubbo starts getting started

I've finally come to this step. I stopped writing here for about a week. The main reason is that the project is too busy recently and I'm in a hurry to hand over the work. Today, I hope I can work hard and complete the basic article of dubbo!

3.1 server

First of all, let's write the interface of the server first, because in fact, the function of dubbo is simply to provide an interface to the consumer.

Interface definition

/**
 * xml Mode service provider interface
 */
public interface ProviderService {

    String SayHello(String word);
}

This interface is very simple. It just contains a SayHello method.

Next, define its implementation class.

/**
 * xml Service provider implementation class
 */
public class ProviderServiceImpl implements ProviderService{

    public String SayHello(String word) {
        return word;
    }
}

In this way, we have written our interface, so how should we expose our services?

Import maven dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ouyangsihai</groupId>
    <artifactId>dubbo-provider</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.5</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.32.Final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.8.0</version>
        </dependency>

    </dependencies>
</project>

The version of dubbo used here is {2.6.6. It should be noted that if you only import dubbo packages, errors will be reported, and the dependencies of netty and curator cannot be found. Therefore, we need to add the dependencies of these two to avoid errors.

In addition, here we use zookeeper as the registry.

So far, the environment required by dubbo is OK. Next, let's expose the interface just defined above.

Expose interface (xml configuration method)

First, we create META-INF.spring package in the resource directory of our project, and then create meta-inf.provider XML} file, the name can be taken, as shown in the figure below.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--The unique name of the current project in the whole distributed architecture and the label of calculation dependency-->
    <dubbo:application name="provider" owner="sihai">
        <dubbo:parameter key="qos.enable" value="true"/>
        <dubbo:parameter key="qos.accept.foreign.ip" value="false"/>
        <dubbo:parameter key="qos.port" value="55555"/>
    </dubbo:application>

    <dubbo:monitor protocol="registry"/>

    <!--dubbo The registry corresponding to the service address to be exposed by this service-->
    <!--<dubbo:registry address="N/A"/>-->
    <dubbo:registry address="N/A" />

    <!--The protocol on which the current service release depends; webserovice,Thrift,Hessain,http-->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService"/>

    <!--Bean bean definition-->
    <bean id="providerService" class="com.sihai.dubbo.provider.service.ProviderServiceImpl"/>

</beans>

① The above file is actually a spring like configuration file, and the bottom layer of dubbo is spring.
② Node: dubbo:application
It is the unique name of the whole project in the distributed architecture. It can be configured in the "name" attribute. In addition, the "owner" field can be configured to indicate who belongs to.
The following parameters can not be configured. The configuration here is configured because of port conflict.
③ Node: dubbo:monitor
Monitoring center configuration is used to configure the information related to connecting to the monitoring center. It can not be configured and is not a required parameter.
④ Node: dubbo:registry
Configure the information of the registry. For example, here we can configure zookeeper as our registry. Address , is the address of the registration center. Here, we configure , N/A , which means that dubbo automatically assigns the address. Or it is a direct connection, not through the registration center.
⑤ Node: dubbo:protocol
What protocol does dubbo rely on when publishing services? You can configure dubbo, webserovice, Thrift, Hessain, http and other protocols.
⑥ Node: dubbo:service
This node is our focus. When we publish our services, we publish our services through this configuration. Interface , is the package path of the interface, and ref , is the bean of the interface configured at point ⑦.
⑦ Finally, we need to configure the bean of the interface just as we configure the interface of spring.

At this step, the configuration of the server is completed. Let's publish the interface through the main method.

Publish interface

package com.sihai.dubbo.provider;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.container.Main;
import com.sihai.dubbo.provider.service.ProviderService;
import com.sihai.dubbo.provider.service.ProviderServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * xml Mode start
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException {
        //Load xml configuration file start
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/provider.xml");
        context.start();
        System.in.read(); // press any key to exit
    }
}

The publishing interface is very simple, because the bottom layer of dubbo is dependent on spring, so we only need to get the xml we just configured through ClassPathXmlApplicationContext and then call context.. The start () method starts.

See the screenshot below. Even if the startup is successful, the interface will be released.

You think it's over here. No, we got the url analysis exposed by dubbo.

url of dubbo exposure

dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService?anyhost=true&application=provider&bean.name=com.sihai.dubbo.provider.service.ProviderService&bind.ip=192.168.234.1&bind.port=20880&dubbo=2.0.2&generic=false&interface=com.sihai.dubbo.provider.service.ProviderService&methods=SayHello&owner=sihai&pid=8412&qos.accept.foreign.ip=false&qos.enable=true&qos.port=55555&side=provider&timestamp=1562077289380

analysis

① First of all, in terms of form, we found that in fact, such a powerful dubbo also publishes its own services with a protocol similar to http, but here we use the # dubbo protocol.
② dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService
The link above is? The previous link consists of: protocol: / / ip: port / interface. There's no mystery about finding out.
③ anyhost=true&application=provider&bean.name=com.sihai.dubbo.provider.service.ProviderService&bind.ip=192.168.234.1&bind.port=20880&dubbo=2.0.2&generic=false&interface=com.sihai.dubbo.provider.service.ProviderService&methods=SayHello&owner=sihai&pid=8412&qos.accept.foreign.ip=false&qos.enable=true&qos.port=55555&side=provider&timestamp=1562077289380
? After the string analysis, you find that these are just in the} provider The fields configured in XML , and then spliced through & do you smell the smell of , http ??

Finally, the dubbo server is getting started. Now let's see how to consume after we get the url?

3.2 consumer side

As mentioned above, we only provide services in a peer-to-peer manner on the server, and do not use the registry. Therefore, the following configurations will be different.

Consumer environment configuration

First of all, we create the configuration file "consumer" under the resource of the consumer xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--The unique name of the current project in the whole distributed architecture and the label of calculation dependency-->
    <dubbo:application name="consumer" owner="sihai"/>

    <!--dubbo The registry corresponding to the service address to be exposed by this service-->
    <!--Point to point approach-->
    <dubbo:registry address="N/A" />
    <!--<dubbo:registry address="zookeeper://localhost:2181" check="false"/>-->

    <!--Generate a call proxy for the remote service-->
    <!--Point to point mode-->
    <dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"
                     url="dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService"/>

    <!--<dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>-->

</beans>

analysis

① It is found that , dubbo:application , and , dubbo:registry , are consistent here.
② dubbo:reference: we use a point-to-point approach here, so we need to configure the url exposed on the server.

maven dependency

The same as the server

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ouyangsihai</groupId>
    <artifactId>dubbo-consumer</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.ouyangsihai</groupId>
            <artifactId>dubbo-provider</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.5</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.32.Final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.8.0</version>
        </dependency>
    </dependencies>
</project>

Call service

package com.sihai.dubbo.consumer;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.sihai.dubbo.provider.service.ProviderService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * xml Called by
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException {

        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        ProviderService providerService = (ProviderService) context.getBean("providerService");
        String str = providerService.SayHello("hello");
        System.out.println(str);
        System.in.read();

    }
}

This is the same as the release of the server.


In this way, we successfully call the interface.

4. Join zookeeper as the registration center

Direct connection is not used in any of the previous cases, but in the registration center. However, in fact, we often use dubbo + zookeeper as the registration center. Here, we will introduce the use of zookeeper as the registration center.

Here, we will transform it in the previous entry example.

4.1 server

In the server, we only need to modify the provider XML.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--The unique name of the current project in the whole distributed architecture and the label of calculation dependency-->
    <dubbo:application name="provider" owner="sihai">
        <dubbo:parameter key="qos.enable" value="true"/>
        <dubbo:parameter key="qos.accept.foreign.ip" value="false"/>
        <dubbo:parameter key="qos.port" value="55555"/>
    </dubbo:application>

    <dubbo:monitor protocol="registry"/>

    <!--dubbo The registry corresponding to the service address to be exposed by this service-->
    <!--<dubbo:registry address="N/A"/>-->
    <dubbo:registry address="zookeeper://localhost:2181" check="false"/>

    <!--The protocol on which the current service release depends; webserovice,Thrift,Hessain,http-->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService"/>

    <!--Bean bean definition-->
    <bean id="providerService" class="com.sihai.dubbo.provider.service.ProviderServiceImpl"/>

</beans>

Focus on this sentence

<dubbo:registry address="zookeeper://localhost:2181" />

In address, use the address of our zookeeper.

If it is a} zookeeper cluster, use the following method.

<dubbo:registry protocol="zookeeper" address="192.168.11.129:2181,192.168.11.137:2181,192.168.11.138:2181"/>

The configuration of the server is just fine. The others are the same as the # entry case.

4.2 consumer side

Like the server side, on the consumer side, we only need to modify the {consumer XML #.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--The unique name of the current project in the whole distributed architecture and the label of calculation dependency-->
    <dubbo:application name="consumer" owner="sihai"/>

    <!--dubbo The registry corresponding to the service address to be exposed by this service-->
    <!--Point to point approach-->
    <!--<dubbo:registry address="N/A" />-->
    <dubbo:registry address="zookeeper://localhost:2181" check="false"/>

    <!--Generate a call proxy for the remote service-->
    <!--Point to point mode-->
    <!--<dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"
                     url="dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService"/>-->

    <dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

</beans>

① The configuration of the registry is the same as that of the server.

<dubbo:registry address="zookeeper://localhost:2181"/>

② dubbo:reference
Since we use zookeeper as the registration center here, it is different from the point-to-point method. The url provided by the dubbo server is no longer needed here. We only need to directly reference the interface provided by the server.

<dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

Well, the consumer side is also configured, so you can use the modified entry case to restart the operation.

It was also successful.

The difference at this time is that the url published by dubbo is registered with zookeeper, and the consumer consumes from zookeeper. Zookeeper is equivalent to an intermediary that provides services to consumers.

You think it's over? No, the good play has just begun.

Five configurations

When we start the example, we use the xml configuration method to configure the dubbo environment. However, the official also provides other configuration methods, which we also decompose one by one here.

5.1 API configuration mode

In fact, this method is not recommended by the official. The official recommends the use of xml configuration. However, it can still be used when testing. In addition, it is necessary to talk about these contents in order to ensure integrity.

First, go back to the server-side project.

Server

Here we use the} api to configure, so provider The XML configuration file is not needed for the time being. We just need to configure and start it with api in the main method of the above AppApi class.

package com.sihai.dubbo.provider;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.sihai.dubbo.provider.service.ProviderService;
import com.sihai.dubbo.provider.service.ProviderServiceImpl;

import java.io.IOException;

/**
 * Api Mode start
 * api There is no need for other configurations, just the following code.
 * However, it should be noted that official recommendations:
 * Api Method is used for test cases, and xml is recommended
 */
public class AppApi
{
    public static void main( String[] args ) throws IOException {

        // Service realization
        ProviderService providerService = new ProviderServiceImpl();

        // Current application configuration
        ApplicationConfig application = new ApplicationConfig();
        application.setName("provider");
        application.setOwner("sihai");

        // Connection registry configuration
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://localhost:2181");
//        registry.setUsername("aaa");
//        registry.setPassword("bbb");

        // Service provider agreement configuration
        ProtocolConfig protocol = new ProtocolConfig();
        protocol.setName("dubbo");
        protocol.setPort(20880);
        //protocol.setThreads(200);

        // Note: ServiceConfig is a duplicate object, which encapsulates the connection with the registry and opens the service port

        // Service provider exposes service configuration
        ServiceConfig<ProviderService> service = new ServiceConfig<ProviderService>(); // This instance is very heavy and encapsulates the connection with the registry. Please cache it yourself, otherwise it may cause memory and connection leakage
        service.setApplication(application);
        service.setRegistry(registry); // Multiple registries can use setRegistries()
        service.setProtocol(protocol); // Multiple protocols can use setProtocols()
        service.setInterface(ProviderService.class);
        service.setRef(providerService);
        service.setVersion("1.0.0");

        // Exposure and registration services
        service.export();
    }
}

analysis

Don't panic when you see whether the above code is in the clouds. Let's analyze it by comparing it with xml.

xml mode of registry
<dubbo:registry protocol="zookeeper" address="localhost:2181"/>
API approach
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://localhost:2181");

Dubbo: the registry node corresponds to RegistryConfig, and the xml attribute corresponds to the API. Just use the set method. In contrast, you will find that if you are not familiar with the API, you can compare it with the xml configuration method.

Other API s

org.apache.dubbo.config.ServiceConfig
org.apache.dubbo.config.ReferenceConfig
org.apache.dubbo.config.ProtocolConfig
org.apache.dubbo.config.RegistryConfig
org.apache.dubbo.config.MonitorConfig
org.apache.dubbo.config.ApplicationConfig
org.apache.dubbo.config.ModuleConfig
org.apache.dubbo.config.ProviderConfig
org.apache.dubbo.config.ConsumerConfig
org.apache.dubbo.config.MethodConfig
org.apache.dubbo.config.ArgumentConfig

For more details, you can view the official documents:
http://dubbo.apache.org/zh-cn...

Let's take a look at the Api mode of the consumer side I configured.

Consumer side

Again, we don't need a consumer XML configuration file, just start it in the main method.

package com.sihai.dubbo.consumer;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.sihai.dubbo.provider.service.ProviderService;

/**
 * api Called by
 * api There is no need for other configurations, just the following code.
 * However, it should be noted that official recommendations:
 * Api Method is used for test cases, and xml is recommended
 */
public class AppApi {

    public static void main(String[] args) {
        // Current application configuration
        ApplicationConfig application = new ApplicationConfig();
        application.setName("consumer");
        application.setOwner("sihai");

        // Connection registry configuration
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://localhost:2181");

        // Note: ReferenceConfig is a duplicate object, which internally encapsulates the connection with the registry and the service provider

        // Reference remote service
        ReferenceConfig<ProviderService> reference = new ReferenceConfig<ProviderService>(); // This instance is very heavy and encapsulates the connection with the registry and the provider. Please cache it yourself, otherwise memory and connection leakage may occur
        reference.setApplication(application);
        reference.setRegistry(registry); // Multiple registries can use setRegistries()
        reference.setInterface(ProviderService.class);

        // Use xxservice like local bean s
        ProviderService providerService = reference.get(); // Note: all communication details are encapsulated inside this proxy object. The object is heavy. Please cache and reuse it
        providerService.SayHello("hello dubbo! I am sihai!");
    }
}

That's all for API configuration in this part. Note: xml configuration method is officially recommended.

5.2 annotation configuration mode

The annotation configuration method still needs to be understood. Now microservices tend to this method, which is also the development trend in the future. 0 configuration should be the trend in recent years.

So how do you annotate dubbo? Let's look at the server first.

Server

Step 1: define the interface and implementation class under the annotation package in the screenshot above

package com.sihai.dubbo.provider.service.annotation;

/**
 * Annotation mode interface
 */
public interface ProviderServiceAnnotation {
    String SayHelloAnnotation(String word);
}
package com.sihai.dubbo.provider.service.annotation;

import com.alibaba.dubbo.config.annotation.Service;

/**
 * Annotation implementation class
 */
@Service(timeout = 5000)
public class ProviderServiceImplAnnotation implements ProviderServiceAnnotation{

    public String SayHelloAnnotation(String word) {
        return word;
    }
}

@Service

@Service is used to configure Dubbo's service provider.

Step 2: assembly service provider. Discover, assemble and provide Dubbo services through the technology of Java Config (@ Configuration) and annotation scanning (@ EnableDubbo) in Spring.

package com.sihai.dubbo.provider.configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Annotation mode configuration
 */
@Configuration
@EnableDubbo(scanBasePackages = "com.sihai.dubbo.provider.service.annotation")
public class DubboConfiguration {

    @Bean // #1. Service provider information configuration
    public ProviderConfig providerConfig() {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(1000);
        return providerConfig;
    }

    @Bean // #2 distributed application information configuration
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-provider");
        return applicationConfig;
    }

    @Bean // #3 registry information configuration
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }

    @Bean // #4. Use protocol configuration. Here, use dubbo
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    }
}

analysis

  • Specify on com.com through @ EnableDubbo sihai. dubbo. provider. Service. Scan all classes marked with @ Service # under annotation #
  • Assemble all @ beans in @ DubboConfiguration , through @ Configuration , and inject them into Dubbo Service through @ Java Config , that is, the class marked with @ Service ,. This includes:

    • ProviderConfig: service provider configuration
    • ApplicationConfig: application configuration
    • RegistryConfig: Registry configuration
    • ProtocolConfig: protocol configuration

It looks complicated, but actually...

Step 3: start the service

package com.sihai.dubbo.provider;

import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import com.sihai.dubbo.provider.configuration.DubboConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import sun.applet.Main;

import java.io.IOException;

/**
 * Annotation start mode
 */
public class AppAnnotation {

    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfiguration.class); 
        context.start();
        System.in.read(); 
    }
}

It is found that the following information indicates success.

Consumer side

Similarly, let's take a look at the consumer side project and have a perceptual understanding.

Step 1: Reference Service

package com.sihai.dubbo.consumer.Annotation;

import com.alibaba.dubbo.config.annotation.Reference;
import com.sihai.dubbo.provider.service.annotation.ProviderServiceAnnotation;
import org.springframework.stereotype.Component;

/**
 * Annotation service
 */
@Component("annotatedConsumer")
public class ConsumerAnnotationService {

    @Reference
    private ProviderServiceAnnotation providerServiceAnnotation;

    public String doSayHello(String name) {
        return providerServiceAnnotation.SayHelloAnnotation(name);
    }
}

In the "ConsumerAnnotationService" class, Reference the class provided by the server through @ Reference, and then provide an interface to the consumer by calling this class through a method.
Note: if the "ProviderServiceAnnotation" class cannot be found here, please use "Maven into all" for the server-side project at the server-side, and then put the dependencies of the server-side into the "pom" of the consumer side. As follows:

<dependency>
          <groupId>com.ouyangsihai</groupId>
            <artifactId>dubbo-provider</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

Step 2: assemble service consumers
This step is not the same as that of the server.

package com.sihai.dubbo.consumer.configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * Annotation configuration class
 */
@Configuration
@EnableDubbo(scanBasePackages = "com.sihai.dubbo.consumer.Annotation")
@ComponentScan(value = {"com.sihai.dubbo.consumer.Annotation"})
public class ConsumerConfiguration {
    @Bean // Application configuration
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-consumer");
        Map<String, String> stringStringMap = new HashMap<String, String>();
        stringStringMap.put("qos.enable","true");
        stringStringMap.put("qos.accept.foreign.ip","false");
        stringStringMap.put("qos.port","33333");
        applicationConfig.setParameters(stringStringMap);
        return applicationConfig;
    }

    @Bean // Service consumer configuration
    public ConsumerConfig consumerConfig() {
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setTimeout(3000);
        return consumerConfig;
    }

    @Bean // Configure registry
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }
}

Step 3: initiate remote call

In the main method, start a Spring Context to find the assembled Dubbo service consumer and initiate a remote call.

package com.sihai.dubbo.consumer;

import com.sihai.dubbo.consumer.Annotation.ConsumerAnnotationService;
import com.sihai.dubbo.consumer.configuration.ConsumerConfiguration;
import com.sihai.dubbo.provider.service.ProviderService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Annotation mode start
 *
 */
public class AppAnnotation
{
    public static void main( String[] args ) throws IOException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class); 
        context.start(); // start-up
        ConsumerAnnotationService consumerAnnotationService = context.getBean(ConsumerAnnotationService.class); 
        String hello = consumerAnnotationService.doSayHello("annotation"); // Call method
        System.out.println("result: " + hello); // Output results

    }
}

result

Six common scenarios

In the following explanation, it will be explained in the way of xml configuration, which is also the way recommended by dubbo officials. The following operations are explained in the xml configuration file of the server and the configuration file of the consumer.

6.1 check at startup

By default, Dubbo will check whether the dependent services are available at startup. When unavailable, an exception will be thrown to prevent the completion of Spring initialization, so that problems can be found early when online. By default, 'check="true".

However, sometimes, we don't all need to check when starting. For example, when testing, we need to start faster. Therefore, in this scenario, we need to turn off this function.

Next, let's see how to use this function.

When registering at the server (the same applies when registering at the client);

<dubbo:registry protocol="zookeeper" address="localhost:2181,localhost:2182,localhost:2183" check="false"/>

When the client refers to the service of the server;

<dubbo:reference check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

It's so simple, it's so strong!

6.2 cluster fault tolerance

dubbo also supports cluster fault tolerance. At the same time, there are many optional schemes. The default scheme is {failover, that is, the retry mechanism.

First, let's sort out all the fault-tolerant mechanisms, and then look at their use.

Cluster modeexplainusage method
Failover ClusterFail to switch automatically. In case of failure, retry other servers. Usually used for read operations, but retries can cause longer delays. You can set the number of retries (excluding the first time) through retries="2".cluster="xxx" xxx: cluster mode name, for example, cluster="failover"
Failfast ClusterFast failure, only one call is initiated, and an error is reported immediately after failure. It is usually used for non idempotent write operations, such as adding new records. 
Failsafe ClusterFail safe. In case of exception, ignore it directly. 
Failback ClusterFailure automatic recovery, background record failure request, regular retransmission. Usually used for message notification operations. 
Forking ClusterCall multiple servers in parallel and return as long as one succeeds. It is usually used for reading operations with high real-time requirements, but it needs to waste more service resources. You can set the maximum number of parallels by forks="2". 
Broadcast ClusterThe broadcast calls all providers one by one. If any one reports an error, it will report an error. It is usually used to notify all providers to update local resource information such as cache or log. 

Use example
Set when publishing or referencing services

<!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService"/>
<dubbo:reference cluster="failover" retries="2" check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

6.3 load balancing

Load balancing must be a familiar concept, so dubbo support is also normal. Here are some schemes and usage methods of load balancing supported by dubbo.

Load balancing modeexplainusage method
Random LoadBalanceSet random probability by weight at random< Dubbo: service loadbalance = "XXX" / > XXX: load balancing method
RoundRobin LoadBalancePolling sets the polling ratio according to the weight after the Convention. 
LeastActive LoadBalanceThe minimum number of active calls is a random number with the same active number. The active number refers to the count difference before and after the call. 
ConsistentHash LoadBalanceConsistency Hash requests with the same parameters are always sent to the same provider. When a provider hangs up, the original request sent to the provider is shared among other providers based on the virtual node, which will not cause drastic changes. 

6.4 direct provider

In the development and testing environment, we often need to bypass the registration center and only test the specified service provider. Therefore, in this case, we only need to directly connect to the place of the server. In fact, this method has been used in the previous explanation. The first explanation is this method, because it is simple.

use

<dubbo:reference id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"
                     url="dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService"/>

Note: it can be seen that as long as the method of the service end is given at the # dubbo:reference # node by using # url # on the consumer end.

6.5 subscription only

Subscription only means that you can only subscribe to the services on the server, but not register.

The official usage scenarios are quoted as follows:

In order to facilitate development and testing, a registry for all services is often shared offline. At this time, if a service provider under development registers, it may affect the normal operation of consumers.
Service providers and developers can only subscribe to services (the developed services may depend on other services) without registering the services under development, and test the services under development through direct connection.
<dubbo:registry register="false" protocol="zookeeper" address="localhost:2181,localhost:2182,localhost:2183" check="false"/>

① Use subscription only

When using register="false" at the service provider, we use the following methods to obtain the service at the service provider;

<dubbo:reference cluster="failover" retries="2" check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService"/>

Startup information

It is found that at this time, instead of registering with the registration center zookeeper , it just publishes the service and starts netty.

② Do not use subscription only mode

<dubbo:registry protocol="zookeeper" address="localhost:2181,localhost:2182,localhost:2183" check="false"/>

Startup information

You can find that you have registered with the registration center zookeeper here.

6.6 registration only

Registration only is just the opposite of subscription only. You can register with the registry at this time, but the consumer can't read the service.

Application scenario

If there are two mirror environments and two registries, one service is only deployed in one registry, the other registry has not been deployed in time, and other applications of the two registries need to rely on this service. At this time, the service provider can only register the service to another registry instead of subscribing to the service from another registry.

instructions

<dubbo:registry subscribe="false" address="localhost:2181"></dubbo:registry>

Under the # dubbo:registry # node on the server side, use # subscribe="false" to declare that this service is a registration only service.

At this time, it cannot be called when the consumer calls.

6.7 multi protocol mechanism

The protocols we used earlier are all dubbo protocols, but in addition to supporting this protocol, dubbo also supports other protocols, such as rmi, hessian, etc. in addition, we can expose a service with multiple protocols at the same time.

usage method

① An interface uses a protocol

Declare multiple protocols first

 <!--The protocol on which the current service release depends; webserovice,Thrift,Hessain,http-->
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:protocol name="rmi" port="1099" />

Then use the specific protocol when publishing the interface

<!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi"/>

In the output log, you can find the interface published by rmi.

rmi://192.168.234.1:1099/com.sihai.dubbo.provider.service.ProviderService?anyhost=true&application=provider&bean.name=com.sihai.dubbo.provider.service.ProviderService&cluster=failover&dubbo=2.0.2&generic=false&interface=com.sihai.dubbo.provider.service.ProviderService&methods=SayHello&owner=sihai&pid=796&retries=2&side=provider&timestamp=1564281053185, dubbo version: 2.6.6, current host: 192.168.234.1

② An interface uses multiple protocols
The way to declare the protocol is the same as the above. When publishing the interface, it is a little different.

<dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi,dubbo"/>

Description: the protocol attribute can be separated by, and multiple protocols can be used.

6.8 multiple registration centers

Dubbo supports the simultaneous registration of the same service with multiple registries, or the registration of different services in different registries, or even the simultaneous reference of services with the same name registered in different registries.

Server side multi registry publishing service

A service can be registered in different registries. When a problem occurs in one registry, you can use another registry.

register

<!--Multi registry-->
    <dubbo:registry protocol="zookeeper" id="reg1" timeout="10000" address="localhost:2181"/>
    <dubbo:registry protocol="zookeeper" id="reg2" timeout="10000" address="localhost:2182"/>
    <dubbo:registry protocol="zookeeper" id="reg3" timeout="10000" address="localhost:2183"/>

Publishing services

<!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService" registry="reg1"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi" registry="reg2"/>

Note: use registry="reg2" to specify the registry used by the interface. At the same time, you can also use multiple, separated by, for example, registry="reg1,,reg2".

Consumer multi registry reference service

First, register with different registration centers;

<!--Multi Registration Center-->
    <dubbo:registry protocol="zookeeper" id="reg1" timeout="10000" address="localhost:2181"/>
    <dubbo:registry protocol="zookeeper" id="reg2" timeout="10000" address="localhost:2182"/>
    <dubbo:registry protocol="zookeeper" id="reg3" timeout="10000" address="localhost:2183"/>

Secondly, different consumer service references use different registries;

!--Different services use different registries-->
    <dubbo:reference cluster="failover" retries="2" check="false" id="providerService"
                     interface="com.sihai.dubbo.provider.service.ProviderService" registry="reg1"/>
    <dubbo:reference cluster="failover" retries="2" check="false" id="providerService2"
                     interface="com.sihai.dubbo.provider.service.ProviderService" registry="reg2"/>

Note: the above uses registry 1 and registry 2 respectively.

6.9 multiple versions

Different services have different versions, which can be updated and upgraded. At the same time, different versions cannot be called.

<!--The configuration of service publishing requires exposed service interfaces-->
    <dubbo:service cluster="failover" retries="2"
            interface="com.sihai.dubbo.provider.service.ProviderService"
            ref="providerService" registry="reg1" version="1.0.0"/>
    <dubbo:service cluster="failover" retries="2"
                   interface="com.sihai.dubbo.provider.service.ProviderService"
                   ref="providerService" protocol="rmi" registry="reg2" version="1.0.0"/>

Added version control.

6.10 log management

dubbo can also record or save log information to a file.

① Use accesslog to output to log4j

<dubbo:protocol accesslog="true" name="dubbo" port="20880"/>
    <dubbo:protocol accesslog="true" name="rmi" port="1099" />

② Output to file

<dubbo:protocol accesslog="http://localhost/log.txt" name="dubbo" port="20880"/>
    <dubbo:protocol accesslog="http://localhost/log2.txt" name="rmi" port="1099" />

VII. Summary

That's all for this article. It mainly talks about several contents
1. Why dubbo
2. Brief analysis of dubbo architecture
3. Introduction to dubbo
4. Join dubbo with zookeeper registry
5. dubbo has various configuration modes (xml, api, annotation)
6. Introduction to common scenarios

Topics: Java