Dubbo

分布式系统中的相关概念

传统项目:OA系统、HR系统(用户数量少,单体项目)
互联网项目:用户多、流量大,高并发、海量数据、易受攻击、功能繁琐、变更快

大型互联网项目架构目标

衡量网站的性能指标:
响应时间:执行一个请求从开始到最后收到响应数据所花费的总体时间
并发数:指系统同时能处理的请求数量

并发连接数:指的是客户端向服务器发起请求,并建立了TCP连接,每秒服务器连接接的总的TCP数量
请求数:也成为QPS(Query Per Second)指每秒多少请求
并发用户数:单位时间内有多少用户

吞吐量:指单位时间内系统处理的请求数量

QPS:每秒查询数
TPS:每秒事务数
一个事务是指一个客户机向服务器做出反应的过程,客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数
一个页面的一次访问,只会形成一个TPS,但一次页面请求,可能产生多次对服务器的请求,就会有多个QPS
QPS>= 并发连接数>= TPS

高性能:提供快读的访问体验
高可用:网站服务一直可以正常访问
可伸缩:通过硬件增加/减少,提高/降低处理能力
高可扩展:系统间耦合地,方便的通过新增/移除方式,增加/减少新的功能/模块
安全性:提供网站安全访问和数据加密,安全存储等策略
敏捷性:随需应变,快速响应

集群和分布式

集群相当于很多人一起干相同的事,一个业务模块部署在多台服务器上
分布式相当于很多人干不同的事,一个大的业务系统,拆分为小的业务模块,部署在不同的机器上

架构演进

在这里插入图片描述

单体架构模型

在这里插入图片描述

垂直架构

在这里插入图片描述

分布式架构

在这里插入图片描述

SOA架构

在这里插入图片描述

微服务架构

在这里插入图片描述

Dubbo概述

Dubbo是阿里巴巴公司开源的一个高性能、轻量级的Java RPC框架。
致力于提供高性能和透明化的 RPC远程服务调用方案,以及SOA 服务治理方案。

http://dubbo.apache.org

Dubbo架构图

在这里插入图片描述

Dubbo官方推荐使用Zookeeper作为注册中心

Zookeeper安装步骤

Dubbo快速入门

1、创建服务提供者Provider模块
2、创建服务消费者Consumer模块
3、在服务提供者模块编写UserServicelmpl提供服务
4、在服务消费者中的UserController远程调用UserServicelmpl提供的服务
5、分别启动两个服务,测试

使用Controller调用Service,在Spring和Spring MVC中,将UserController通过Spring MVC提供,在Controller中注入service的实现类,然后就可以调用。

这种方式进行拆分的具体是将service和web放在不同的模块中,service使用jar的打包方式,web使用war的打包方式,此时web可充当消费者,service充当服务者,在web的pom文件中引入service的依赖即可。

使用dubbo的方式进行服务间的调用

在这里插入图片描述

服务提供方

1、在service模块中将pom文件的打包方式改为war,引入Dubbo和Zookeeper的依赖,并开启一个端口为9000的tomcat服务器插件。

<?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>org.zg</groupId>
    <artifactId>dubbo-server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <spring.version>5.1.9.RELEASE</spring.version>
        <dubbo.version>2.7.4.1</dubbo.version>
        <zookeeper.version>4.0.0</zookeeper.version>

    </properties>

    <dependencies>
        <!-- servlet3.0规范的坐标 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--spring的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--springmvc的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>



        <!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!--ZooKeeper客户端实现 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>${zookeeper.version}</version>
        </dependency>
        <!--ZooKeeper客户端实现 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>${zookeeper.version}</version>
        </dependency>


        <!--&lt;!&ndash;公共接口模块&ndash;&gt;
        <dependency>
            <groupId>com.zg</groupId>
            <artifactId>dubbo-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
-->
    </dependencies>

    <build>
        <plugins>
            <!--tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>9000</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、将service提供的服务通过dubbo对外发布

package com.zg.service.impl;

import com.zg.service.UserService;
import org.apache.dubbo.config.annotation.Service;

//@Service//用在单体架构中,将该类的对象创建出来,放到Spring的IOC容器中,bean定义
@Service//将这个类提供的方法(服务)对外发布,将访问的地址ip,端口,路径注册到注册中心中
public class UserServiceImpl implements UserService{



    public String sayHello() {
        return "hello dubbo";
    }
}

3、在核心配置类applicationContext.xml文件中配置dubbo

<?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"
	   xmlns:context="http://www.springframework.org/schema/context"
	   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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!--<context:component-scan base-package="com.zg.service"/>-->

	<!--dubbo相关配置-->
	<!--1、配置项目的名称,必须唯一-->
	<dubbo:application name="dubbo-server"/>
	<!--2、配置注册中心的地址-->
	<dubbo:registry address="zookeeper://192.168.52.128:2181"/>
	<!--3、定义dubbo的包扫描,向spring的component-scan一样-->
	<dubbo:annotation package="com.zg.service.impl"/>
</beans>

4、在web.xml文件中扫描dubbo的核心配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">


    <!-- spring 用来扫描dubbo的配置-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/applicationContext*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>




</web-app>
服务消费方

1、当使用分布式时就不能将service的依赖进行传递了,因此pom文件就不用引入service的依赖

<?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>org.zg</groupId>
    <artifactId>dubbo-web</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <spring.version>5.1.9.RELEASE</spring.version>
        <dubbo.version>2.7.4.1</dubbo.version>
        <zookeeper.version>4.0.0</zookeeper.version>

    </properties>

    <dependencies>
        <!-- servlet3.0规范的坐标 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--spring的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--springmvc的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>



        <!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!--ZooKeeper客户端实现 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>${zookeeper.version}</version>
        </dependency>
        <!--ZooKeeper客户端实现 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>${zookeeper.version}</version>
        </dependency>


<!--        &lt;!&ndash;公共接口模块&ndash;&gt;
        <dependency>
            <groupId>org.zg</groupId>
            <artifactId>dubbo-server</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>-->


    <build>
        <plugins>
            <!--tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>8000</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、在controller中就不能使用本地注入,引入@Reference注解(1、从注册中心获取userService的访问url 2、进行远程调用RPC 3、将结果封装为一个代理对象,给变量赋值)

package com.zg.controller;

import com.zg.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    //@Autowired//本地注入
    @Reference
    //1、从注册中心获取userService的访问url
    //2、进行远程调用RPC
    //3、将结果封装为一个代理对象,给变量赋值
    private UserService userService;

    @RequestMapping("/sayHello")
    public String sayHello(){
        return userService.sayHello();
    }
}

3、在核心配置文件中配置dubbo的信息这里的配置项目名称必须唯一,注册中心地址需要和服务者相同,定义包扫描

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <mvc:annotation-driven/>
    <context:component-scan base-package="com.zg.controller"/>
    <!--这里的包扫描仍需留下来扫描Springmvc中的注解-->

    <!--dubbo相关配置-->
    <!--1、配置项目的名称,必须唯一-->
    <dubbo:application name="dubbo-web">
        <!--这里的配置是因为两个项目在同一台机器部署,发生了qos的端口发生了冲突-->
            <dubbo:parameter key="qos.port" value="33333"/>
    </dubbo:application>
    <!--2、配置注册中心的地址-->
    <dubbo:registry address="zookeeper://192.168.52.128:2181"/>
    <!--3、定义dubbo的包扫描,向spring的component-scan一样-->
    <dubbo:annotation package="com.zg.controller"/>
</beans>

4、在web.xml文件中进行配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">




    <!-- Springmvc -->
    <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:spring/springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>


</web-app>

5、但是在消费者的Controller中没有服务者的service注入了。就需要抽取一个公共的模块来存放
在这里插入图片描述
6、将消费者和服务者的service的接口抽取成单独模块,并在消费者和服务者的pom文件中引入接口模块的依赖,就是只将接口进行抽取其它不变如果注册中心在Linux上部署,一定一定一定要关闭防火墙systemctl stop firewalld.service

dubbo-admin

dubbo-admin管理平台,是图形化的服务管理页面
从注册中心中获取到所有的提供者/消费者进行配置管理
路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能
dubbo-admin是一个前后端分离的项目。前端使用vue.,后端使用springboot
安装dubbo-admin其实就是部署该项目

dubbo-admin安装
安装nodehttps://nodejs.org/en/

dubbo-admin 是一个前后端分离的项目。前端使用vue,后端使用springboot,安装 dubbo-admin 其实就是部署该项目。我们将dubbo-admin安装到开发环境上。要保证开发环境有jdk,maven,nodejs

因为前端工程是用vue开发的,所以需要安装node.js,node.js中自带了npm,后面我们会通过npm启动
在这里插入图片描述

下载dubbo-adminhttps://github.com/apache/dubbo-admin

在这里插入图片描述

修改配置文件application.properties

在这里插入图片描述
将配置文件中的注册中心地址改为自己部署注册中心的地址
在这里插入图片描述

回到刚才解压的项目目录下执行mvn clean package打包命令

在这里插入图片描述

启动后端

切换目录dubbo-Admin-develop\dubbo-admin-distribution\target>
执行java -jar .\dubbo-admin-0.1.jar命令启动项目
在这里插入图片描述

启动前端E:\soft\dubbo-admin-develop\dubbo-admin-ui
npm run dev

在这里插入图片描述

访问http://localhost:8081/

在这里插入图片描述

dubbo-admin简单使用

首次使用需要输入默认的用户名密码,这里都为root
在这里插入图片描述

A:输入的查询条件com.itheima.service.UserService

B:搜索类型,主要分为【按服务名】【按IP地址】【按应用】三种类型查询

C:搜索结果

修改端口

当需要部署很多的服务,端口就需要改了<dubbo:protocol port="20880"/>
在这里插入图片描述

序列化

在这里插入图片描述

dubbo 内部已经将序列化和反序列化的过程内部封装了我们只需要在定义pojo类时实现serializable接口即可一般会定义一个公共的pojo模块,让生产者和消费者都依赖该模块。

package com.zg.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private int id;
    private String username;
    private String password;

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

地址缓存

注册中心挂了,服务是否可以正常访问

可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。
当服务提供者地址发生变化时,注册中心会通知服务消费者。

超时与重试

在这里插入图片描述

超时

服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。
使用timeout属性配置超时时间,默认值1000,单位毫秒。
可以配置在服务的生产者中的@Service注解中,也可以配置在消费者的@Reference注解中,如果消费者和生产者都配置的话,其会以消费者为准。但一般都会将其配置在生产者一方。

@Service(timeout = 3000,retries = 0)//当前服务超时时间为3秒,重试0次
@Reference(timeout = 30000,retries = 2)
重试

设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。如果出现网络抖动,则这一次请求就会失败。
Dubbo提供重试机制来避免类似问题的发生。通过retries属性来设置重试次数。默认为2次。

多版本

在这里插入图片描述

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。
dubbo中使用version属性来设置和调用同一个接口的不同版本灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。
dubbo中使用version属性来设置和调用同一个接口的不同版本@Service(version = "1.0")

生产者
@Service(version = "1.0")//UserService1
@Service(version = "2.0")//UserService2
消费者
@Reference(version = "1.0")//消费者调用哪个版本就写哪个版本

负载均衡

在这里插入图片描述

负载均衡的策略
@Reference(loadbalance = "Random")//按权重随机,默认值。按权重设置随机概率。
@Reference(loadbalance = "RoundRobin")//按权重轮询
@Reference(loadbalance = "LeastActive")//最少活跃调用数,相同活跃数的随机
@Reference(loadbalance = "consistentHash")//—致性Hash,相同参数的请求总是发到同一提供者。

Random :按权重随机,默认值。按权重设置随机概率。
RoundRobin:按权重轮询。
LeastActive:最少活跃调用数,相同活跃数的随机
consistentHash:—致性Hash,相同参数的请求总是发到同一提供者。

集群容错

@Reference(cluster = "Failover Cluster")

Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。一般用于读操作。
Eailfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于写操作。
Failsafe Cluster :失败安全,出现异常时,直接忽略。返回—个空结果。
Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster:并行调用多个服务器,只要一个成功即返回。
Broadcast Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错。

服务降级

将不太重要的服务进行关闭,释放资源,保证核心业务服务能正常运行
在这里插入图片描述

@Reference(moke = "force:return null")

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zgDaren

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值