Dubbo+Zookeeper使用

news2024/11/18 9:29:03

说明:Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。

本文介绍Dubbo的简单使用及一些Dubbo功能特性,注册中心使用的是ZooKeeper,可在官网下载。

(另外,在阿里巴巴发出的《微服务治理技术白皮书》中各种注册中心的区别如下:)

在这里插入图片描述

环境搭建

首先,搭建一个ZooKeeper + Dubbo的项目

(1)下载ZooKeeper

在上面提供的官网上下载ZooKeeper,解压到一个没有中文的路径下;

在这里插入图片描述
因为默认提供的配置文件是一个模板,解压后需要手动设置一下,将zookeeper默认的配置文件(zoo_sample.cfg)复制一份,并将文件名改为"zoo.cfg"

在这里插入图片描述

另外,修改zoo.cfg配置文件中的这行配置,默认的是Linux文件路径,修改为当前目录的上级目录(…/data);

在这里插入图片描述

启动,选择安装目录下bin文件夹下的zkServer.cmd文件,可双击启动或者在该目录下打开CMD窗口执行

在这里插入图片描述

没有报错,运行结果如下,表示启动成功

在这里插入图片描述

在这里插入图片描述

如果启动失败,提示此时不应有 jdk,参考:http://t.csdn.cn/52O2K

(2)创建项目

创建一个Zookper+Dubbo的项目,有两个微服务,一个用户服务(UserService),一个订单服务(OrderService),

  • 订单服务(消费者,Consumer):没有Service层,直接使用用户服务查询用户信息、用户名;

  • 用户服务(提供者,Provider):没有Controller层,提供查询用户信息、用户名的接口;

订单服务(OrderService)

Controlle层,两个接口,一个用于查找用户名,一个用于查找用户。实现暂时空着,待会儿使用Dubbo调用用户服务对应的接口

@RestController
@RequestMapping("order")
public class OrderController {

    @GetMapping("/name")
    public String getUserName(Integer id){
        return userService.getUserName(id);
    }

    @GetMapping("/user")
    public User getUser(Integer id){
        return userService.getUser(id);
    }
}

用户服务(UserService)

UserService实现类,实现两个接口,分别是查询用户名,返回固定值;查询用户,返回固定用户对象;

@Service
public class UserServiceImpl implements UserService {


    @Override
    public String getUserName(Integer id) {
        return "getUserName";
    }

    @Override
    public User getUser(Integer id) {
        User user = new User(30, "张三", "12456");
        return user;
    }
}

(3)配置

使用Dubbo前,需先导入依赖,我这里直接在父模块中添加,如下:

<?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>com.hzy</groupId>
    <artifactId>user-provider</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>8</java.version>
        <spring-boot.version>2.2.1.RELEASE</spring-boot.version>
        <dubbo.version>2.7.5</dubbo.version>
        <curator.version>2.12.0</curator.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    
    <dependencies>
        <!--MVC框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--dubbo-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </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>
    </dependencies>
</project>

设置各个服务的配置,两方面,一方面是zookeeper,一方面是dubbo的,如下:

(OrderService)

server:
  port: 8081
spring:
  application:
    name: dubbo-consumer
dubbo:
  registry:
    address: zookeeper://localhost:2181  # 连接到注册中心
  protocol:
    name: dubbo # 指定的协议
    port: 28081  # 指定的端口
  scan:
    basePackages: com.hzy.controller # 接口列表和接口中的方法列表

(UserService)

server:
  port: 8082
spring:
  application:
    name: dubbo-provider
dubbo:
  registry:
    address: zookeeper://localhost:2181  # 连接到注册中心
  protocol:
    name: dubbo # 指定的协议
    port: 28082  # 指定的端口
  scan:
    basePackages: com.hzy.controller # 接口列表和接口中的方法列表

(4)启动

依次 启动用户服务、订单服务,没有报错说明项目注册到zookeeper没有问题;

在这里插入图片描述

打开zookeeper客户端,输入 ls /可查看到dubbo项,再输入ls /dubbo,可查看到注册的服务;

在这里插入图片描述

(5)使用

使用Dubbo非常简单,只需如下操作:

  • 第一步:修改提供者Service注解,改为Dubbo依赖提供的;

在这里插入图片描述

  • 第二步:将提供者的UserService接口复制一份到消费者这边来,注意结构要平行相同

在这里插入图片描述

  • 第三步:在消费者Controller层注入(引用)UserService接口;

  • 第四步:直接调用UserService中的接口;

在这里插入图片描述

(6)测试

重启两个服务(注意先启动提供者),使用fastRequest测试;

(获取用户名)

在这里插入图片描述

(获取用户信息)

在这里插入图片描述

可以看到两个接口都可以正常返回,说明zookeeper+dubbo的结合已完成;

Dubbo特性

以下介绍Dubbo中的一些特性,更多特性用法可在官网中查看;

在这里插入图片描述

(1)启动检查

上面一直提到,需要先启动提供者,再启动消费者,这是因为消费者服务依赖于提供者,在启动时Dubbo会进行检查,发现提供者找不到会报错,程序启动失败。

在这里插入图片描述

可在消费者这边添加如下配置,取消启动检查

# 取消消费者检查
dubbo:
  consumer:
    check: false

再次启动就没有问题了

在这里插入图片描述

(2)地址缓存

地址缓存是指,消费者与提供者联系建立起来了,服务消费者会把提供者的接口地址缓存一份,此时注册中心宕机,该请求仍可以正常访问;

发送请求,没得问题;

在这里插入图片描述

关闭注册中心zookeeper;

在这里插入图片描述

两个服务一直在打印未知错误;

在这里插入图片描述

此时,访问刚刚的那个请求,仍然可以成功;

在这里插入图片描述

换个重启服务后没发过的请求,也可以访问;

在这里插入图片描述

(3)对象传输

使用Dubbo可以传输自定义对象,但需要注意对象需要实现序列号接口,不然会报错;

在这里插入图片描述

根据经验,凡是涉及到传输对象,都需要实现序列化接口,并且最好添加全参构造、无参构造,因为有些工具,底层可能是通过对象的全参构造来帮助我们实例化对象的。

(4)连接超时

Dubbo默认设置的连接超时是1秒,即当消费者发送的请求,1秒未得到返回即为超时,这个超时是可以设置的。

在提供者这边方法内设置2秒睡眠;

在这里插入图片描述

消费者发送请求,返回超时错误;

在这里插入图片描述

连接超时可以在消费者、提供者设置,并且可以在接口、方法上设置,优先级是消费者大于提供者,方法大于接口,如下我在消费者(@Reference)、提供者(@Service)双方设置超时时长;

(消费者,设置1500ms)

在这里插入图片描述

(提供者,设置3000ms)

在这里插入图片描述

(重启服务,发送请求,依旧报错,说明提供者设置的超时没有起作用,超时是以消费者的1500ms为准)

在这里插入图片描述

(互调设置,消费者设置3000ms,提供者1500ms,重启服务可以正常访问)

在这里插入图片描述

(5)重试次数

重试次数,在之前连接超时错误的信息,可以看到一个“Tried 3 times”,表示尝试了3次,默认重试2次;

在这里插入图片描述

同样,这个也可以在消费者、提供者双方设置

(提供者)

// 设置重试10次
@Service(timeout = 3000, retries = 10)

(消费者)

// 设置重试5次
@Reference(timeout = 1500, retries = 5)
private UserService userService;

同样,优先级是消费者大于提供者;

在这里插入图片描述

注意

需要注意哦,不是所有操作都可以设置重试次数的,应该需要考虑当前请求所对应的操作是否为幂等性操作,即执行一次或多次结果都相同,不然会造成数据混乱。以数据库的增删改查操作为例:

  • 增:每增加一条数据,数据库表都是变化的,所以为非幂等性;

  • 删:与增同理,是非幂等性;

  • 改:视情况而定,看SQL语句是怎么写的,如果是"number + 1"这样的,是非幂等性;如果是“set name = #{name} where id = #{id}”这样的,就是幂等性的;

  • 查:多次查询(没有其他操作参与)数据库表都是一样的,所以是幂等性操作;

(6)多版本

多版本是指,如果存在多个提供者、消费者时,可以指定版本信息,让提供者指服务指定的消费者,消费者指消费指定的服务者;

(消费者,不指定版本信息)

@Reference(timeout = 3000, retries = 5)
private UserService userService;

(提供者,指定版本信息“V1.0”)

@Service(timeout = 3000, retries = 10, version = "V1.0")

请求失败,提示没有可用的提供者;

在这里插入图片描述

修改消费者版本号为“V1.0”;

@Reference(timeout = 3000, retries = 5,version = "V1.0")

请求访问成功;

在这里插入图片描述

使用Dubbo的这种特性,可以实现灰度发布,即版本更新不是一下全部更新,而是在系统中设置多个版本,如新版本的接口设置10个,旧版本的接口设置5个,实现“缓更新,慢发布”,减少系统出现异常的风险,比如一些金融、支付类的软件。

(7)负载均衡

可使用“loadbalance”属性设置接口的负载均衡策略,支持以下四种策略:

  • RandomLoadBalance:加权随机,默认算法,默认权重相同;

  • RoundRobinLoadBalance:加权轮询,默认权重相同;

  • LeastActiveLoadBalance:最少活跃优先+加权随机,能者多劳;

  • ConsistentHashLoadBalance:一致性Hash,确定入参,确定提供者,适用于有状态的请求;

在这里插入图片描述

注意使用并不是直接new它们类,而是进入到它们对应的类里面,查看它们的这行代码中写的名称

在这里插入图片描述

将该名称作为负载均衡属性的值

@Reference(loadbalance = "random")
private UserService userService;

在代码中打印一行标识,开启两个服务,发送十几条请求,可以看到两边服务均有访问,数量不等;
在这里插入图片描述

在这里插入图片描述

提供者,消费者两边都可以设置,都有效;

(8)失败降级

失败降级是指访问失败时,返回一个降级方案,即“打了折扣”的响应结果,使用mock属性设置,如下:

@Reference(mock = "return 请求错误")
private UserService userService;

另外,还可以有其他几种用法:

#  调用失败,返回请求错误
mock = "return 请求错误"

# 不发起远程调用,直接返回null,不管请求成功与否,都返回null
mock = "force:return null"

# 发起远程调用,失败后返回null
mock = "fail:return null"

# 发起远程调用,失败后抛异常
mock = "throw"

# 调用失败后使用自己实现的降级方案
mock = "自定义类的全限定类名"

其中,最后一种方法最好用,搞一下


降级降级方案,实现接口就可以

public class UserServiceMock implements UserService {
    @Override
    public String getUserName(Integer id) {
        return "降级方案";
    }

    @Override
    public User getUser(Integer id) {
        return new User(-1,"降级对象","降级密码");
    }
}

mock设置为降级方案的全限定类名

    @Reference(mock = "com.hzy.mock.UserServiceMock")
    private UserService userService;

测试,连接超时,走了降级

在这里插入图片描述

(9)集群容错

使用场景(官方);多个服务器部署同一集群中,运行同一应用程序,如果一台服务器出现故障,其他服务器将接管负载,确保应用程序对用户仍然可用。

Failover Cluster(默认设置):失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。

其他配置如下:

在这里插入图片描述

使用如下:

@Reference(cluster = "failover")
private UserService userService;

同样,也是使用对应的策略,就进入到对应的类中,使用对应的名称作为属性值;

在这里插入图片描述

Nacos+Dubbo

Nacos作为注册中心Dubbo使用与ZooKeeper基本相同,在使用上,不同的地方只有以下两点:

  • 导入的依赖,配置不同;

  • 注解不同,ZooKeeper使用@Service、@Reference注解;Nacos使用@DubboService、@DubboReference注解;

总结

总结成一句话,Dubbo是替代Feign的;

另外提一句,Dubbo是使用自定义的协议,所以如果需要考虑提高Dubbo效率,可以从传输协议、对象序列化方式这些方面入手;

文中代码的GitHub地址:https://github.com/Heapfiy/dubbo-simple.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/837660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

案例实践:小红书APP出现闪退问题,接口测试怎么做?(二)

Postman实现接口功能测试 新增货品接口实战 1、填写接口请求4要素&#xff1a; 由于货品新增接口文档找不到接口请求4要素中的&#xff1a;请求方法、请求地址和请求头&#xff0c;故&#xff0c;使用Fiddler抓包获取&#xff0c;获取结果如下&#xff1a; 1&#xff09;请求…

选择适合的项目管理工具,高效完成项目管理

很多项目经理想要知道项目计划执行的情况&#xff0c;大部分都是通过在线EXCEL文档&#xff0c;大家去更新进度&#xff0c;或者通过各种群消息&#xff0c;邮件&#xff0c;电话去通知项目经理项目执行进度&#xff0c;好一点的企业可能有专业的项目管理软件去收集进度&#x…

WebAPI文档与自动化测试

目录 1、控制器&#xff0c;项目属性里需要勾选输出Xml文档选项&#xff1a; 2、下载文档的网页数据 3、运行访问网址 4、接口测试&#xff1a; 5、批量测试&#xff1a; 6、微服务文档 总结&#xff1a; 本篇介绍框架的WebAPI文档与自动化测试 1、控制器&#xff0c;项…

Elasticsearchr入门

首先在官网下载elasticsearch8.9版本&#xff0c;以及8.9版本的kibana。 解压&#xff0c;点击es8.9bin目录下的elasticsearch.bat文件启动es 如图所示即为成功。 启动之后打开idea&#xff0c;添加依赖 <dependency><groupId>com.fasterxml.jackson.core</g…

【二开版】大魔王7.0-PHP来客云在线客服系统

前言 由于即时通讯软件不是存在敏感词汇就是收费&#xff0c;想找一个网上开源的又麻烦&#xff0c;来客云在线客服系统网上到处都能找到&#xff0c;但是由于开发时间太久&#xff0c;像公众号的一些消息服务受限不能用了&#xff0c;这一套客服系统只能做到基本的聊天对话功…

华为OD机试真题 Java 实现【最长的完全交替连续方波信号】【2023 B卷 200分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》…

TP DP PP 并行训练方法介绍

这里写目录标题 张量并行TP流水线并行 PPnaive模型并行GPipePipeDream 数据并行DPFSDP 张量并行TP 挖坑 流水线并行 PP 经典的流水线并行范式有Google推出的Gpipe&#xff0c;和微软推出的PipeDream。两者的推出时间都在2019年左右&#xff0c;大体设计框架一致。主要差别为…

Java阶段五Day19

Java阶段五Day19 问题解析 需求单查询列表功能的bug 业务逻辑&#xff1a; 需要用户登录&#xff0c;师傅入驻&#xff0c;审核入驻通过 查询师傅详情&#xff08;areaIds&#xff0c;categoryIds&#xff09; demand-server-dao-impl 包含持久层实现 requestOrderMappe…

JavaScript数据结构与算法——栈

文章目录 一、初始栈结构1.1 特性1.2 注意事项 二、栈结构的封装2.1 封装简单栈结构2.2 利用栈将十进制转二进制 一、初始栈结构 1.1 特性 类似于汉诺塔&#xff0c;后进先出&#xff0c;每次只能操作栈顶的元素。关键词&#xff1a;压栈、退栈 简单示意图&#xff1a; 1.…

java编码规范 和 数据库规范

总体规约以《阿里巴巴Java开发手册》为主&#xff0c;请开发人员至少阅读一遍该手册。 一、java编码规范 1.1 java基础规范 多使用 jdk自带库和被验证的第三方库的类和函数&#xff0c;不要用野路子来的jar包 无论是包、类、方法、变量&#xff0c;见名知意 1.2 在线文档规…

AlmediaDev Style Controls Crack

AlmediaDev Style Controls Crack StyleControls是一个稳定、强大的包(超过100个组件)&#xff0c;它使用经典绘图、系统主题、GDI和VCL样式。该软件包包含扩展标准VCL控件的独特解决方案&#xff0c;还包含许多独特的高级控件&#xff0c;用于创建具有Fluent UI模糊背景的现代…

AI的蓬勃发展,程序员的末日?

一、AI是什么&#xff1f;AI有哪些类型&#xff1f;生成式AI是什么&#xff1f;未来AI有哪些发展方向&#xff1f; ● AI是人工智能(Artificial Intelligence)的缩写,是比人类更强大的算法与软硬件系统,能模拟出人类智力相关的某些行为与功能。 ● AI主要分为三大类型: 机器学…

Docker Compose 使用方法

目录 前言 安装 Docker Compose Ubuntu 安装与更新 Red Hat 安装与更新 验证是否安装 Docker Compose 创建 docker-compose.yml 文件 创建一个MySQL 与 tomcat 示例 使用Docker Compose启动服务 前言 Docker Compose 是一个工具&#xff0c;旨在帮助定义和 共享多容器…

Scikit Learn识别手写数字 -- 机器学习项目基础篇(6)

Scikit learn是机器学习社区中使用最广泛的机器学习库之一&#xff0c;其背后的原因是代码的易用性和机器学习开发人员构建机器学习模型所需的几乎所有功能的可用性。在本文中&#xff0c;我们将学习如何使用sklearn在手写数字数据集上训练MLP模型。 其优势是&#xff1a; 它提…

React 在 html 中 CDN 引入(包含 antd、axios ....)

一、简介 cdn 获取推荐 https://unpkg.com&#xff0c;unpkg 是一个快速的全球内容交付网络&#xff0c;适用于 npm 上所有内容。 【必备】react 相关 cdn。附&#xff1a;github 官方文档获取、现阶段官方文档 CDN 网址。 <script crossorigin src"https://unpkg.com…

matlab使用教程(8)—绘制三维曲面图

1网格图和曲面图 MATLAB 在 x-y 平面中的网格上方使用点的 z 坐标来定义曲面图&#xff0c;并使用直线连接相邻的点。mesh 和surf 函数以三维形式显示曲面图。 • mesh 生成仅使用颜色来标记连接定义点的线条的线框曲面图。 • surf 使用颜色显示曲面图的连接线和面。 MATL…

Android沉浸式状态栏主题跟随状态栏背景颜色自动变化主题,状态栏主题跟随状态栏背景色自适应

1.状态栏显示模式介绍 Android系统提供了两种显示模式&#xff1a;明亮模式与暗黑模式 明亮模式&#xff08;Light Model&#xff09;&#xff1a;整体偏亮&#xff0c;即背景亮色&#xff0c;文字等内容暗色。 暗黑模式&#xff08;Dark Model&#xff09;&#xff1a;整体偏…

flutter开发实战-实现首页分类目录入口切换功能

。 在开发中经常遇到首页的分类入口&#xff0c;如美团的美食团购、打车等入口&#xff0c;左右切换还可以分页更多展示。 一、使用flutter_swiper_null_safety 在pubspec.yaml引入 # 轮播图flutter_swiper_null_safety: ^1.0.2二、实现swiper分页代码 由于我这里按照一页8…

C高级--day3(shell中的输入、命令置换符、数组、算数运算、分支结构)

#!/bin/bash pls ~/ -l | grep "^-" | wc -l qls ~/ -l | grep "^d" | wc -l echo "普通文件个数&#xff1a;$p" echo "目录文件个数&#xff1a;$q"#!/bin/bash read file posexpr index $file \. strexpr substr $file $((pos1)) 2…

Xposed回发android.os.NetworkOnMainThreadException修复

最近用xposed进行hook回发的时候&#xff0c;又出现了新的问题&#xff1b; android.os.NetworkOnMainThreadException&#xff1b; 在Android4.0以后&#xff0c;写在主线程&#xff08;就是Activity&#xff09;中的HTTP请求&#xff0c;运行时都会报错&#xff0c;这是因为…