• Dubbo


    1、Dubbo基础知识

    1、什么是分布式系统?

    ​ 分布式系统是若干个独立计算机的集合,这些计算机对于用户来说就像单个相关系统。分布式系统是建立在网络之上的软件系统。

    2、分布式的发展演练

    img

    3、RPC

    ​ 简单的理解就是,RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数或方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

    RPC两个核心模块:通讯,序列化

    2、Dubbo

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

    基本概念:

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

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

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

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

    ​ 下面罗列一些Dubbo常用的,也就是说每个项目的Dubbo的Xml文件中基本都会出现的标签,并以表格的形式列举标签中常见的可用属性:

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.test.UserServiceBo" ref="userService" version="1.0.0" timeout="3000"/>
    

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="userService" interface="com.test.UserServiceBo" version="1.0.0" timeout="3000"/>
    

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    

    Dubbo配置的覆盖规则:

    • 方法配置级别优于接口级别
    • Consumer端配置优于Provider配置优于全局配置
    • 最后是Dubbo Hard Code的配置值

    2.1、使用dubbo+zookeeper整合springboot创建提供者、消费者案列:

    提供者:

    首先导入相关的依赖jar包

    <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>2.7.3</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
            <!--<dependency>
                <groupId>com.github.sgroschupf</groupId>
                <artifactId>zkclient</artifactId>
                <version>0.1</version>
            </dependency>-->
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>2.12.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>2.12.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.14</version>
                <exclusions>
                    <exclusion>
                        <artifactId>slf4j-log4j12</artifactId>
                        <groupId>org.slf4j</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    这里有个版本配合,dubbo的版本在25之间使用zkClient的jar包,2.5之后使用curator依赖包。

    然后在properties中配置

    #要注册的服务名
    dubbo.application.name=provider-server
    #注册中心的地址
    dubbo.registry.address=zookeeper://127.0.0.1:2181
    #扫描包下要被注册的服务
    dubbo.scan.base-packages=com.hao.service
    

    编写实现类

    @Service  //注意:这里使用的是dubbo下的service注解
    @Component  //让其被扫描到,放到IOC容器中去
    public class BuyTicketImpl implements BuyTicket {
        @Override
        public String buyTicket() {
          return "快点买票啊,不然就回不去了";
        }
    }
    

    这样就可以在监控中心可以看到该提供者了

    消费者:

    首先跟提供者一样导入一样的jar包,跟上面一样

    其次就在配置文件中配置消费者信息

    #消费者名字
    dubbo.application.name=consumer-server
    #注册中心地址
    dubbo.registry.address=zookeeper://127.0.0.1:2181
    

    然后就是使用了,首先先创建一个跟提供者一样包路径的接口,再生成相应的实现类

    @Controller
    @Service  //注意:这里使用的是springmvc中的service注解
    public class UserService {
        @Reference
        BuyTicket buyTicket;
        @RequestMapping("/dd")
        @ResponseBody
        public String buyTicket(){
            String s = buyTicket.buyTicket();
            return s;
        }
    }
    

    这样消费者就可以通过dubbo+zookeeper拿到不同服务器上的服务了。这个是基于springboot做的。

    下面是基于spring项目搭建的

    提供者:

      <dependencies>
            <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.6.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.4</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>2.12.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>2.12.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.14</version>
                <exclusions>
                    <exclusion>
                        <artifactId>slf4j-log4j12</artifactId>
                        <groupId>org.slf4j</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
    <?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:context="http://www.springframework.org/schema/context"
           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://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context.xsd
    		 http://code.alibabatech.com/schema/dubbo
    		 http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        <dubbo:application name="DubboDemo-Provider"/>
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
        <dubbo:protocol name="dubbo" port="20880"/>
        <bean id="UserServiceImpl" class="com.hao.service.UserServiceImpl"/>
    
        <dubbo:service interface="com.hao.service.UserService" ref="UserServiceImpl"/>
    
    </beans>
    
    //提供者启动类
    public class test {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-provider.xml"); //通过读取配置文件获取容器
            context.start(); 
            System.out.println("提供者服务已注册成功");
            try {
                System.in.read();  //让该程序一直执行下去,不会停止
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    在启动的时候可能会报日志冲突的问题:需要自己在resource文件夹下添加log4j.properties文件

    ###set log levels###
    log4j.rootLogger=info, stdout
    ###output to the console###
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n
    

    消费者:

    消费者这里也要创建一个和提供者一样的接口。

    public interface UserService {
        String say();
    }
    

    配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <dubbo:application name="dubboDemo-consumer"/>
    
        <!-- 使用预发 -->
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    
        <dubbo:reference interface="com.hao.service.UserService" id="user"/>
    
    </beans>
    
    public class test {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-consumer.xml"); //也是通过读取配置文件获取容器,再通过容器获取指定的接口实现类
            context.start();
            UserService user = context.getBean("user", UserService.class);
            System.out.println("执行前");
            String say = user.say();
            System.out.println(say);  //这里注意:消费者只能获取到提供者接口实现类中return的值,方法具体中具体的实现获取不了。
            System.out.println("执行后");
            try {
                System.in.read();  //让程序一直运行下去。
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    zookeeper宕机与dubbo直连

    现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务。

    原因:

    • 监控中心宕机后不影响使用,只是丢失部分采样数据。
    • 数据库宕机后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务。
    • 注册中心对等集群,任意一台宕机后,将自动切换到另一台。
    • 注册中心全部宕机后,服务提供者和服务消费者仍能通过本地缓存通讯。
    • 服务提供者无状态,任意一台宕机后,不影响使用。
    • 服务提供者全部宕机后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复。

    集群下dubbo负载均衡配置

    在集群负载均衡是,dubbo提供了多种均衡策略,默认为random随机调用。

    负载均衡策略:Random(随机)、RoundRobin(循环)、LeastActive(最少调用)、ConsistentHash(一致性)

    服务降级

    当服务器压力剧增的情况下,根据实际业务员情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

    其中:

    • mock=force:return+null表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
    • mock=fail:return+null表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

    集群容错模式

    Failover Cluster:失败自动切换,当出现失败时,重试其它服务器。

    Failfast Cluster:快速失败,只发起一次调用,失败立即报错。

    Failback Cluster:失败自动恢复,后代记录失败请求,定时重发。

    Forking Cluster:并行调用多个服务器,只要一个成功即返回。

    Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错。

    3、Dubbo原理

    RPC原理

    一次完整的RPC调用流程(同步调用,异步另说)如下:
    1)服务消费方(client)调用以本地调用方式调用服务;
    2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
    3)client stub找到服务地址,并将消息发送到服务端;
    4)server stub收到消息后进行解码;
    5)server stub根据解码结果调用本地的服务;
    6)本地服务执行并将结果返回给server stub;
    7)server stub将返回结果打包成消息并发送至消费方;
    8)client stub接收到消息,并进行解码;
    9)服务消费方得到最终结果。
    RPC框架的目标就是要2~8这些步骤都封装起来,这些细节对用户来说是透明的,不可见的。

    Netty通信原理

    ​ Netty是一个异步事件驱动的网络应用程序框架, 用于快速开发可维护的高性能协议服务器和客户端。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。

    Selector 一般称 为选择器 ,也可以翻译为 多路复用器,Connect(连接就绪)、Accept(接受就绪)、Read(读就绪)、Write(写就绪)

    Netty基本原理

    Dubbo原理(框架设计)

    • config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
    • proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactory
    • registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
    • cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
    • monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService
    • protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
    • exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient,ExchangeServer
    • transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
    • serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool

    dubbo原理(启动解析、加载配置信息)

    dubbo原理(服务暴露)

    dubbo原理(服务引用)

    dubbo原理(服务调用)

  • 相关阅读:
    基于WebGIS的电子政务应用(基于J2EE的MVC架构)
    和菜鸟一起学c之函数中堆栈及运行内存情况
    《父亲》献给程序员的我们
    黑客高级技巧之Linux后门技术及实践
    批处理实现对网站的监测
    无敌批处理
    Adsutil.vbs在脚本入侵中的妙用
    黑客高级技巧之Linux后门技术及实践
    ms 06014漏洞检测代码
    ms 06014漏洞检测代码
  • 原文地址:https://www.cnblogs.com/xiaopanjava/p/14443485.html
Copyright © 2020-2023  润新知