dubbo系统学习

目录

1.什么是Dubbo

2.架构的演变

3.dubbo的架构图(链接)

1.dubbo的demo(链接)

1.服务提供者

2.创建服务消费者

3.连接zookeeper(服务注册与发现的注册中心)

2.dubbo三种开发方式

3.dubbo的配置优先级

4.属性配置(🔗)

5.注解配置(🔗)

4.dubbo用法

1.启动时检查(🔗)

2.集群容错(🔗)

1.服务的集群容错:

3.集群负载均衡策略(🔗)

一致性hash算法

4.集群容错(🔗)

5.线程模型(🔗)

6.直连提供者(🔗)

7.多协议(链接)

1.dubbo协议(链接)

2.rmi协议

8.多注册中心(🔗)

9.服务分组(🔗)

10.JSON泛化调用(🔗)

11.服务化最佳实践(🔗)

版本:

调用

5.springboot与dubbo整合

1.springboot与dubbo的依赖

2.建表

3.拆分模块

4.开发用户服务


1.什么是Dubbo

dubbo:是一个基于soa思想的rpc框架(rpc:远程服务调用)

1.高性能RPC框架

2.服务治理 资源调度

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

soa思想:面向服务的架构

给每一个模块暴露对应的ip和端口,当做一个服务进行运行

重点在于服务的管理(负载均衡,容灾模式,服务的横向扩展)

2.架构的演变

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

流动计算架构(自认为这个是微服务)
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

分布式服务架构:

3.dubbo的架构图(链接

节点

角色说明

Provider

暴露服务的服务提供方

Consumer

调用远程服务的服务消费方

Registry

服务注册与发现的注册中心

Monitor

统计服务的调用次数和调用时间的监控中心

Container

服务运行容器,建议是spring

1.dubbo的demo(链接

1.服务提供者

1.引入依赖 spring dubbo zookeeper zkclient

  <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.12</version>
        </dependency>

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>

2.开发服务类(接口和实现类)

public interface DemoService {
    String sayHello(String name);
}
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        System.out.println("hello"+name);
        return "hello"+name;
    }
}

3.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">
    <!-- 提供方应用信息,用于计算依赖关系       唯一应用名,标识(项目模块名)-->
    <dubbo:application name="dubbo_provider1"  />

    <!-- 使用multicast广播注册中心暴露服务地址multicast://224.5.6.7:1234      指定注册中心(zookeeper)-->
    <dubbo:registry address="zookeeper://192.168.231.135:2181" />

    <!-- 用dubbo协议在20880端口暴露服务     指定服务的协议:dubbo协议(固定)和使用的端口号(随意)-->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口       注册服务到注册中心-->
    <dubbo:service interface="com.liziyi.service.DemoService" ref="demoService" />

    <!-- 和本地bean一样实现服务    服务实现类-->
    <bean id="demoService" class="com.liziyi.service.impl.DemoServiceImpl" />
</beans>

4.发布服务

public class Provider {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
        context.start();
        System.out.println("服务提供者,开始提供服务----------------");
        System.in.read(); // 按任意键退出
    }
}

2.创建服务消费者

1.引入依赖 spring dubbo zookeeper zkclient

2.调用服务配置服务

1.将生产者接口拷贝|创建 到消费者中

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

3.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">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样   服务消费者-->
    <dubbo:application name="dubbo_consumer1"  />

    <!-- 使用multicast广播注册中心暴露发现服务地址     配置注册中心(zookeeper)-->
    <dubbo:registry address="zookeeper://192.168.231.135:2181" />

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService    调用服务-->
    <dubbo:reference id="demoService" interface="com.liziyi.service.DemoService" />
</beans>

3.服务调用

public class Consumer {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理
        String hello = demoService.sayHello("world"); // 执行远程方法
        System.out.println( hello ); // 显示调用结果
    }
}

3.连接zookeeper(服务注册与发现的注册中心)

安装zookeeper

cd /opt/software/zookeeper/bin
#连接客户端
./zkCli.sh

这就证明连接成功!

查看里面的内容

dubbo%3A%2F%2F192.168.231.1%3A20880%2Fcom.liziyi.service.DemoService%3Fanyhost%3Dtrue%26application%3Ddubbo_provider1%26dubbo%3D2.5.3%26interface%3Dcom.liziyi.service.DemoService%26methods%3DsayHel%3D504%26side%3Dprovider%26timestamp%3D1626694429185

转码:

public class TestDubborProviders {
    @Test
    public void test() throws UnsupportedEncodingException {
        String s = "dubbo%3A%2F%2F192.168.231.1%3A20880%2Fcom.liziyi.service.DemoService%3Fanyhost%3Dtrue%26application%" +
                "3Ddubbo_provider1%26dubbo%3D2.5.3%26interface%3Dcom.liziyi.service.DemoService%26methods%3DsayHel%3D504" +
                "%26side%3Dprovider%26timestamp%3D1626694429185";
        String decode = URLDecoder.decode(s, "UTF-8");
        System.out.println(decode);
    }
}

结果:

dubbo://192.168.231.1:20880/com.liziyi.service.DemoService?anyhost=true&application=dubbo_provider1&dubbo=2.5.3&interface=com.liziyi.service.DemoService&methods=sayHel=504&side=provider&timestamp=1626694429185

2.dubbo三种开发方式

1.dubbo+spring 上面的demo

2.dubbo 原始API

3.dubbo+spring 注解式开发

3.dubbo的配置优先级

设置过期时间:(链接

方法级优先,接口级次之,全局配置再次之。

如果级别一样,则消费方优先,提供方次之。

(建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置)。

4.属性配置(🔗

5.注解配置(🔗

使用@Service就不需要在provider.xml文件中指定下面这几条内容:

@Service
public class AnnotationServiceImpl implements AnnotationService {
    @Override
    public String sayHello(String name) {
        return "annotation: hello, " + name;
    }
}

4.dubbo用法

1.启动时检查(🔗

2.集群容错(🔗

1.服务的集群容错:

1.搭建服务方 3个或多个服务

做集群的时候,复制duboo_provider1后如果出现下面情况:

rename改名即可

2.启动多个服务

因为在一台机器上,所以配置三个端口 20881 ,2, 3

3.集群负载均衡策略(🔗

建议配置在服务端

Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
轮询,按公约后的权重设置轮询比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />
缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />
配

一致性hash算法

因为热点问题,提出虚拟节点。

默认160份,均匀分布在圆上,找到某个虚拟节点,其实就是对应的真实节点。

真实节点:

192.168.0.3

虚拟:1.1.1.0-1.1.1.159(举例)

192.168.0.4

虚拟:2.1.1.0-2.1.1.159

192.168.0.5

虚拟:3.1.1.0-3.1.1.159

4.集群容错(🔗)

5.线程模型(🔗

如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。

但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。

如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。

参数详情见官网

6.直连提供者(🔗

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。

用法:在消费端

<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" />

7.多协议(链接

1.dubbo协议(链接

Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。

反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。

2.rmi协议

适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
适用场景:常规远程服务方法调用,与原生RMI服务互操作

8.多注册中心(🔗

Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的 

9.服务分组(🔗

10.JSON泛化调用(🔗

对于Dubbo泛化调用,提供一种新的方式:直接传递字符串来完成一次调用。即用户可以直接传递参数对象的json字符串来完成一次Dubbo泛化调用

当客户端没有接口时,怎么调用服务端的服务呢?

客户端的consumer.xml添加上generic="true"

    <dubbo:reference id="demoService" interface="com.liziyi.service.DemoService" generic="true" />

客户端

public class Consumer {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
        GenericService genericService = (GenericService) context.getBean("demoService");
        // 传递参数对象的json字符串进行一次调用
            // 参数1:调用的方法名称
            // 参数2:调用参数类型
            // 参数3:调用参数类型对应的值
        Object res = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"xiaohei"});
        System.out.println("result[setUser]:"+res); // 响应结果:result[setUser]:{name=Tom, class=com.xxx.api.service.User, age=24}
        System.in.read(); // 按任意键退出
    }
}

11.服务化最佳实践(🔗

版本:

每个接口都应定义版本号,为后续不兼容升级提供可能,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />。

建议使用两位版本号,因为第三位版本号通常表示兼容升级,只有不兼容时才需要变更服务版本。

当不兼容时,先升级一半提供者为新版本,再将消费者全部升为新版本,然后将剩下的一半提供者升为新版本。

调用

Provider 端需要对输入参数进行校验。如有性能上的考虑,服务实现者可以考虑在 API 包上加上服务 Stub 类来完成检验。如下参数验证:

参数验证(🔗

5.springboot与dubbo整合

1.springboot与dubbo的依赖

 <!--dubbo-springBoot依赖 springboot是1.5.7只能用dubbo的1.0.2 1.5.6对应1.0.1  2.1.5对应1.1.3-->
        <dependency>
            <groupId>com.gitee.reger</groupId>
            <artifactId>spring-boot-starter-dubbo</artifactId>
            <version>1.0.2</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--整合web开发-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--testclient-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>

        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>

2.建表

3.拆分模块

cmfz_user cmfz_commons cmfz_book cmfz_back_sys(后台) cmfz_front_sys(前台)

4.开发用户服务

这样子模块可以拿到父模块全部的依赖。

1).业务层加入下面第三个注解

@Service
@Transactional
@com.alibaba.dubbo.config.annotation.Service(interfaceClass = UserService.class)
public class UserServiceImpl implements UserService {

2).配置文件中配置dubbo

server:
  port: 8989
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    data-username: root
    data-password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  dubbo:
    application:
      name: cmfz_user
    registry:
      address: zookeeper://192.168.231.136:2181
    protocol:
      name: dubbo
      port: 20881
    base-package: com.liziyi.cmfz.service
mybatis:
  mapper-locations: classpath:com/liziyi/mapper/*.xml

  • 24
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值