Distributed RPC framework_ Apache Dubbo

Posted by Steffen on Thu, 10 Feb 2022 20:23:00 +0100

Evolution of software architecture

The development of software architecture has experienced the evolution process from single architecture, vertical architecture, SOA architecture to micro service architecture. Let's learn about these architectures respectively.

Monomer architecture

Architecture description

All in one

Architecture advantages

The structure is simple, the early development cost is low, and the development cycle is short. It is suitable for small projects.

Architecture shortcomings

  • All functions are integrated in one project, which is difficult to develop, expand and maintain for large projects.
  • The technology stack is limited and can only be developed in one language.
  • The system performance can only be expanded by expanding cluster nodes, which is costly.

Vertical Architecture

Architecture description

Cut according to the business to form a single project.

Architecture advantages

The stack can be written in different programming languages

Architecture shortcomings

  • Functions are concentrated in one project, which is not conducive to development, expansion and maintenance.
  • System expansion can only be achieved through clusters.
  • Functional redundancy, data redundancy and strong coupling between projects.

SOA Architecture

The full name of SOA is Service-Oriented Architecture, that is, Service-Oriented Architecture.

It can deploy, combine and use loosely coupled coarse-grained application components (services) through the network according to the needs. A service usually exists in the operating system process in a separate form.

From the perspective of function, abstract the business logic into reusable services, and realize the rapid regeneration of business through the arrangement of services. The purpose is to transform the original inherent business functions into general business services and realize the rapid reuse of business logic.

Architecture description

The repeated functions or modules are extracted into components to provide services, and the form of ESB (Enterprise Service Bus) is used as the communication bridge between projects and services.

Architecture advantages

  • Duplicate functions or modules are extracted as services to improve development efficiency.
  • High reusability.
  • High maintainability.

Architecture shortcomings

  • The business of each system is different, so it is difficult to confirm that the functions or modules are repeated.
  • The granularity of extracting services is large.
  • High coupling between systems and services.

Microservice architecture

Architecture description

The system service layer is completely independent and extracted into micro services one by one.

The granularity of extraction is finer and follows the single principle.

It adopts lightweight framework protocol transmission.

Architecture advantages

  • The granularity of service splitting is finer, which is conducive to improving development efficiency.
  • Corresponding optimization schemes can be formulated for different services.
  • Applicable to the Internet era, the product iteration cycle is shorter.

Architecture shortcomings

  • Too fine granularity leads to too many services and high maintenance costs.
  • The technical cost of distributed system development is high and poses great challenges to the team.

Apache Dubbo overview

1. Introduction to Dubbo

Apache Dubbo is a high-performance Java RPC framework. Its predecessor is a high-performance and lightweight open-source Java RPC framework opened by Alibaba, which can be seamlessly integrated with the Spring framework.

What is RPC?

The full name of RPC is remote procedure call, that is, remote procedure call. For example, there are two servers A and B. an application is deployed on server A and an application is deployed on server B. The Application on server A wants to call the method provided by the application on server B. because the two applications are not in the same memory space, they cannot be called directly. Therefore, it is necessary to express the semantics of the call and convey the data of the call through the network.

It should be noted that RPC is not a specific technology, but refers to the process of remote call of the whole network.

RPC is a generalized concept. Strictly speaking, all remote procedure call methods belong to the category of RPC. Various development languages have their own RPC framework. There are many RPC frameworks in Java, such as RMI, Hessian, Dubbo, etc.

Dubbo official website address: http://dubbo.apache.org

Dubbo provides three core capabilities: interface oriented remote method invocation, intelligent fault tolerance and load balancing, and automatic service registration and discovery.

Dubbo architecture

Dubbo architecture diagram (officially provided by Dubbo) is as follows:

Node role description:

nodeRole name
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
  • The dotted line is asynchronous access, and the solid line is synchronous access.
  • Blue dotted line: the function completed at startup.
  • The red dotted line (solid line) is the function executed during the operation of the program.

Description of calling relationship:

  1. The service container is responsible for starting, loading and running the service provider.
  2. When a service provider starts, it registers its services with the registry.
  3. Service consumers subscribe to the services they need from the registry when they start.
  4. 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.
  5. 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.
  6. Service consumers and providers accumulate call times and call times in memory, and regularly send statistical data to the monitoring center every minute.

Service registry Zookeeper

As can be seen from the previous Dubbo architecture diagram, Registry (service registry) plays a vital role in it.

Dubbo officially recommends using Zookeeper as the service registry.

Introduction to Zookeeper

Zookeeper is a sub project of Apache Hadoop. It is a tree type directory service that supports change push. It is suitable to be used as the registration center of Dubbo service. It has high industrial intensity, can be used in production environment, and is recommended.

In order to understand Zookeeper's tree directory service, let's take a look at our computer's file system (also a tree directory structure):


My computer can be divided into multiple drive letters (such as C, D, E, etc.), and multiple directories can be created under each drive letter. Files or subdirectories can be created under each directory, which finally forms a tree structure. Through this tree structure directory, we can store the files by categories, which is convenient for us to find later. And each file on the disk has a unique access path, for example: C: \ windows \ itcast \ hello txt.

Zookeeper tree directory service:


Process Description:

  • When a service provider starts up: to / Dubbo / com foo. Write your own URL address in the barservice / providers directory
  • When a service consumer starts: subscribe to / Dubbo / com foo. The URL address of the provider in the barservice / providers directory. And to / Dubbo / com foo. Write your own address in the URL / barsumerconservice directory
  • When the monitoring center starts: subscribe to / Dubbo / com foo. URL addresses of all providers and consumers under the barservice directory

Install Zookeeper

Download address: http://archive.apache.org/dist/zookeeper/

The version of Zookeeper used in this course is 3.4.6. After downloading, you can get the name Zookeeper-3.4.6 tar. GZ compressed file.

Installation steps

  • Step 1: install jdk (omitted)
  • Step 2: upload zookeeper's compressed package (zookeeper-3.4.6.tar.gz) to linux system
  • Step 3: decompress the compressed package tar -zxvf zookeeper-3.4.6 tar. gz
  • Step 4: enter the zookeeper-3.4.6 directory and create the data directory mkdir data
  • Step 5: enter the conf directory and put zoo_sample.cfg is renamed zoo cfg
    • cd conf
    • mv zoo_sample.cfg zoo.cfg
  • Step 6: open zoo Cfg file, modify the data attribute: dataDir=/root/zookeeper-3.4.6/data

Start and stop Zookeeper

  • Enter the bin directory of Zookeeper and start the service command:/ zkServer.sh start
  • Stop service command:/ zkServer.sh stop
  • View service status:/ zkServer.sh status

Dubbo quick start

As an RPC framework, Dubbo's core function is to realize cross network remote call.

This section is to create two applications, one as a service provider and the other as a service consumer. Dubbo enables the service consumer to remotely call the method of the service provider.

Service provider development

Development steps

(1) Create maven project (packaged as war) dubbodemo_provider, in POM Import the following coordinates into the XML file, and the tomcat port number is 8081.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring.version>5.0.5.RELEASE</spring.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- dubbo relevant -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.7</version>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <configuration>
                <!-- Specify port -->
                <port>8081</port>
                <!-- Request path -->
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>

(2) Configure web XML file

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

(3) Create service interface

package com.itheima.service;

public interface HelloService {
    public String sayHello(String name);
}

(4) Create service implementation class

package com.itheima.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.service.HelloService;

@Service//Note: the Service annotation used on the Service implementation class is provided by Dubbo and is used to publish services
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "hello" + name;
    }
}

Note: the Service annotation used on the Service implementation class is provided by Dubbo and is used to publish services

(5) Create ApplicationContext service under src/main/resources 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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/mvc
         http://www.springframework.org/schema/mvc/spring-mvc.xsd
         http://code.alibabatech.com/schema/dubbo
         http://code.alibabatech.com/schema/dubbo/dubbo.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- The current application name is used to calculate the dependency between applications in the registry. Note: the application names of consumers and providers are different -->
    <dubbo:application name="dubbodemo_provider"/>
    <!-- Connect service registry zookeeper ip by zookeeper Server ip address-->
    <dubbo:registry address="zookeeper://192.168.44.44:2181"/>
    <!-- Registration agreement and port   The default port is 20880 -->
    <dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>
    <!-- Scan the specified package and join@Service Annotated classes are published as services  -->
    <dubbo:annotation package="com.itheima.service.impl"/>
</beans>

(6) Start service

tomcat7:run

Service consumer development

Development steps

(1) Create maven project (packaged as war) dubbodemo_consumer,pom. The XML configuration is the same as that of the above service provider. You only need to change the port number of Tomcat plug-in to 8082.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring.version>5.0.5.RELEASE</spring.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- dubbo relevant -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.7</version>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <configuration>
                <!-- Specify port -->
                <port>8082</port>
                <!-- Request path -->
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>

(2) Configure web XML file

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Specify the loaded configuration file through parameters contextConfigLocation load -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-web.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

(3) Copy the HelloService interface in the service provider project to the current project

(4) Write Controller

package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.service.HelloService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/demo")
public class HelloController {

    @Reference //Note: the @ Reference annotation provided by Dubbo is used to inject HelloService into the Controller
    private HelloService helloService;

    @RequestMapping("/Hello")
    @ResponseBody
    public String getName(String name) {
        //Remote call
        String result = helloService.sayHello(name);
        System.out.println(result);
        return result;
    }
}

Note: the @ Reference annotation provided by Dubbo is used to inject HelloService into the Controller

(5) Create ApplicationContext web under src/main/resources 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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
			http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/mvc
			http://www.springframework.org/schema/mvc/spring-mvc.xsd
			http://code.alibabatech.com/schema/dubbo
			http://code.alibabatech.com/schema/dubbo/dubbo.xsd
			http://www.springframework.org/schema/context
			http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- The current application name is used to calculate the dependency between applications in the registry. Note: the application names of consumers and providers are different -->
    <dubbo:application name="dubbodemo-consumer"/>
    <!-- Connect service registry zookeeper ip by zookeeper Server ip address-->
    <dubbo:registry address="zookeeper://192.168.44.44:2181"/>
    <!-- Expose the interface by scanning  -->
    <dubbo:annotation package="com.itheima.controller"/>
</beans>

(6) Run test

tomcat7:run start

Enter in the browser http://localhost:8082/demo/Hello.do?name=tom , view browser output

Thinking one

In the Dubbo introduction case above, we copied the HelloService interface from the dubcodemo_provider to the dubcodemo_consumer. Is this appropriate? Is there a better way?

A: This is obviously bad. The same interface has been copied twice, which is not conducive to later maintenance. A better way is to create a maven project separately and create this interface in this Maven project. Projects that need to rely on this interface only need to be in their own POM Just import Maven coordinates into the XML file.

Thinking II

In the Dubbo demo_consumer project, only the HelloService interface is referenced, and no implementation class is provided. How does Dubbo achieve remote invocation?

A: the underlying layer of Dubbo creates a proxy object for the HelloService interface based on proxy technology, and remote calls are completed through this proxy object. You can view the internal structure of this proxy object through the debug function of the development tool. In addition, the bottom layer of Dubbo's network transmission is based on the Netty framework.

Thinking three

In the Dubbo introduction case above, we use Zookeeper as the service registration center. Service providers need to register their service information with Zookeeper, and service consumers need to subscribe to the services they need from Zookeeper. At this time, Zookeeper service becomes very important. How to prevent Zookeeper from single point of failure?

A: zookeeper actually supports the cluster mode. Zookeeper clusters can be configured to achieve high availability of zookeeper services and prevent single point of failure.

Dubbo management console

When developing, we need to know which services are registered in Zookeeper registry and which consumers consume these services. We can do this by deploying a management center. In fact, the management center is a web application, which can be deployed to tomcat.

install

Installation steps:

(1) Dubbo-admin-2.6.0 Copy the war file to the webapps directory of tomcat

(2) Start tomcat and the war file will be decompressed automatically

(3) Modify Dubbo. Under WEB-INF Properties file, pay attention to Dubbo registry. The value corresponding to address needs to correspond to the ip address and port number of the Zookeeper currently used

dubbo.registry.address=zookeeper://192.168.134.129:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest

(4) Restart tomcat

use

Operation steps:

(1) Visit http://localhost:8080/dubbo-admin-2.6.0/ , enter the user name (root) and password (root)


(2) Start the service provider project and service consumer project, and you can view the corresponding information




Dubbo related configuration description

Packet scanning

<dubbo:annotation package="com.itheima.service" />

Both service providers and service consumers need to be configured to represent package scanning, which is used to scan classes under specified packages (including sub packages).

If you do not use package scanning, you can also publish services through the following configuration.

<bean id="helloService" class="com.itheima.service.impl.HelloServiceImpl" />
<dubbo:service interface="com.itheima.api.HelloService" ref="helloService" />

As a service consumer, services can be referenced through the following configuration:

<!-- Generate a remote service proxy, which can communicate with local bean Same use helloService -->
<dubbo:reference id="helloService" interface="com.itheima.api.HelloService" />

The above method publishes and references services. A configuration item (< Dubbo: Service >, < Dubbo: reference >) can only publish or reference one service. If there are multiple services, this method is cumbersome. Package scanning is recommended.

agreement

<dubbo:protocol name="dubbo" port="20880"/>

Generally, it is configured on the service provider side, and the protocol name and port number can be specified.

The protocols supported by Dubbo include Dubbo, rmi, hessian, http, webservice, rest, redis, etc.

dubbo protocol is recommended.

dubbo protocol adopts single long connection and NIO asynchronous communication, which is suitable for service calls with small amount of data and large concurrency, and the number of service consumer machines is much larger than that of service provider machines. It is not suitable for services that transmit large amounts of data, such as files and videos, unless the request volume is very low.

Multiple protocols can also be configured in the same project. Different services can use different protocols, for example:

<!-- Multi protocol configuration -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<!-- use dubbo Agreement exposure service -->
<dubbo:service interface="com.itheima.api.HelloService" ref="helloService" protocol="dubbo" />
<!-- use rmi Agreement exposure service -->
<dubbo:service interface="com.itheima.api.DemoService" ref="demoService" protocol="rmi" /> 

Check on startup

<dubbo:consumer check="false"/>

The above configuration needs to be configured on the service consumer side. If it is not configured, the default check value is true. 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 as soon as possible when online. You can turn off the check by changing the check value to false.

It is recommended to set the check value to false in the development stage and to true in the production environment.

load balancing

Load Balance: in fact, it is to allocate requests to multiple operating units for execution, so as to complete work tasks together.

In cluster load balancing, Dubbo provides a variety of balancing strategies (including random, polling, minimum number of active calls, consistency Hash), and the default is random random calls.

The load balancing policy can be configured either on the service provider side or on the service consumer side, as follows:

@Controller
@RequestMapping("/demo")
public class HelloController {

    //Configure the load balancing policy on the service consumer side
    //check = false: check at startup. The default value is true
    @Reference(check = false, loadbalance = "random") //Note: the @ Reference annotation provided by Dubbo is used to inject HelloService into the Controller
    private HelloService helloService;

    @RequestMapping("/Hello")
    @ResponseBody
    public String getName(String name) {
        //Remote call
        String result = helloService.sayHello(name);
        System.out.println(result);
        return result;
    }
}
//Configure load balancing on the service provider side
@Service(loadbalance = "random")//Note: the Service annotation used on the Service implementation class is provided by Dubbo and is used to publish services
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "hello" + name;
    }
}

You can observe the effect of Dubbo load balancing by starting multiple service providers.

Note: since we start multiple service providers on one machine, we need to modify the port number of tomcat and Dubbo service to prevent port conflict.

In the actual production environment, multiple service providers are deployed on different machines, so there is no port conflict.

Solve the problem that Dubbo cannot publish the Service proxied by the transaction

Previously, we have completed the introduction case of Dubbo. Through the introduction case, we can see that the package can be scanned through the label configuration provided by Dubbo, and the classes scanned to @ Service annotation can be published as micro services.

However, if we add the @ Transactional transaction control annotation to the service provider class, the service will not be published successfully. The reason is that the underlying principle of transaction control is to create a proxy object for the service provider class. By default, Spring creates a proxy object based on JDK dynamic proxy, and the complete class name of this proxy object is com sun. proxy.$ Proxy42 (the last two digits are not fixed), which makes Dubbo unable to complete the package matching before publishing the service, and then does not publish the service.

Problem display

Dubbodemo, the service provider in the entry case_ Display based on provider project

Operation steps:

(1) In POM Add maven coordinates in XML file

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.47</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.6</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.2</version>
</dependency>

(2) In ApplicationContext service Add relevant configurations of data source, transaction manager and transaction annotation in XML configuration file

<!--data source-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
  <property name="username" value="root" />
  <property name="password" value="root" />
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="jdbc:mysql://localhost:3306/test" />
</bean>
<!-- Transaction manager  -->
<bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>
<!--Enable annotation support for transaction control-->
<tx:annotation-driven transaction-manager="transactionManager"/>

The database connected above can be created by yourself.

(3) Add @ Transactional annotation on HelloServiceImpl class

(4) Start the service provider and service consumer and visit: http://localhost:8082/demo/Hello.do?name=jack

The above error is that there is no service provider available.

Check the dubbo management console and find that the service has not been published, as shown below:

You can view Dubbo's execution process through breakpoint debugging, and Dubbo handles it through the postProcessAfterInitialization method of AnnotationBean

Solution

Through the above breakpoint debugging, we can see that after adding transaction annotation to HelloServiceImpl class, Spring will create a proxy object for this class based on JDK dynamic proxy technology, and the complete class name of the created proxy object is com sun. proxy.$ Proxy35, resulting in Dubbo's failure in package matching (because the package we scanned when publishing the service was com.itheima.service), so the code that actually publishes the service later was not executed.

Solution steps

(1) Modify ApplicationContext Service XML configuration file. When the transaction control annotation support is enabled, specify the proxy target class attribute and the value is true. Its function is to use cglib proxy method to create proxy object for Service class

<!--Enable annotation support for transaction control-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>


(2) Modify the HelloServiceImpl class, add the interfaceClass attribute in the Service annotation, and the value is helloservice Class, which is used to specify the interface type of the Service

@Service(interfaceClass = HelloService.class)//Note: the Service annotation used on the Service implementation class is provided by Dubbo and is used to publish services
@Transactional
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "hello" + name;
    }
}

This must also be modified. Otherwise, the published service interface will be SpringProxy instead of HelloService interface, as follows:

Topics: Dubbo Zookeeper