一、分布式和微服务

1.1 什么是分布式

分布式是一种系统部署方式,即根据实际情况将项目拆分成多个不同的服务,并分散部署在不同的机器是。在分布式中,生产环境的服务器或虚拟机必定超过一台。

分布式服务顾名思义服务是分散部署在不同的机器上的,一个服务可能负责几个功能,是一种面向SOA架构的,服务之间也是通过rpc来交互或者是webservice来交互的。逻辑架构设计完后就该做物理架构设计,系统应用部署在超过一台服务器或虚拟机上,且各分开部署的部分彼此通过各种通讯协议交互信息,就可算作分布式部署。

 

1.2 什么是微服务

微服务是一种架构设计方式,即将项目根据实际情况拆分成多个微小的服务,小到一个服务只负责一个单一的功能。这个服务可以单独部署运行,服务间可以通过rpc来互相调用。

微服务架构:

在做架构设计的时候,先做逻辑架构,再做物理架构,当你拿到需求后,估算过最大用户量和并发量后,计算单个应用服务器能否满足需求,如果用户量只有几百人的小应用,单体应用就能搞定,即所有应用部署在一个应用服务器里,如果是很大用户量,且某些功能会被频繁访问,或者某些功能计算量很大,建议将应用拆解为多个子系统,各自负责各自功能,这就是微服务架构。

 

1.3 两者对比

生产环境下的微服务肯定是分布式部署的,分布式部署的应用不一定是微服务架构的,比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。

 

二、什么是 Java RPC

2.1 RPC 概念

RPC 全程为  remote procedure call,即远程过程调用。例如两台服务器A、B上分别部署了不同的应用,A服务器上的应用想调用B服务器上的应用提供的方法,就需要通过网络来表达调用的语义和传达调用的数据。

RPC 是一个泛化的概念,严格来说一切远程调用手段都属于 RPC 范畴,Java 中的 RPC 框架 有 RMI、Hessian、Dubbo 等

2.2 基本原理图

  

分布式虚拟化是什么 分布式和虚拟化的区别_spring

 

2.3 RPC 框架性能

RPC 框架的优劣主要取决于:

  • 通信效率:是否能快速的在不同服务之间建立起连接
  • 序列化与反序列化效率:序列化和反序列化机制是否快速

 

三、Dubbo 学习

3.1 Dubbo 简介

Apache Dubbo 是一款高性能的 Java RPC 框架,可以和 Spring 框架无缝集成。

Dubbo 提供了三大核心能力:

  • 面向接口的远程方法调用
  • 智能容错和负载均衡
  • 服务自动注册和发现

 

3.2 Dubbo 架构图

分布式虚拟化是什么 分布式和虚拟化的区别_xml_02

虚线为异步调用,实线为同步调用

蓝色虚线:在启动时未完成的功能

红色线条:在程序运行过程中执行的功能

节点角色说明:

节点

角色名称

Provider

暴露服务的服务提供方

Consumer

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

Registry

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

Monitor

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

Container

服务运行容器

 

 

 

 

 

 

 

3.3 服务注册中心 Zookeeper

3.3.1 什么是注册中心

消费者通过注册中心来调用服务提供方,消费者和服务提供者均要在注册中心进行注册,注册中心能够监控到服务提供方是否在线,以及实现负载均衡。

 

3.3.2 Zookeeper 简介

Zookeeper 是 Apache Hadoop 的子项目,是一个树形的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生成环境。

 

3.3.3 Zookeeper 结构说明

分布式虚拟化是什么 分布式和虚拟化的区别_spring_03

流程说明:

  • 服务提供者(Provicer)启动时,向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
  • 服务消费者(Consumer)启动时,订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
  • 监控中心(Monitor)启动时,订阅 /dubbo/com.foo.BarService 目录下所有的提供者和消费者 URL 地址

 

3.3.4 安装 Zookeeper

百度网盘:

链接:https://pan.baidu.com/s/1CL1CYr2-Eb4ZOX-fe4WFRg   提取码:13y3

官网下载地址:

http://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/

# 解压压缩包
tar -zxvf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 zookeeper


# 创建data目录
cd zookeeper
mkdir data

# 修改配置文件
cd conf
mv zoo_sample.cfg zoo.cfg

# 修改 zoo.cfg 文件
dataDir=/usr/local/lincya/zookeeper/data

 

3.3.4 Zookeeper 使用

# 启动 Zookeeper
./zkServer.sh start

# 停止服务命令
./zkServer.sh stop

# 查看服务状态
./zkServer.sh status

3.3.5 Zookeeper 客户端使用

# 进入客户端
sh zkCli.sh

# 查看节点
ls /

# 获取某个节点数据
get /dubbo

# 创建节点
create dubbo 123456

 

3.3.6 Zookeeper 可视化界面

GitHub 项目地址:

https://github.com/apache/dubbo-admin

使用教程:

分布式虚拟化是什么 分布式和虚拟化的区别_spring_04

访问结果:

分布式虚拟化是什么 分布式和虚拟化的区别_dubbo_05

 

四、Dubbo 搭建基于 xml 的实例

4.1 提供方搭建

4.1.1 引入 maven 依赖

<dependencies>
        <dependency>
            <groupId>com.tom</groupId>
            <artifactId>dubbo-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!--    引入dubbo    -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.2</version>
        </dependency>
        <!--    引入操作zookeeper的客户端    -->
        <!--     dubbo 2.6 以前使用 zkclient   -->
        <!--        <dependency>-->
        <!--            <groupId>org.101tec</groupId>-->
        <!--            <artifactId>zkclient</artifactId>-->
        <!--            <version>0.10</version>-->
        <!--        </dependency>-->
        <!--   dubbo 2.6 及以后使用 curator     -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
    </dependencies>

4.1.2 增加注解

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://dubbo.apache.org/schema/dubbo"
       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="user-service-provider"/>

    <!--  指定注册中心地址  -->
    <dubbo:registry address="zookeeper://www.greattom.xyz:2181"/>

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

    <!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
    <dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl"/>

    <!-- 和本地bean一样实现服务 -->
    <bean id="userServiceImpl" class="com.tom.service.impl.UserServiceImpl"/>

    <!-- 设置请求超时时间 -->
    <dubbo:provider timeout="5000"></dubbo:provider>

    <!--  自动发现监控中心  -->
    <dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>

4.1.3 修改启动类

使用 ClassPathXmlApplicationContext 加载配置文件

public class ProviderApplication {

    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
        ioc.start();

        System.in.read();
    }
}

4.1.4 编写服务代码

import com.tom.bean.UserAddress;
import com.tom.service.UserService;

import java.util.Arrays;
import java.util.List;

public class UserServiceImpl implements UserService {
    public List<UserAddress> getUserAddressList(String userId) {
        UserAddress address1 = new UserAddress(1, "北京市", "1", "小王", "18030145000", "1");
        UserAddress address2 = new UserAddress(2, "杭州市", "2", "小北", "18030145999", "2");
        return Arrays.asList(address1, address2);
    }
}

 

4.2 服务方搭建

4.2.1 引入 maven 依赖

与提供方相同

4.2.2 增加注解

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

    <context:component-scan base-package="com.tom.service.impl"></context:component-scan>

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

    <!-- 使用注册中心 -->
    <dubbo:registry address="zookeeper://www.greattom.xyz:2181"/>

    <!-- 生成远程服务代理 -->
    <dubbo:reference interface="com.tom.service.UserService" id="userService"/>

    <!--  自动发现监控中心  -->
    <dubbo:monitor protocol="registry"></dubbo:monitor>
    <!--    <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>-->
</beans>

4.2.3 修改启动类

public class ConsumerApplication {

    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
        OrderService orderService = applicationContext.getBean(OrderService.class);
        orderService.initOrder("1");

        System.out.println("调用完成...");
        System.in.read();
    }
}

4.2.4 编写服务代码

import com.tom.bean.UserAddress;
import com.tom.service.OrderService;
import com.tom.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    UserService userService;

    public void initOrder(String userId) {
        System.out.println("用户ID: " + userId);
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        for (UserAddress item : addressList) {
            System.out.println(item.getUserAddress());
        }
    }
}

 

五、Dubbo 搭建基于注解的实例

Github项目地址:https://github.com/IDLC1/dubboDemos

项目相关依赖版本:

  • jdk: 1.8
  • dubbo: 2.7.7
  • zookeeper: 3.6.1
  • curator: 5.0.0

 

5.1 提供者搭建

5.1.1 引入 maven 依赖

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>com.tom</groupId>
        <artifactId>boot-dubbo-common-interface</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!--    引入dubbo    -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>${dubbo.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>${zookeeper.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
        <version>${curator.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>${curator.version}</version>
    </dependency>

    <!-- Dubbo Spring Boot Starter -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>${dubbo.version}</version>
    </dependency>
</dependencies>

5.1.2 修改配置文件

dubbo.application.name=dubbo-order-provicder
# 指定 zookeeper 注册,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
# 指定要扫描的包
dubbo.scan.base-packages=com.tom.bootdubboorderprovider.service
# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry

5.1.3 修改启动类

@SpringBootApplication
@EnableDubbo
public class BootDubboOrderProviderApplication {

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

5.1.4 实现类中使用

@DubboService
public class UserServiceImpl implements UserService {
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        UserAddress address1 = new UserAddress(1, "北京市", "1", "小王", "18030145000", "1");
        UserAddress address2 = new UserAddress(2, "杭州市", "2", "小北", "18030145999", "2");
        return Arrays.asList(address1, address2);
    }
}

5.2 消费者搭建

5.2.1 引入 maven 依赖

依赖于提供者相同

5.2.2 修改配置文件

server.port=8084
dubbo.application.name=dubbo-user-consumer
# 指定 zookeeper 注册,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator
# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry

5.2.3 修改启动类

@SpringBootApplication
@EnableDubbo
public class BootDubboUserConsumerApplication {

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

}

5.2.4 实现类中使用

使用 @Reference 来调用 dubbo 上注册的提供者

@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference
    UserService userService;

    @Override
    public List<UserAddress> initOrder(String userId) {
        System.out.println("用户ID: " + userId);
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        for (UserAddress item : addressList) {
            System.out.println(item.getUserAddress());
        }
        return addressList;
    }

    @Override
    public String orderTest(String id) {
        return "order test!";
    }
}

 

5.3 Dubbo 配置解析

# 指定 dubbo 在 zookeeper 上注册的服务名
dubbo.application.name=dubbo-user-consumer

# 指定 zookeeper 注册中心,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator

# 设置 dubbo 在启动时不检查 zookeeper 上是否已经注册了依赖
# 用于不同服务间的互相调用
dubbo.consumer.check=false

# 协议方式和端口,用于其他服务调用。
# 不同的服务端口不能相同
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881

# 要暴露的包路径
dubbo.scan.base-packages=com.tom.bootdubbouserconsumer

# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry

 

六、Dubbo 详细配置

官网文档:http://dubbo.apache.org/zh-cn/docs/user/demos/preflight-check.html

6.1 配置覆盖关系

6.1.1 配置优先级

  • 精确优先:方法级优先,接口次之,全局配置再次之
  • 消费方优先:若级别一致,则消费方优先,提供方次之

  

分布式虚拟化是什么 分布式和虚拟化的区别_xml_06

6.1.2 在Provider上尽量多配置Consumer属性

  • 服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
  • 在 provider 配置后,consumer 不配置则会使用 provider 的配置值,即 provider 配置可以作为 consumer 的缺省值。否则,consumer 会使用 consumer 端的全局设置,这对于 provider 不可控的,并且往往是不合理的

 

6.2 启动时检查

分布式虚拟化是什么 分布式和虚拟化的区别_xml_07

分布式虚拟化是什么 分布式和虚拟化的区别_spring_08

 

6.3 超时时间配置

根据实际情况,修改 dubbo 访问其他提供者的接口超时时间。Dubbo 默认超时时间为 1 秒,在实际情况中 1 秒对于服务的请求速度要求很高,故应该根据实际情况进行统一或针对性修改

统一修改和针对性修改可以同时存在,且优先级:针对性修改 > 统一修改

6.3.1 统一修改

在 springboot 配置文件中增加:

dubbo.provider.timeout=3000

6.3.2 针对性修改

@DubboService(timeout = 5000)
@Service
public class OrderServiceImpl implements OrderService {

    @DubboReference(timeout = 3000)
    UserService userService;

    @Override
    public List<UserAddress> initOrder(String userId) throws InterruptedException {
        System.out.println("用户ID: " + userId);
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        for (UserAddress item : addressList) {
            System.out.println(item.getUserAddress());
        }
        return addressList;
    }
}

6.3.3 xml 修改

<dubbo:provider timeout="5000"></dubbo:provider>

 

6.4 重试次数配置

可以根据实际情况设置请求的重试次数,默认为 3 次。为实际配置值 N + 1

方法分类:

  • 幂等方法:无论多少次,只要请求数据不变,则响应结果最终都是同一个效果,如查询、删除、修改
  • 非幂等方法:每次运行都会产生新的效果,如数据库新增

设置区别:

  • 幂等方法:设置重试次数
  • 非幂等方法:不能设置重试次数,设置为0

6.4.2 xml 配置

统一配置:

<dubbo:provider timeout="2000" retries="5"></dubbo:provider>

针对方法配置:

<!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl">
    <dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>

 

6.5 灰度发布

6.5.1 概念

概念:

dubbo多版本控制: http://dubbo.apache.org/zh-cn/docs/user/demos/multi-versions.html

6.5.2 适应场景

  • 当接口存在不兼容的升级时,要让一部分用户用新版本,又要支持老版本接口的使用,可以使用dubbo多版本控制
  • 当服务要更新时,无法确保线上服务更新正常,需要先进行测试,之后逐步将用户流量指引向新版本

6.5.3 示例代码

提供方:

<!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl01" version="1.0.0">
    <dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl02" version="2.0.0">
    <dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>

<!-- 和本地bean一样实现服务 -->
<bean id="userServiceImpl01" class="com.tom.service.impl.UserServiceImpl"/>
<bean id="userServiceImpl02" class="com.tom.service.impl.UserServiceImpl2"/>

调用方:

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

 

6.6 本地存根

6.6.1 概念

远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub [1],然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。

 

七、Springboot 整合 Dubbo  的三种方式

7.1 描述

SpringBoot 整合 Dubbo 的方式有:

  • 注解配置方式(常用):在 springboot 配置文件中配置相关内容,使用 @Service 和 @Reference 注解实现功能
  • xml配置方式(常用):使用 xml 配置文件,使用 @ImportResource 导入生效
  • 注解Api方式(知道):创建dubbo配置文件,依次注册 dubbo 组件到项目中

7.2 三种方式对比

 

注解配置方式

xml配置方式

注解API方式

配置方式

导入 dubbo-starter,在配置文件中进行配置,使用@Service暴露服务,使用@Reference引用服务

首先导入dubbo-starter,然后使用 @ImportResource 加载 xml 配置文件

创建统一的dubbo配置文件,将dubbo的每一个组件手动注入到springboot项目中

优点

配置快速方便

支持精确配置

支持精确配置

缺点

不支持精确配置,如针对 method 进行配置

 

配置繁琐,不常用

 

八、常见的高可用场景

高可用即通过设计,减少系统不能提供服务的时间

 Dubbo 与 Zookeeper 的高可用有:

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

 

8.1 Zookeeper 宕机与 dubbo 直连

8.1.1 本地缓存

当消费者调用过提供者的方法后,消费者会在本地存储提供者的地址以及方法信息,故当 Zookeeper 宕机后消费者依旧可以消费提供者提供的服务

 

8.1.2 dubbo 直连

需要保证 provider 服务正常运行中

修改 consumer 配置,关闭 zookeeper 连接配置

分布式虚拟化是什么 分布式和虚拟化的区别_dubbo_09

进入管理界面查看提供者的地址信息

分布式虚拟化是什么 分布式和虚拟化的区别_分布式虚拟化是什么_10

修改 consumer 的引用

分布式虚拟化是什么 分布式和虚拟化的区别_xml_11

可以正常调用了

分布式虚拟化是什么 分布式和虚拟化的区别_spring_12

 

8.2 Dubbo 负载均衡

8.2.1 四种负载均衡策略

Dubbo内置了4种负载均衡策略:

  • RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
  • RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。
  • LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
  • ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。

 

8.2.2 随机负载均衡(或基于权重)

随机负载均衡即随机选择一个节点进行请求,接下来主要介绍基于权重的随机负载均衡

例如 orderService 是一个消费者,userService 是提供者,根据权重的不同,大致会有1/6的请求来带A服务,3/6的请求会来到B服务,2/6的请求会来到C服务,并不是严格遵守比例,不能保证顺序调用,只能够保证大概一致

   

分布式虚拟化是什么 分布式和虚拟化的区别_zookeeper_13

 

8.2.3 轮询负载均衡(或基于权重)

轮询负载均衡即在所有节点中间循环发送请求,接下来主要介绍基于权重的轮询负载均衡

例如 orderService 是一个消费者,userService 是提供者,根据权重的不同,在一次完整的轮询((100+300+200)/100 = 6次)中,A服务一定只会被轮询到一次,B服务被轮询到3次,C服务轮询到2次

分布式虚拟化是什么 分布式和虚拟化的区别_分布式虚拟化是什么_14

8.2.4 最少活跃数负载均衡

最少活跃数通俗来说就是将请求指向处理速度更快的提供者节点,让请求速度更慢的节点收到更少的请求

例如 orderService 是一个消费者,userService 是提供者,根据响应时间的不同,请求会更多地指向A节点,B节点次之,C节点最少

  

分布式虚拟化是什么 分布式和虚拟化的区别_xml_15

8.2.5 一致性Hash负载均衡

一致性Hash是指将调用方法相同、参数相同的请求发送到同一个提供者节点中

例如 orderService 是一个消费者,userService 是提供者,则无论请求数量多少,id为1的请求永远发送到A服务,id为2的请求永远发送到B服务,id为3的请求永远发送到C服务。

分布式虚拟化是什么 分布式和虚拟化的区别_xml_16

 

8.3 负载均衡配置

8.3.1 设置负载均衡方法

分布式虚拟化是什么 分布式和虚拟化的区别_xml_17

8.3.2 设置权重

 

8.4 服务降级

8.4.1 概念

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

我们可以通过服务降级功能临时屏蔽某个出错的非关键业务,并定义降级后的返回策略

 

8.5 集群容错

8.5.1 概念和模式

在集群调用失败时,Dubbo 提供了多种容错方案,默认为 failover 重试

Failfast Cluster(默认)

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

Failsafe Cluster

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

Failback Cluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

Forking Cluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。

Broadcast Cluster

广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。

 

8.5.2 修改方式

<dubbo:reference cluster="failsafe" />

 

8.5 集群容错结合 Hyxtrix

8.5.1 概念

Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix 具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能

8.5.2 使用

消费者和提供者均引入依赖:

使用 EditStarters 插件,在 setting -> plugin 中搜索并安装

分布式虚拟化是什么 分布式和虚拟化的区别_xml_18

按住 Alt + Insert

分布式虚拟化是什么 分布式和虚拟化的区别_xml_19

使用默认地址

分布式虚拟化是什么 分布式和虚拟化的区别_分布式虚拟化是什么_20

分布式虚拟化是什么 分布式和虚拟化的区别_dubbo_21

自动添加

分布式虚拟化是什么 分布式和虚拟化的区别_xml_22

修改消费者和提供者的启动类:

分布式虚拟化是什么 分布式和虚拟化的区别_分布式虚拟化是什么_23

提供者方法修改:

分布式虚拟化是什么 分布式和虚拟化的区别_分布式虚拟化是什么_24

消费者方法修改:

分布式虚拟化是什么 分布式和虚拟化的区别_zookeeper_25