第二章 Dubbo框架

一、Dubbo概述

① Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

② Dubbo(读音[ˈdʌbəʊ])是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架(由Rod Johnson创建的一个开源框架)无缝集成

③ Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案、服务治理方案。

官网:http://dubbo.apache.org/zh-cnhttp://dubbo.apache.org/zh-cn特性: 

面向接口代理:调用接口的方法,在A服务器调用B服务器的方法,由dubbo实现对B的调用,无需关心实现的细节,就像MyBatis访问Dao的接口,可以操作数据库一样。不用关心Dao接口方法的实现。这样开发是方便,舒服的。

二、基本架构

① 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

② 服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

③ 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 –如果信息有变,注册中心提供新的信息给消费者

监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心 –监控服务提供者、消费者状态,与开发没有直接关系。

调用关系说明:

① 服务容器spring负责启动,加载,运行服务提供者。

② 服务提供者在启动时,向注册中心注册自己提供的服务。

③ 服务消费者在启动时,向注册中心订阅自己所需的服务。

④ 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

⑤ 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

⑥ 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

三、Dubbo支持的协议

支持多种协议:dubbo , hessian , rmi , http, webservice , thrift , memcached , redis。

dubbo官方推荐使用dubbo协议。dubbo协议默认端口20880

使用dubbo协议,spring配置文件加入:

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

四、电商平台需求

某电商平台系统需求,用户浏览商品;选择商品下订单,订单系统需要获取用户信息中的送货地址;向支付系统请求完成付款。

服务 功能
网站系统 展示商品,修改用户信息
订单系统 生成订单
用户系统 用户信息(地址,收件人,联系方式等)

五、直连方式dubbo

点对点的直连项目:消费者直接访问服务提供者,没有注册中心。消费者必须指定服务提供者的访问(URL)地址。

消费者直接通过URL地址访问固定的服务提供者。这个URL地址是不变的。

1. 实现目标

用户访问 ------>【商品网站服务】访问-----> 【订单服务】

2. 实现方式

以JavaSE为例,服务提供者,服务消费者都是JavaSE项目

(1) 创建父工程:parent

A. maven pom.xml

<?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.suke</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>../order-provider</module>
        <module>../web-consumer</module>
    </modules>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
        <spring.version>5.0.3.RELEASE</spring.version>
        <dubbo.version>2.6.2</dubbo.version>
    </properties>

    <packaging>pom</packaging>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <!--Dubbo依赖-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!--   <pluginManagement>
               <plugins>
                   <plugin>
                       <artifactId>maven-compiler-plugin</artifactId>
                       <version>3.1</version>
                       <configuration>
                           <source>1.8</source>
                           <target>1.8</target>
                       </configuration>
                   </plugin>
               </plugins>
           </pluginManagement>-->
    </build>
</project>

B. 删除src目录 

(2)创建服务提供者:订单服务

A. 新建java project

项目名称:orderservice-provider

设置version 为 1.0.0

B. maven pom.xml

<?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">
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.suke</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-provider</artifactId>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>

        <!--Dubbo依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
    </dependencies>
</project>

C. 创建订单实体类:Order

package com.suke.provider.bean;

import java.io.Serializable;

public class Order implements Serializable {

    private String id;
    private String goodsName;
    private Double price;
    private Integer amount;

    @Override
    public String toString() {
        return "Order{" +
                "id='" + id + '\'' +
                ", goodsName='" + goodsName + '\'' +
                ", price=" + price +
                ", amount=" + amount +
                '}';
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }
}

D. 新建订单服务接口:OrderService

package com.suke.provider.service;

import com.suke.provider.bean.Order;

public interface OrderService {
    Order addOrder(String id, String goodsName, Double price, Integer amount);
}

E. 新建接口的实现类:OrderServiceImpl

package com.suke.provider.service.impl;

import com.suke.provider.bean.Order;
import com.suke.provider.service.OrderService;

import java.util.UUID;

public class OrderServiceImpl implements OrderService {

    @Override
    public Order addOrder(String id, String goodsName, Double price, Integer amount) {
        Order order = new Order();
        order.setId(UUID.randomUUID().toString().replace("-", ""));
        order.setGoodsName(goodsName);
        order.setPrice(price);
        order.setAmount(amount);
        return order;
    }
}

F. 创建dubbo配置文件: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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://dubbo.apache.org/schema/dubbo
        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!--给服务提供从起一个唯一标识-->
    <dubbo:application name="provider"/>

    <!--使用Dubbo协议通信-->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!--对外开放的接口,N/A:不使用注册中心-->
    <dubbo:service interface="com.suke.provider.service.OrderService"
                   ref="orderService" registry="N/A"/>

    <bean id="orderService" class="com.suke.provider.service.impl.OrderServiceImpl"/>
</beans>

G. 测试配置文件

package com.suke.provider.test;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Scanner;

public class TestProvider {

    public static void main(String[] args) {
        BeanFactory beanFactory =
                new ClassPathXmlApplicationContext("classpath:provider.xml");
        ((ClassPathXmlApplicationContext) beanFactory).start();
        //服务的提供方必须一直运行 阻塞方式
        System.out.println("服务器已运行");
        Scanner scanner = new Scanner(System.in);
        scanner.nextInt();
    }
}

H. 安装本地jar 到maven仓库

① 服务接口中的方法要给消费者使用,消费者项目需要知道接口名称和接口中的方法名称、参数等。这些信息服务提供者才知道。需要把接口的class文件打包为jar。

② 服务接口项目的类文件打包为jar, 安装到maven仓库,仓库中的提供者jar可以被消费者使用。

③ 使用IDEA的maven窗口执行 install。

(2)创建服务消费者:商品网站

A. 新建java project

项目名称:web-consumer

设置version 为 1.0.0

B. maven pom.xml

<?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">
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.suke</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>web-consumer</artifactId>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>

        <!--Dubbo依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>

        <!--引入提供者坐标-->
        <dependency>
            <groupId>com.suke</groupId>
            <artifactId>order-provider</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>
</project>

C. 创建购买商品接口:GoodService

package com.suke.consumer.service;

import com.suke.provider.bean.Order;

public interface GoodService {
    Order buyGood(String id, String goodsName, Double price, Integer amount);
}

D. 创建购买接口的实现类:GoodServiceImpl

package com.suke.consumer.service.impl;

import com.suke.consumer.service.GoodService;
import com.suke.provider.bean.Order;
import com.suke.provider.service.OrderService;

public class GoodServiceImpl implements GoodService {

    private OrderService orderService;

    public OrderService getOrderService() {
        return orderService;
    }

    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public Order buyGood(String id, String goodsName, Double price, Integer amount) {
        return orderService.addOrder(id, goodsName, price, amount);
    }
}

E. 创建dubbo配置文件:consume.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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://dubbo.apache.org/schema/dubbo
        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!--给服务消费者起一个唯一标识-->
    <dubbo:application name="consumer"/>

    <!--查找开放指定接口-->
    <dubbo:reference interface="com.suke.provider.service.OrderService"
                     url="dubbo://localhost:20880" registry="N/A" id="remoteService"/>

    <!--配置消费方的服务对象-->
    <bean id="goodService" class="com.suke.consumer.service.impl.GoodServiceImpl">
        <property name="orderService" ref="remoteService"/>
    </bean>
</beans>

F. 执行消费者

六、Dubbo服务化最佳实践

1. 分包

建议将服务接口、服务模型、服务异常等均放在公共包中。

2. 粒度

① 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,

② 服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。

③ 不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。

3. 版本

每个接口都应定义版本号,区分同一接口的不同实现,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />。

七、改造Dubbo项目

抽象分散在多个项目中的公共接口,实体类,异常,工具类到一个项目中,在其他项目如服务提供者,消费者共用公共的资源。

1. 实现目标

用户访问电商网站浏览商品—选择商品购买

用户访问电商网站—查看用户信息(收件人地址)

项目是web应用,需要加入spring web开发jar:

maven依赖

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>4.3.16.RELEASE</version>

</dependency>

2. 创建公共资源项目

服务提供者,消费者,网站等多个服务中共用,重复使用的类单独定义在一个项目。

A. 创建公共的maven java project

项目名称:bean

项目名称:common-interface

项目名称:common-util

接口工程的Maven坐标

  

B. 复制之前的Order实体类、OrderService业务接口到新建项目

八、dubbo常用标签

Dubbo中常用标签。分为三个类别:公用标签,服务提供者标签,服务消费者标签

1. 公用标签

<dubbo:application/> 和 <dubbo:registry/>

A. 配置应用信息

<dubbo:application name=”服务的名称”/>

B. 配置注册中心

<dubbo:registry address=”ip:port” protocol=”协议”/>

2. 服务提供者标签

配置暴露的服务

<dubbo:service interface=”服务接口名” ref=”服务实现对象bean”>

3. 服务消费者

配置服务消费者引用远程服务

<dubbo:reference id=”服务引用bean的id” interface=”服务接口名”/>

猜你喜欢

转载自blog.csdn.net/qq_45037155/article/details/124955382