10-dubbo

一 Dubbo概念

1 什么是分布式系统

在这里插入图片描述

单机架构

一个系统业务量很小的时候所有的代码都放在一个项目中就好了, 然后这个项目部署在一台服务器上,整个项目所有的服务都由这台 服务器提供。

缺点: 服务性能存在瓶颈 ;代码量庞大,系统臃肿,牵一发动全身 ;单点故障问题

集群架构

单机处理到达瓶颈的时候,你就把单机复制几份,这样就构成了一 个集群。

在这里插入图片描述

集群存在的问题: 当你的业务发展到一定程度的时候,你会发现一个问题无论怎 么增加节点,貌似整个集群性能的提升效果并不明显了。这时 候,你就需要使用分布式架构了。

什么是分布式

在这里插入图片描述

分布式架构就是将一个完整的系统,按照业务功能,拆分成一个个 独立的子系统,在分布式结构中,每个子系统就被称为“服务”。这 些子系统能够独立运行在web容器中,它们之间通过RPC方式通信。

分布式的优势:

  • 系统之间的耦合度大大降低,可以独立开发、独立部署、独立测试,系统与系统之间的边界非常明确,排错也变得相当容易,开发效率大大提升。
  • 系统之间的耦合度降低,从而系统更易于扩展。我们可以针对性地扩展某些服务。
  • 服务的复用性更高。比如,当我们将用户系统作为单独的服务后,该公司所有的产品都可以 使用该系统作为用户系统,无需重复开发。

三者区别

在这里插入图片描述

总结: 将一套系统拆分成不同子系统部署在不同服务器上(这叫分布式),然后部署多个相同的子系统在不同的服务器上(这叫集群)。

集群:多个人在一起作同样的事 。

分布式 :多个人在一起作不同的事 。

2 什么是RPC

在这里插入图片描述

什么是RPC

RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从 远程计算机程序上请求服务。

在这里插入图片描述

大白话理解就是:RPC让你用别人家的东西就像自己家的一样。

RPC两个作用:

  • 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法
  • 隐藏底层网络通信的复杂性,让我们更加专注业务逻辑

常用的RPC框架

RPC是一种技术思想而非一种规范或协议。

常见 RPC 技术和框架:

阿里的 Dubbo/Dubbox、Google gRPC、Spring Cloud。

3 简介

在这里插入图片描述

Dubbo是什么

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

Dubbo能做什么

  • 透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵 入。
  • 软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
  • 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者

在这里插入图片描述

注意: Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可。

Dubbo支持的协议

协议是两个网络实体进行通信的基础,数据在网络上从一个实体传 输到另一个实体,以字节流的形式传递到对端。在这个字节流的世界里,如果没有协议,就无法将这个一维的字节流重塑成为二维或者多维的数据结构以及领域对象。

在这里插入图片描述

Dubbo支持的协议 :

Dubbo协议 Hessian协议 HTTP协议 RMI协议 WebService协议 Memcached协议 Redis协议

推荐: 使用Dubbo协议。

4 核心组件

在这里插入图片描述

注册中心Registry

在Dubbo微服务体系中,注册中心是其核心组件之一。Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现,是各个分布式节点之间的纽带。

在这里插入图片描述

其主要作用如下:

  • 动态加入:一个服务提供者通过注册中心可以动态地把自己暴露给其他消费者,无须消费者逐个去更新配置文件。
  • 动态发现:一个消费者可以动态地感知新的配置、路由规则和新的服务提供者,无须重启服务使之生效。
  • 动态调整:注册中心支持参数的动态调整,新参数自动更新到所有相关服务节点。
  • 统一配置:避免了本地配置导致每个服务的配置不一致问题。

常见得注册发现服务:

常见的注册中心有zookeeper 、eureka、consul、etcd。

在这里插入图片描述

服务提供者Provider

服务的提供方

服务消费者Consumer

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

在这里插入图片描述

监控中心Monitor

主要负责监控统计调用次数和调用时间等

工作流程

在这里插入图片描述

二 Dubbo配置开发环境

1 Zookeeper注册中心

在这里插入图片描述

下载Zookeeper镜像

docker pull zookeeper

启动运行容器

docker run --name zk -d -p 2181:2181 zookeeper

参数: -d:守护进程运行 -p:映射端口号

进入容器

docker exec -it zk /bin/bash

参数: exec:在运行的容器中执行命令 -it:交互式

2 管理控制台

dubbo-admin待续…

三 入门案例

1 需求介绍

单体架构

在这里插入图片描述

项目架构

在这里插入图片描述

订单服务

功能如下:

创建订单 根据用户id查询订单详情

用户服务

功能如下:

创建订单 根据用户id查询订单详情

2 Windows安装zookeeper

1、下载zookeeper

官网地址

https://zookeeper.apache.org/

从国内开源网站下载镜像,例如:清华大学开源软件镜像站 | Tsinghua Open Source Mirror

https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper

2、解压

坑1:解压提示某些文件已存在

应该是因为压缩软件不支持解压tar.gz压缩包,可以在 windows 系统上 如下操作即可

1、打开Windows上的Linux环境。即Windows PowerShell
2、执行解压:tar -zxvf .\apache-zookeeper-3.6.3-bin.tar.gz

3、运行

执行bin目录下 zkServer.cmd

坑2:执行闪退
编辑zkServer.cmd文件末尾添加pause 。这样运行出错就不会退出,会提示错误信息,方便找到原因。

在这里插入图片描述

添加后得知是缺少zoo.cfg配置文件;

进入conf目录,发现存在zoo_sample.cfg ,其实我们要做的就是复制它作为一个新的文件,命名zoo.cfg,如果需要做适当修改:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true

该文件中常用的例如注册中心端口号。

修改后再次运行,出现ZooKeeper audit is disabled,修改zkServer.cmd 添加

“-Dzookeeper.audit.enable=true”

或zoo.cfg新增一行

audit.enable=true

再次打开 OK。

4、测试

打开里面的客户端 zkCli.cmd 测试:

测试一下:

[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 1] create -e /hwl
Created /hwl
[zk: localhost:2181(CONNECTED) 2] ls /
[hwl, zookeeper]
[zk: localhost:2181(CONNECTED) 3] get /hwl
null
[zk: localhost:2181(CONNECTED) 4] set /hwl hello
[zk: localhost:2181(CONNECTED) 5] ls /
[hwl, zookeeper]
[zk: localhost:2181(CONNECTED) 6] get /hwl
hello

3 代码编写

简单理解在微服务中使用Dubbo实现RPC远程接口调用,只需要满足如下几个条件:

1、导入org.apache.dubbo maven依赖。
2、配置基于dubbo的yml配置文件
3、在启动类加上@EnableDubbo注解
4、被调用接口实现类使用@DubboService注解
5、调用接口时使用@DubboReference注解

在这里插入图片描述

dubbodemo父项目

两个子项目provider,consumer都是SpringBoot项目,所以我们直接让父项目dubbodemo继承spring-boot-starter-parent,而后再让两个子项目provider,consumer继承父项目dubbodemo。

dubbodemo的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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modules>
        <module>provider</module>
        <module>consumer</module>
    </modules>

    <groupId>com.lxx</groupId>
    <artifactId>dubbodemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <maven.compiler.source>12</maven.compiler.source>
        <maven.compiler.target>12</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

provider

在这里插入图片描述

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.lxx</groupId>
        <artifactId>dubbodemo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.lxx</groupId>
    <artifactId>provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>provider</name>
    <description>provider</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

com.lxx.pojo.CommonResult:

package com.lxx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 统一返回结果集
 *
 * @param <T>
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> implements Serializable {
    // 返回结果编码
    private Integer code;
    // 返回结果描述
    private String message;
    // 数据
    private T data;
}

com.lxx.pojo.Order

package com.lxx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 订单模型
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {
    // 订单id
    private Long id;
    // 用户id
    private Long userId;
    // 订单总价格
    private Double prict;
    // 收货人手机号
    private String mobile;
    // 收货人地址
    private String address;
    // 支付类型 1:微信 2:支付宝
    private Integer pay_method;
}


com.lxx.service.IOrderService

package com.lxx.service;

import com.lxx.pojo.CommonResult;
import com.lxx.pojo.Order;

public interface IOrderService {
    //创建订单
    CommonResult createOrder(Order order);

    //根据用户id查询订单详情
    CommonResult<Order> findByUserId(Long userId);
}

com.lxx.service.impl.OrderServiceImpl

package com.lxx.service.impl;

import com.lxx.pojo.CommonResult;
import com.lxx.pojo.Order;
import com.lxx.service.IOrderService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class OrderServiceImpl implements IOrderService {
    @Override
    public CommonResult createOrder(Order order) {
        CommonResult commonResult = new CommonResult();
        // 返回结果编码
        commonResult.setCode(200);
        // 返回结果描述信息
        commonResult.setMessage("创建成功");
        return commonResult;
    }

    @Override
    public CommonResult<Order> findByUserId(Long userId) {
        //TODO 模拟数据库操作
        CommonResult commonResult = new CommonResult();
        // 返回结果编码
        commonResult.setCode(200);
        // 返回结果描述信息
        commonResult.setMessage("查询成功");
        // 返回结果集
        Order order = new Order();
        order.setId(1L);
        order.setUserId(1L);
        order.setPrict(121.1);
        order.setMobile("18588888888");
        order.setAddress("北京市海淀区中关村");
        order.setPay_method(1);
        commonResult.setData(order);
        return commonResult;

    }
}

com.lxx.ProviderApplication

package com.lxx;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {

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

}

application.properties

server.port=9090
dubbo.application.name=provider-app
dubbo.registry.address=zookeeper://localhost:2181
dubbo.protocol.port=20880

consumer

在这里插入图片描述

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.lxx</groupId>
        <artifactId>dubbodemo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.lxx</groupId>
    <artifactId>consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer</name>
    <description>consumer</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.lxx</groupId>
            <artifactId>provider</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

com.lxx.pojo.User

package com.lxx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;


/**
 * 用户模型
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {

    //用户id
    private Long id;
    // 用户名字
    private String name;
}


com.lxx.service.IUserService

package com.lxx.service;

import com.lxx.pojo.CommonResult;
import com.lxx.pojo.Order;

/**
 * 用户接口
 */
public interface IUserService {
    //根据用户id查询订单详情
    CommonResult<Order> findByUserId(Long id);
}

com.lxx.service.impl.UserServiceImpl

package com.lxx.service.impl;

import com.lxx.pojo.CommonResult;
import com.lxx.pojo.Order;
import com.lxx.service.IOrderService;
import com.lxx.service.IUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements IUserService {

    @DubboReference
    private IOrderService orderService;

    @Override
    public CommonResult<Order> findByUserId(Long id) {
        return orderService.findByUserId(id);
    }
}

com.lxx.controller.UserController

package com.lxx.controller;

import com.lxx.pojo.CommonResult;
import com.lxx.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private IUserService userService;

    @GetMapping("/findByUserId")
    public CommonResult findByUserId(Long id){
        return userService.findByUserId(id);
    }
}

com.lxx.ConsumerApplication

package com.lxx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {

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

}

application.properties

server.port=9091
dubbo.application.name=consumer-app
dubbo.registry.address=zookeeper://localhost:2181
dubbo.protocol.port=20881

四 Dubbo高级特性

1 序列化协议安全

在这里插入图片描述

为什么需要序列化

网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。

在这里插入图片描述

总结:

序列化就是将对象转换成二进制数据的过程,而反序列就是反过来将二进制数据转换为对象的过程。

序列化反序列过程

在这里插入图片描述

流程:

不妨借用个例子帮助你理解,比如发快递,我们要发一个需要自行组装的物件。发件人发之前,会把物件拆开装箱,这就好比序列化;这时候快递员来了,不能磕碰呀,那就要打包,这就好比将序列化后的数据进行编码,封装成一个固定格式的协议; 过了两天,收件人收到包裹了,就会拆箱将物件拼接好,这就 好比是协议解码和反序列化。

2 地址缓存

在这里插入图片描述

地址缓存

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

答案:

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

3 超时时间与配置覆盖关系

超时机制

在这里插入图片描述

问题:

  • 服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一 直等待下去。
  • 在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大呈堆积,势必会造成雪崩。
  • dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。

配置超时时间

服务生产者端:

@DubboService(timeout = 3000)
public class OrderServiceImpl implements IOrderService {

服务消费者端:

@DubboReference(timeout = 1000)
private IOrderService orderService;

超时设置的优先级

上面有提到dubbo支持多种场景下设置超时时间,也说过超时是针对消费端的。那么既然超时是针对消费端,为什么服务端也可以设置超时呢?

在这里插入图片描述

总结:

这其实是一种策略,其实服务端的超时配置是消费端的缺省配置,即如果服务端设置了超时,任务消费端可以不设置超时时间,简化了配置。另外针对控制的粒度,Dubbo支持了接口级 别也支持方法级别,可以根据不同的实际情况精确控制每个方法的超时时间。

4 重试机制

在这里插入图片描述

重试机制

超时问题: 如果出现网络抖动,则会出现请求失败。

如何解决

Dubbo提供重试机制来避免类似问题的发生。

@DubboService(timeout = 3000,retries = 2)

注意: Dubbo在调用服务不成功时,默认会重试2次。

5 多版本

在这里插入图片描述

Dubbo提供多版本的配置,方便我们做服务的灰度发布,或者是解决不兼容的问题。

在这里插入图片描述

灰度发布(金丝雀发布): 当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。

版本迁移步骤

  • 在低压力时间段,先升级一半提供者为新版本
  • 再将所有消费者升级为新版本
  • 然后将剩下的一半提供者升级为新版本

多版本配置

老版本服务提供者配置

@DubboService(version = "1.0.0")
public class OrderServiceImpl implements IOrderService {

新版本服务提供者配置

@DubboService(version = "2.0.0")
public class OrderServiceImpl implements IOrderService {

新版本服务消费者配置

@DubboReference(version = "2.0.0")
private IOrderService orderService;

如果不需要区分版本,可以按照以下的方式配置 :

@DubboReference(version = "*")
private IOrderService orderService;

6 负载均衡

在这里插入图片描述

Dubbo是一个分布式服务框架,能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。

在这里插入图片描述

问题: 订单服务生产者会出现单点故障。

在这里插入图片描述

如何从多个服务 Provider 组成的集群中挑选出一个进行调用, 就涉及到一个负载均衡的策略。

负载均衡策略配置

如果不指定负载均衡,默认使用随机负载均衡。我们也可以根据自己的需要,显式指定一个负载均衡。

生产者服务:

@DubboService(timeout = 3000,retries =3,loadbalance = "roundrobin")

消费者服务

@DubboReference(timeout = 2000,loadbalance = "roundrobin")

参数:

  • random:随机负载均衡
  • leastactive:最少活跃调用数,相同活跃数的随机
  • roundrobin:轮询负载均衡
  • consistenthash:一致性哈希负载均衡

7 集群容错

在这里插入图片描述

集群容错模式

Dubbo框架为服务集群容错提供了一系列好的解决方案,在此称为 dubbo服务集群容错模式。

在这里插入图片描述

容错模式

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

集群容错配置

在消费者服务配置

@DubboReference(cluster = "failover")
private IOrderService iOrderService;

8 服务降级

在这里插入图片描述

什么是服务降级

服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

两种场景:

  • 当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务 器资源,增加响应速度!
  • 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

为什么需要降级

当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心 服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。

服务降级方式

第一种

mock=force:return null

含义:表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

第二种

mock=fail:return null

含义: 表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

服务降级演示

@DubboReference(timeout = 2000,mock = "force:return null")
private IOrderService iOrderService;

9 服务限流原理

在这里插入图片描述

生活中的限流

春运,一项全人类历史上最大规模的迁移活动,抢火车票一直是每 年跨年以后的热点话题。

在这里插入图片描述

限流算法:

漏桶算法

在这里插入图片描述

原理:

漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一 定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶 算法能强行限制数据的传输速率。

令牌桶算法

在这里插入图片描述

原理:

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令 牌,而如果请求需要被处理,则需要先从桶里获取一个令牌, 当桶里没有令牌可取时,则拒绝服务。

漏桶 vs 令牌桶的区别

漏桶的天然特性决定了它不会发生突发流量,就算每秒1000个请求 到来,那么它对后台服务输出的访问速率永远恒定。而令牌桶则不 同,其特性可以“预存”一定量的令牌,因此在应对突发流量的时候 可以在短时间消耗所有令牌,其突发流量处理效率会比漏桶高,但 是导向后台系统的压力也会相应增多。

10 服务限流实现

为了防止某个消费者的QPS或是所有消费者的QPS总和突然飙升而导致的重要服务的失效,系统可以对访问流量进行控制,这种对集 群的保护措施称为服务限流。

并发控制

@DubboService(executes = 10 )

注意: 服务端并发执行(或占用线程池线程数)不能超过10个

连接控制

@DubboService(actives = 10 )

注意: 占用连接的请求的数不能超过10个。

11 结果缓存

在这里插入图片描述

结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。

Dubbo提供了三种结果缓存机制:

  • lru:基于最近最少使用原则删除多余缓存,保持最热的数据被缓存
  • threadlocal:当前线程缓存,比如一个页面渲染,用到很多portal,每个portal都要去查用户信息,通过线程缓存,可以减少这种多余访问。
  • jcache:与JSR107集成,可以桥接各种缓存实现。

配置缓存

@DubboReference(cache="lru")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值