高级框架第二天Dubbo:高效的RPC框架

主要内容

1.Dubbo简介

2.Dubbo架构讲解

3.Dubbo支持的协议

4.Dubbo支持的注册中心

5.第一个Dubbo的Provider

6.Admin管理界面搭建

7.完成Dubbo的Consumer

8.负载均衡

9.完整Dubbo项目演示

一.Dubbo简介

1.官方说明

Apache Dubbo是一个高可用的,基于Java的开源RPC框架

Dubbo框架不仅仅是具备RPC访问功能,还包含服务治理功能

2发展历史

Dubbo最开始是阿里巴巴内部使用的RPC框架

2011年对外提供

2012年停止更新

2017年开始继续更新

2019年捐献给Apache,由Apaceh维护2.7以上版本

二.Dubbo框架讲解

1.架构图

架构图

2.架构说明

2.1虚线

虚线表示异步,实现表示同步.异步不阻塞线程性能高,同步阻塞线程必须等待响应结果才能继续执行,相对性能低

2.2Provider

提供者.编写持久层,业务层和事务代码

2.3Container

容器(Spring容器),Dubbo完全基于Spring实现的

2.4Registry

注册中心.放置所有Provider对外提供的信息.包含Provider的IP,访问端口,访问遵守的协议,对外提供的接口,接口中有哪些方法等相关信息

2.5Consumer

消费者(RPC调用者,SOA调用服务的项目)开发中也是一个项目,编写service和controller(还可以包括页面等).调用远程服务实现(XXXServiceImpl)中的方法

2.6Monitor

监控中心.监控Provider的压力情况等.每个2分钟Consumer和Provider会把调用次数发送给Monitor,由Monitor进行统计

3.执行流程

0.start:启动Spring容器时会把Provider启动

1.register:把Provider相关信息注册到Registry里

2.subscribe:Consumer从Registry中订阅Provider的信息

3.notify:通知给Consumer

4.invoke:Consumer根据Registry通知的信息进行调用Provider中方法

5.count:Consumer和Provider把调用次数信息异步发送给Monitor进行统计

三.Dubbo支持的协议

1.Dubbo协议(官方推荐协议)

优点:

    采用NIO复用单一长链接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用)协议的默认端口是:20880.(端口是服务端Provider占用的)

缺点:

    大文件上传时,可能出现问题(不使用Dubbo实现文件传输)

2.RMI(Remote Method Invocation)协议

优点:

    jdk自带的能力

缺点:

    偶尔连接失败

3.Hessian协议

优点:

    可与原生Hession互操作,基于HTTP协议

缺点:

    需hession.jar支持,http短连接的开销大

四.Dubbo支持的注册中心

1.Zookeeper(官方推荐)

1)优点:

支持分布式,很多周边产品

2)缺点:

受限于Zookeeper软件的稳定性.Zookeeper专门分布式辅助软件,稳定性较优

2.Multicast

1)优点

去中心化,不需要单独安装软件

2)缺点:

2.2.1Provider,Consumer和Registry不能跨机房(路由)

3.Redis

1)优点:

支持集群,性能高

2)缺点:要求服务器时间同步,否则可能出现集群失败问题

4.Simple

1)优点:

标准RPC服务,没有兼容问题

2)缺点:

不支持集群

五.第一个Dubbo的Provider

新建父项目Parent1.最终结构如下:

编写pom.xml继承SpringBoot父项目

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.2.5.RELEASE</version>

</parent>

1.新建api项目

1.1创建接口

创建com.bjsxt.dubbo.service.DemoDubboService接口

public interface DemoDubboService{

    String demo();

}

2.新建propvider项目

2.1编写pom.xml

注意:不需要依赖web,如果依赖spring-boot-start-web还需要考虑端口问题

<dependencies>

    <dependency>

        <artifactId>api</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>dubbo-spring-boot-starter</artifactId>

        <version>2.7.3</version>

    <dependency>

    <dependency>

        <groupId>prg.apache.curator</groupId>

        <artifactId>curator-recipes<a/rtifactId>

        <version>4.2.0</version>

    </dependency>

   <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-framework</artifactId>

        <version>4.2.0</version>

    </dependency>

</dependencies>

2.2编写配置文件

新建application.yml

dubbo:

    application:

        name: dubbo-provider

registry:

    address: zookeeper://192.168.232.132:2181

2.3先进实现类

先进com.bjsxt.dubbo.service.impl.DemoDubboServiceImpl

注意:

    注解是apache的注解

import com.bjsxt.dubbo.service.DemoDubboService;

import org.apache.dubbo.config.annotation.Service;

@Service

public class DemoDubboServiceImpl implements DemoDubboService{

    @Override

    public String demo(){

        System.out.println("demo方法");

        return "123";

    }

}

2.4新建启动类

新建com.bjext.ProviderApplication

必须要有@EnableDubbo注解,否则Dubbo不生效

@SpringBootApplication

@EnableDubbo

public class ProviderApplication{

    public static void main(String[] args){             SpringApplication.run(ProviderApplication.class,args);

    }

}

六.Admin管理界面搭建

01资料中把dubbo-admin-server-0.2.0.jar\BOOT-INF\classes中application.properties里面注册中心的ip设置正确

使用java -jar dubbo-admin-server-0.2.0.jar运行即可.访问http://localhost:8080可以进入Dubbo Admin管理控制台

注意:占用8080端口,不要冲突了.如果需要修改端口,增加配置server.port=新端口号

七.完成Dubbo的Consumer

创建consumer项目

1.编写pom.xml

<dependencies>

    <dependency>

        <artifactId>api</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>spring-boot-starter-web</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.dubbo</groupId>

        <artifactId>dubbo-spring-boot-starter</artifactId>

        <version>2.7.3</version>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-recipes</artifactId>

        <version>4.2.0</version>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-framework</artifactId>

        <version>4.2.0</version>

    </dependency>

</dependencies>

2.新建配置文件

新建application.yml

dubbo:

    application:

        name: dubbo-consumer

registry:

    address: zookeeper://192.168.232.132:2181

3.新建service及实现类

新建com.bjsxt.service.DemoService

新建com.bjsxt.service.impl.DemoServiceImpl

调用服务使用@Reference注解,不要导错包了,有两个

public interface DemoService{

    String comsumerDemo();

}

import com.bjsxt.dubbo.service.DemoDubboService;

import com.bjsxt.service.DemoService;

import org.apache.dubbo.config.annotation.Reference;

import org.springframework.stereotype.Service;

@Service

public class DemoServiceImpl implements DemoService{

    @Reference

    private DemoDubboService demoDubboService;

    @override

    public String consumerDemo(){

        return demoDubboService.demo();

    }

}

4.新建控制器

新建控制器com.bjsxt.controller.DemoController

@Controller

publci class DemoController{

    @Autowired

    private DemoService demoService;

    @RequestMapping("/demo")

    @ResponseBody

    public String demo(){

        return demoService.consumerDemo();

    }

}

5.新建启动器

先进com.bjsxt.ConsumerApplication

@SpringBootApplication

@EnableDubbo

public class ConsumerApplication{

    public static void main(String[] args){

        SpringApplication.run(ConsumerApplication.class,args);

    }

}

八.负载均衡

集群:一个内容,部署多次,形成的整体称为集群.集群中每个个体应该部署到不同的服务器上.

伪集群:集群中内部部署到同一台服务器上,通过不同端口区分不同个体

负载均衡是在集群前提下,当访问整个集群时,集群中每个节点被访问次数或频率的规则

Dubbo内置了四个负载均衡策略.默认为Random

负载均衡策略的决定规则:

1.Provider方默认负载均衡策略是Random,随机策略

2.Consumer方默认负载均衡策略不设定,使用Provider提供的负载均衡策略

3.如果双方都设置了负载均衡策略,使用Consumer的负载均衡策略,因为局部优先,Provider是给所有的Consumer提供服务的,负载均衡策略也是给所有的Consumer提供的默认策略.Consumer的负载均衡策略只局限在当前消费端,是一个局部策略

1.内置策略

1.1Random

随机.随机访问集群中节点.访问概率和权重有关

1.2RoundRobin

轮训.访问评率和权重有关

权重(weight):占有比例.集群中,每个项目部署的服务器的性能可能是不同,性能好的服务器权重应该高一些

1.3LeastActive

活页数相同的随机,不同的活跃数高的放前面

1.4ConsistentHash

一致性Hash.相同参数请求总是发到一个提供者

2.Provider集群

新建四个启动类

每次启动启动类修改配置文件dubbo.protocal.port.默认20880

3.设置负载均衡

3.1@Reference

调用的服务采用的负载均衡

@Reference(loadbalance="roundrobin")

private DemoDubboService demoDubboService;

3.2@Service

当前服务采用的负载均衡算法

@Service(loadbalance="random")

public class DemoDubboServiceImpl implements DemoDubboService{

    设置权重

    @Service(weight=4)

}

3.3配置文件

全局设置所有provider和consumer的负载均衡效果

dubbo:

    application:

        name:    dubbo-provider

    registry:

        address: zookeeper://192.168.232.132:2181

    protocol:

        port: 20884

    provider;

        loadbalance: random

    consumer:

        loadbalance: random

九.注解常用属性详解

1.group分组

为服务人为划分组别.Provider可以在不同的组中注册类似的服务.Consumer可以指定获取远程服务所在分组,获取徐亚ode远程服务.通过分组属性,可以更清晰的管理服务.

Provider注册服务到userGroup分组,注解如下:

@Service(group="userGroup")

Consumer获取userGroup分组下的指定服务,注解如下:

@Reference(group="userGroup")

2.version版本

为服务定制版本.Provider可以为同一个服务发布多个版本的实现.Consumer可以根据具体情况,获取指定版本的服务代理对象.通过版本属性,可以让服务的应用更加细致.

Provider注册服务版本,注解如下:

@Service(group="userGroup",version="1.0")

Consumer获取指定版本的服务,注解如下:

@Service(group="userGroup",version="1.0")

3.payload限制

在Dubbo中,默认限制请求和应答最大容量为8M(8388608).当请求或应答数据容量超标时,会抛出异常.需要通过配置文件设置更大的限制,具体如下:

dubbo:

    registry:

        address: zookeeper://192.168.232.132:2181

    application:

        name:dubbo-first-consumer

    provider:

        payload:83886080 # 设置请求和应答容量限制为8M

十.完整Dubbo项目演示

1.原型

1.1部门显示

显示全部部门信息

1.2员工新增

1.3查看部门员工

2.按照分布式架构进行设计项目

设定员工管理和部门不在同一个模块,需要有一个员工管理项目和一个部门管理项目.

为了方便,不去每个项目使用一个窗口,而是使用聚合项目

3.创建数据库表

create table dept(

    id int(11) primary key auto_increment,

    name varchar(20)

);

insert into dept values(default,'开发部');

insert into dept values(default,'产品部');

create table emp(

    id int(11) primary key auto_increment,

    name varchar(20),

    photo varchar(200),

    did int(11),

    CONSTRAINT fk_emp_dept FOREIGN key (did) REFERENCES dept(id)

);

4.使用逆向工程

5.创建父项目

5.1创建项目parent

5.2编写pom.xml

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.2.5.RELEASE</version>

</parent>

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter</artifactId>

        </depenency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

        <dependency>

            <groupId>org.apaceh.dubbo</groupId>

            <artifactId>dubbo-spring-boot-starter</artifactId>

            <version>2.7.3</version>

        </dependency>

        <dependency>

            <groupId>org.apache.dubbo</groupId>

            <artifactId>dubbo-spring-boot-starter</artifactId>

            <version>2.7.3</version>

        </dependency>

        <dependency>

            <groupId>org.apache.curator</groupId>

            <artifactId>curator-recipes</artifactId>

            <version>4.2.0</version>

        </dependency>

        <dependency>

            <groupId>org.apache.curator</groupId>

            <artifactId>curator-framework</artifactId>

            <version>4.2.0</version>

        </dependency>

        <dependency>

            <groupId>org.mybatis.spring.boot</groupId>

            <artifactId>mybatis-spring-boot-starter</artifactId>

            <version>2.1.1</version>

        </dependency>

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

            <version>5.1.48</version>

        </dependency>

        <dependency>

            <groupId>commons-io</groupId>

            <artifactId>commons-io</artifactId>

            <version>2.6</version>

        </dependency>

    </depenencies>

</depenencyManagement>

6.创建pojo项目

把逆向工程代码粘贴进来

7.创建mapper项目

71.编写pom.xml

<dependencies>

    <dependency>

        <artifactId>pojo</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>org.mybatis.spring.boot</groupId>

        <artifactId>mybatis-spring-boot-starter</artifactId>

    </dependency>

    <dependency>

        <groupId>mysql</groupId>

        <artifactId>mysql-connector-java</artifactId>

    </depenency>

</dependencies>

7.2新建配置文件

先进application-mybatis.yml

spring:

    datasource:

        driver-class-name:com.mysql.cj.jdbc.Driver

        url:jdbc:mysql://localhost:3306/maven?serverTimezone=GMT%2B8

        username:root

        password:root

mybatis:

    mapper-location:classpath:mybatis/*.xml

    type-aliases-package:com.bjsxt.pojo

从逆向工程中把mapper接口和mapper.xml粘贴进行

8.先进api项目

8.1编写pom.xml

<dependencies>

    <dependency>pojo</dependency>

    <groupId>com.bjsxt</groupId>

    <version>1.0-SNAPSHOT</version>

</dependencies>

9.先进provider

9.1编写pom.xml

<dependencies>

    <dependency>

        <artifactId>mapper</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <artifactId>api</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.dubbo</groupId>

        <artifactId>dubbo-spring-boot-starter</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-recipes</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-framework</artifactId>

    </dependency>

</dependencies>

9.2先进配置文件

新建application.yml

dubbo:

    application:

        name:dubbo-provider

    registry:

        address: zookeeper://192.168.232.132:2181

#加载其他配置文件,加载其他application-*.yml文件,多个名称之间使用逗号分隔

spring:

    profiles:

        active:mybatis

9.3新建启动类

先进com.bjsxt.ProviderApplication

@SpringBootApplication

@EnableDubbo

@MapperScan("com.bjsxt.mapper")

public class ProviderApplication{

    public static void main(String[] args){

        SpringApplication.run(ProviderApplication.class,args);

    }

}

10.完成Dept查询功能

10.1在api中先进接口

com.bjsxt.dubbo.servcie.DeptDubboService

public interfacr DeptDubboService{

    List<Dept>selectAll();

}

10.2在provider中先进实现类

com.bsjxt.dubbo.service.DeptDubboServiceImpl

@Service

public class DeptDubboServiceImpl implements DeptDubboService{

    @Autowired

    private DeptMapper deptMapper;

    @Override

    public List<Dept>selectAll(){

        return deptMapper.selectByExample(null);

    }

}

10.3新建项目dept

10.3.1添加依赖

<dependencies>

    <dependency>

        <artifactId>api</artifactId>

        <groupId>com.bjsxt</groupId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-thymeleaf</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.dubbo</groupId>

        <artifactId>dubbo-spring-boot-starter</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.curator</groupId>

        <artifactId>curator-recipes</artifactId>

    </dependency>

    <dependency>

        <groupId>oeg.apache.curator</groupId>

        <artifactId>curator-framework</artifatId>

    </dependency>

</dependencies>

10.3.2编写配置文件

新建application.yml

dubbo:

    application:

        name:dubo-dept-consumer

    registry:

        address: zookeeper://192.168.232.132:2181

10.3.3新建启动类

com.bjsxt.DeptApplication

@SrpingBootApplication

@EnableDubbo

public class DeptApplication{

    publci static void main(String[] args){

        SpringApplication.run(DeptApplication.class,args);

    }

}

10.4新建接口及实现类

接口:com.bjsxt.service.DeptService

实现类:com.bjsxt.service.impl.DeptServiceImpl

public interface DeptService{

    List<Dept>showAll();

}

@Servcie

public class DeptServcieImpl implements DeptService{

    @Reference

    private DeptDubboService deptDubboServcie;

    @Override

    public List<Dept>showAll(){

        return deptDubboService.selectAll();

    };

}

10.3.5新建控制器

com.bjsxt.controller.DeptController

@Controller

public class DeptController{

    @Autowired

    private DeptServcie deptService;

    @GetMapping("/dept")

    public String showDept(Model model){

        model.addAttribute("list",deptService.showAll());

        return "dept";

    }

}

10.3.6新建页面

在resources/templates新建dept.html

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

    <table border="1" width="500">

        <tr>

            <th>编号</th>

            <th>部门名称</th>

            <th>查看</th>

        </tr>

        <tr th:each="dept:${list}">

            <td th:text="${dept.id}"></td>w

            <td th:text="${dept.name}"></td>

            <td><a th:href="@{/showEmp(did=${dept.id})}">查看</a></td>.

        </tr>

    </table>

</body>

</html>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342