Web basis of Dubbo

Dubbo

That RPC Remote Procedure Call, is the remote call. This Java RMI remote agent is somewhat similar, but only RMI calls between Java systems, and is used to communicate serialized objects. In contrast, higher performance Dubbo RPC model, the use of HTTP to communicate, so you can make calls between different language services.

Getting Started

First import Dubbo Spring and its dependencies:


maven dependence

<properties>      
    <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-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
        </dependency>
    <!-- dubbo相关 -->
    <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>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
</dependencies>  

Public interface to create and install maven repository:


Public interface packaged separately

package cn.bilibili.dubbo.service;

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

Service-party developers :

Packaged as war package, and configure the listener in web.xml:


web.xml

<!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-service.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

The introduction of a common interface and dependent interface implementation:


Interface implementation class

package cn.bilibili.dubbo.service.impl;

import cn.bilibili.dubbo.service.HelloService;
import com.alibaba.dubbo.config.annotation.Service;

//这个Service注解是dubbo的,不是spring的
@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        System.out.println("-------HelloService运行了-----------");
        return "hello " + name;
    }
}

Create a spring configuration file, and in which configuration dubbo:


applicationContext-service.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:dubdo="http://code.alibabatech.com/schema/dubbo"
       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">
    <!-- 当前应用名称,用于注册中心计算应用间依赖关系,消费者和提供者应用名不能一样 -->
    <dubbo:application name="dubbo-service-provider" />
    <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!-- 注册  协议和port   端口默认是20880 -->
    <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
    <!-- 扫描指定包,加入@Service注解的类会被发布为服务  -->
     <dubbo:annotation package="cn.bilibili.dubbo.service.impl" />
</beans>

Consumer Development

In the web in the background, the web layer is generally dependent on Service, and therefore a direct call using the Controller.
Creating consumer engineering and fight the war package, then configure SpringMVC in web.xml:


web.xml

<!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>
    <!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext-consumer.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

Then create a Controller:


Specific call object

@Controller
@RequestMapping("/demo")
public class HelloController {
    //这里的注解是Dubbo提供
    @Reference
    private HelloService helloService;

    @RequestMapping("/hello")
    @ResponseBody
    public String getName(String name){
        //远程调用
        String result = helloService.sayHello(name);    
        return result;
    }
}

Then disposed in the spring dubbo parameters:


applicationContext-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: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">

    <!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 -->
    <dubbo:application name="dubbo-service-consumer" />
    <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!-- 扫描的方式controller  -->
    <dubbo:annotation package="cn.bilibili.dubbo.controller" />
</beans>

Two Tomcat and JMX port number can not be the same.

You can then access the Controller in your browser.


There dubbo visual background management tool called dubbo-admin, and can be run separately in a Tomcat.

Dubbo parameter adjustment

Configuration adjustment

The above package is used in a scanning manner, in fact, may be used directly xml configuration bean:

<!-- 注册一个Bean -->
<bean id="helloService" class="cn.bilibili.dubbo.service.impl.HelloServiceImpl">
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="cn.bilibili.dubbo.service.HelloService" ref="helloService"/>

Consumer can also be a way to use xml configuration:

<!-- 引用远程服务代理,可以和本地bean一样使用helloService -->
<dubbo:reference id="helloService" interface="cn.bilibili.dubbo.service.HelloService"/>

Automatic injector to the Controller:

@Controller
@RequestMapping("/demo")
public class HelloController {
    @Autowired
    private HelloService helloService;
}

Service Agreement :

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

Dubbo supports the following protocols: dubbo, rmi, hessian, http , webservice, rest, redis and so on. The recommended protocol is dubbo. dubbo agreement with a single long connection and NIO asynchronous communications, suitable for small amount of data concurrent service calls, customer service and the number of machines is much greater than when the number of service providers machines. Not suitable for transferring large amounts of data services, such as file transfer, video transfer, unless the request is very low.
The same project can configure different protocols.

Start checking

Consumer default checks will depend on when you start the service is available, you can use the following way off the startup checking (configured in the consumer side):

<dubbo:consumer check="false"/>

Load Balancing

When the cluster load balancing, Dubbo offers a variety of balanced strategies (including stochastic (random), polling (roundrobin), the minimum number of active calls, consistency Hash), default random random calls.

Load balancing can be configured in the service side in consumer configuration:

Consumer:

/**
    * 使用轮询负载均衡策略
    * check = false 启动时候不检查服务提供者
    */
@Reference(check = false, loadbalance = "roundrobin")
private DemoService demoService;

Service side:

//在服务提供者一方配置负载均衡
@Service(loadbalance = "roundrobin")
public class HelloServiceImpl implements HelloService {
    public String sayHello(String name) {
        return "hello " + name;
    }
}

And other configuration is similar to Dubbo, multiple configurations are covered relations:

  1. Methods priority level, interface level, followed the global configuration again.
  2. If the level is the same, the consumer first, followed by the provider.

So, four kinds of priority configuration is:

  1. Client method-level configuration.
  2. Client interface level configuration.
  3. Method-level server configuration.
  4. Server interface level configuration.

Service Timeout

Timeout mechanism: within the timeout period set, if the provider does not receive end consume the return value, we consider that the call failed. The default timeout 1 second

Consumer side set the timeout:

//设置整个服务的超时时间为5秒
@Reference(timeout = 5000)
private HelloService helloSerice;

xml form:

<!-- 方式一:设置整个服务的超时时间为5秒 -->
<dubbo:reference id="helloService" interface="cn.bilibili.dubbo.service.HelloService" timeout="5000"/>
<!-- 方式二:设置服务的某个具体方法的超时时间 -->
<dubbo:reference id="helloService" interface="cn.bilibili.dubbo.service.HelloService">
    <!-- 设置sayHello方法的超时时间为5秒 -->
    <dubbo:method name="sayHello" timeout="5000"></dubbo:method>
</dubbo:reference>

Server timeout settings:

//设置整个服务的超时时间为5秒
@Service(timeout = 5000)
public class HelloServiceImpl implements HelloService {
}

xml form:

<!--方式一:设置整个服务的超时时间为5秒-->
<dubbo:service interface="cn.bilibili.dubbo.service.HelloService" ref="helloService" timeout="5000"/>
       
<!--方式二:设置服务的某个具体方法的超时时间 -->
<dubbo:service interface="cn.bilibili.dubbo.service.HelloService" ref="helloService">
    <!-- 设置sayHello方法的超时时间为5秒 -->
    <dubbo:method name="sayHello" timeout="5000"></dubbo:method>
</dubbo:service>

Priority configure the timeout on the server side.

Retry Service

When you call a service method failed, dubbo default retry 2 times (not including the default first call), within a set number of retries, the request failed, the request is considered an exception, an exception is thrown. We can change the number of retries by the retries parameter.
dubbo will appear in the end provide service exception retried again. This does not mean that the service provider failed fully implemented. Therefore, not all interfaces are suitable for a retry, if a service is unequal power, it is not suitable mechanism to retry, because there will be a problem of duplicate submission, or can be retried. For example, to submit an order interface can not be retried, and query types of interfaces can be retried. (About Idempotence can look at MDN and this blog post )
service retry require caution.

Consumer side retry setting:

//设置整个服务失败后的重试次数为3,实际调用是4次
@Reference(retries = 3)
private HelloService helloSerice;

xml form

<!--方式一:设置整个服务失败后的重试次数为3,实际调用是4次-->
<dubbo:reference id="helloService" interface="cn.bilibili.dubbo.service.HelloService" retries="3"/>
<!--方式二:设置服务的某个具体方法的重试次数-->
 <dubbo:reference id="helloService" interface="cn.bilibili.dubbo.service.HelloService">
    <!-- 设置sayHello方法的重试次数为3,实际调用是4次 -->
    <dubbo:method name="sayHello" retries="3"></dubbo:method>
</dubbo:reference>

Server settings:

//设置整个服务失败后的重试次数为3,实际调用是4次
@Service(retries = 3)
public class HelloServiceImpl implements HelloService {
}

xml form

<!--方式一:设置整个服务失败后的重试次数为3,实际调用是4次-->
<dubbo:service interface="cn.bilibli.dubbo.service.HelloService" ref="helloService" retries="3"/>
       
<!--方式二:设置服务的某个具体方法的重试次数-->
<dubbo:service interface="cn.bilibili.dubbo.service.HelloService" ref="helloService">
    <!-- 设置sayHello方法的重试次数为3,实际调用是4次 -->
    <dubbo:method name="sayHello" retries="3"></dubbo:method>
</dubbo:service>

Affairs

But if we join @Transactional transaction control annotation on the service provider class, service is unsuccessful the release. The reason is the underlying principle is to create transaction control for the service provider proxy object classes, and Spring case is to create a proxy object based on the default JDK dynamic proxy approach, but this proxy object for the entire class named com.sun.proxy. $ Proxy42 ( the last two digits is not fixed), making it impossible to complete the match Dubbo for packet match before you publish the service, and then advertise a service.

Solution:

Open proxy-target-class open when the transaction is mandatory to use a proxy cglib:

proxy-target-class affairs in the spring, aop, this cache has a few settings, its role is the same:

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<aop:config proxy-target-class="true">

<cache:annotation-driven proxy-target-class="true"/>

Then you need to specify the type of service interface on the interface of the service provider:

//指定服务接口类型
@Service(interfaceClass = HelloService.class)
@Transactional
public class HelloServiceImpl implements HelloService {
    public String sayHello(String name) {
        return "hello " + name;
    }
}

Guess you like

Origin www.cnblogs.com/lixin-link/p/11540934.html