首页 > 其他分享 >Dubbo(二)_入门

Dubbo(二)_入门

时间:2023-07-29 23:57:14浏览次数:46  
标签:Dubbo 调用 服务 入门 dubbo zookeeper 序列化

什么是 dubbo

dubbo 最新版本为 3.x,Apache Dubbo 是一款易用、高性能的 web 和 rpc 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力。 Dubbo3 替代了阿里运行多年的 HSF 框架,依托于 Dubbo 实现自己的微服务解决方案(DNS),即 Dubbo、Nacos(服务注册与管理)、Sentinel(服务降级、流量治理)。

架构的发展

水平扩展:

部署多个 tomcat服务器,client 请求时通过 loadbalance nginx 实现的特定负载均衡算法把请求发到指定服务器。这样进一步提高了系统的稳定性、可用性。但是存在数据一致性问题。

垂直扩展:

把一个单体架构划分为多个子系统,每个子系统部署在自己的 tomcat 中,多个子系统独立部署共享存储数据。这样某个子系统出现问题不会影响其它子系统的运行,便于系统维护。

RPC架构:

RPC架构是由垂直架构发展而来的,垂直架构中每个进程运行在独立的子系统中,RPC考虑的是子系统间的模块功能调用问题,Service 调用 Service 的问题。RPC 避免了服务的冗余开发,其它需要服务调用时子系统直接调用即可。RPC的核心在于如何与其它进程建立通信,需要考虑通信的方式(HTTP、TCP),采用的协议、数据序列化方式(protobuf、thrift)。

企业服务总线:

ESB,不同语言开发的系统需要调用其它语言开发的服务,这种异构系统如何进行 RPC 调用呢?因为不同进程间通过网络进行服务调用,可以在中间设计一个数据转换层(Grpc、Protobuf、Thrift IDL)将 请求参数/响应结果 进行转换,这样就实现了不同编程语言间服务的调用。

ESB 进程间通信的方式有两种,同步和异步。其中同步调用就是 RPC的调用方式,向某个服务发请请求,然后阻塞等待请求返回,适用于实时性高的系统;异步调用则可以利用 MQ消息队列,将消息放入到队列延缓处理过程。

Dubbo开发

Dubbo代码结构

代码中包含以下角色:

  • provider:功能提供者;
  • consumer:功能调用者(消费者);
  • commons-api:通用内容;
  • registry:注册中心;

软件版本

模块开发

项目整体为微服务结构,主模块 dubbo_learn 下包含 3个子模块(dubbo-01-api 用作服务 api接口定义及公共模块定义、dubbo-02-provider 用作服务提供方实现了具体的服务、dubbo-03-consumer用作消费方);

父项目依赖配置:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.10</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>3.2.0</version>
</dependency>

dubbo-01-api模块:

//定义了实体类 User、服务接口 UserService
package com.xjx.entity;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String name;
    private String password;
}



package com.xjx.service;

public interface UserService {
    public boolean login(String name, String password);
}

dubbo-02-provider模块:

provider 模块引入了 api 模块的依赖,并实现了 api模块的接口,它需要结合 Spring 将服务注册为 Bean对象并将服务发布出去,这里采用 xml 方式注册 Bean。

// 服务接口的具体实现
public class UserServiceImpl implements UserService{
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login name " + name + " password " + password);
        return false;
    }
}

// 服务持续提供,解析配置文件并阻塞运行
public class ProviderMain {
    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-provider.xml");
        context.start();

        //阻塞启动
        new CountDownLatch(1).await();
    }
}

配置文件定义为 applicationContext-provider.xml,需要定义好 rpc 的通信协议及端口、对外提供服务的名称:

<?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://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- provider名称 -->
    <dubbo:application name="dubbo-02-provider"/>

    <!-- 定义rpc通信协议 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- bean对象注册 -->
    <bean id="userService" class="com.xjx.service.UserServiceImpl"/>

    <!-- 服务发布 -->
    <dubbo:service interface="com.xjx.service.UserService" ref="userService"/>
</beans>

dubbo-03-consumer模块:

服务消费者方需要引入服务接口 api模块,并在配置文件中定义远端服务获取的相关配置。

public class ClientApplication {
    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-consumer.xml");
        
        //服务调用
        UserService service = (UserService) applicationContext.getBean("userService");
        service.login("xxxx", "123456");

        new CountDownLatch(1).await();
    }
}
<?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://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="dubbo-03-consumer"/>

    <!-- 远端服务获取配置 interface:服务接口  id:待调用的服务ID  url:访问路径-->
    <dubbo:reference interface="com.xjx.service.UserService" id="userService" url="dubbo://192.168.220.1:20880/com.xjx.service.UserService"/>
</beans>

运行结果:

provider 启动后会打印服务的调用地址:

consumer 启动后会成功调用服务,但报错,错误原因是 provider的 qos进程和 consumer 的 qos进程端口冲突,Qos=Quality of Service,qos 是 Dubbo的在线运维命令,可以对服务进行动态的配置,控制及查询,新版本 Dubbo 重构了 telnet,端口默认为 22222。

解决方案如下:

<!-- qos服务配置 -->
<dubbo:parameter key="qos.enable" value="true"/>  <!-- 是否开启在线运维命令 -->
<dubbo:parameter key="qos.accept.foreign.ip" value="false"/>  <!-- 不允许其它机器访问 -->
<dubbo:parameter key="qos.port" value="33333"/>  <!-- 修改port -->
# springboot 配置
dubbo.application.qos.enable=false
dubbo.application.qos.port=33333
dubbo.application.qos.accept.foreign.ip=false

Dubbo 程序细节补充:

  1. provider 在配置基于 Dubbo协议时,不要显式指定协议端口,用 -1 替代。
<dubbo:protocol name="dubbo" port="-1"/>
  1. 入门程序浅析:
  • 为什么 Provider 提供了 UserService 接口的实现,而在另一个 JVM 中的Consumer 可以调用?Consumer 中调用的到底是什么? 实际上 Consumer 没有直接调用远端的 UserServiceImpl,而是通过调用远端 UserServiceImpl 的代理对象 Proxy来实现。
  • 代理的核心工作是什么? 通过代理对 consumer 屏蔽网络通信的过程(通信方式、协议、序列化)来实现数据传递。

基于 SpringBoot 使用 Dubbo

思路分析

思路:深度封装,将公共配置放到 application.yaml 中,将个性配置应用到注解进行设置。

  1. Provider 的配置处理
  • dubbo 的公共配置,包括 dubbo应用名称、dubbo协议名和端口号;
  • 服务接口实现的 Bean对象、向外提供服务的 dubbo:service 对象;
  1. Consumer 的配置处理
  • dubbo 的公共配置,应用名、qos 应用;
  • 声明需要的服务;

项目开发

  1. 构建多模块 SpringBoot 应用;
  2. 引入依赖 jar 包:
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.2.0</version>
</dependency>
  1. 构建 Provider 模块

application.yaml 文件配置:

spring:
  application:
    name: DUBBO-04-BOOT-PROVIDER
dubbo:
  protocol:
    name: dubbo
    port: -1

核心启动类上标记 @EnableDubbo 注解;

对外服务类 Service

@DubboService
public class UserServiceImpl implements UserService {
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login name " + name + " password " + password);
        return false;
    }
}
  1. 构建 consumer 模块

application.yaml 共有配置:

spring:
  application:
    name: DUBBO-05-BOOT-CONSUMER
dubbo:
  application:
    qos-enable: false

需要使用服务时注入配置:

@SpringBootTest
class Dubbo05BootConsumerApplicationTests {
    @DubboReference(url = "dubbo://192.168.220.1:20880/com.xjx.service.UserService")
    private UserService userService;

    @Test
    void contextLoads() {
    }

    @Test
    void test1() {
        boolean ret = userService.login("xxxx", "1234532");
        System.out.println("ret= " + ret);
    }
}

核心启动类上建议也加入 @EnableDubbo

SpringBoot 项目细节

1、@EnableDubbo 注解的作用?

@EnableDuubo 注解用于扫描 @DubboService 注解内容,并把对应的对象实例化,发布为 RPC 服务。

@EnableDubbo 默认扫描范围为启动类及其子包下的类。但是如果 @DubboService 注解修饰的类没有放到对应路径下,还希望能够扫描到,需要在核心启动类上添加注解 @DubboComponentScan(basePackages = {"xxxxxx"}) 显式指定能够扫描到的路径。

除了使用 @DubboComponentScan 注解外,还可以在 yaml 文件中配置扫描 dubbo.scan.base-packages 来扫描指定路径下的服务 Bean对象,发布为 RPC服务。

2、@DubboService 注解的作用?

@DubboService 注解修饰类型,SpringBoot 会创建这个类型的对象并发布为 Dubbo服务。

@DubboService 等同于 @Component(@Service) @Bean 注解的创建对象的作用,它会创建对象并将 Bean对象注册到容器中,通过在 AbstractApplicationContext 类的 refresh() 方法打断点调试查看 SingletonObjects 对象可以验证:

Dubbo 序列化

1、常见的 Dubbo 序列化方式

  • Hessian:Dubbo 协议中默认的序列化实现方案;
  • Java Serialization:JDK序列化方式;
  • Dubbo 序列化:阿里序列化方案,不成熟生成环境不建议使用;
  • Json 序列化:目前有两种实现方案,一种是阿里的 fastjson 库,一种是 dubbo 自己实现的简单 json;
  • Kryo 序列化:Java序列化方式,后续替换 Hessian,是一种非常成熟的序列化实现,已经被广泛使用;
  • FST:Java序列化方式,后续替换 Hessian,但是缺乏足够成熟的使用场景;
  • ProtoBuf、Thrift IDL 等跨语言二进制序列化方案,允许在多种语言之间交换数据。

docker+zookeeper+dubbo 测试

docker 安装zookeeper 并启动的坑:https://blog.csdn.net/weixin_44808225/article/details/123329529

zookeeper 相关使用:https://juejin.cn/post/7103406988079398942

docker 安装 zookeeper:3.7.1:

# 拉取 zookeeper:3.7.1 镜像
docker pull zookeeper:3.7.1

# 启动 zookeeper 并挂载向数据/日志/配置目录
docker run -d --name zookeeper -p 2181:2181 -v /opt/docker/zookeeper/data:/data -v /opt/docker/zookeeper/conf/zoo.cfg:/conf/zoo.cfg -v /opt/docker/zookeeper/logs:/datalog --restart always  zookeeper:3.7.1

标签:Dubbo,调用,服务,入门,dubbo,zookeeper,序列化
From: https://www.cnblogs.com/istitches/p/17590832.html

相关文章

  • Dubbo(五)_服务注册原理
    服务注册是指将服务暴露出来的过程,包括了服务解析、服务启动、服务注册三部分。其中服务解析就是将Dubbo的服务配置解析成Spring的Bean对象;服务启动是启动一个可以处理请求的服务;服务注册是指将服务信息保存到注册中心中,供服务消费方获取。Dubbo的注册中心支持Redis、Zooke......
  • Dubbo(四)_全局架构
    整体架构全局架构分为注册中心,通常为zk/redis;服务提供者Provider,用来提供并注册服务到注册中心;服务消费者Consumer,用来向注册中心订阅服务,当注册中心服务发生变动时notify通知消费者,消费者通过invoke远程调用服务提供者;Monitor监控者用来监控服务,统计服务的调用次数和调......
  • Dubbo(三)_spi
    DubboSPI源码分析DubboSPI的核心实现是ExtensionLoader,分析时先分析ExtensionLoader的成员变量和对公方法,依次分析扩展点的加载、扩展点的依赖注入、扩展点的自适应、扩展点的激活。分析中的名词约定:扩展点————扩展点实例化的对象,如org.apache.dubbo.rpc.protocol.d......
  • MongoDB从入门到精通深入学习路线图?
    MongoDB从入门到精通深入学习路线图?学习MongoDB从入门到精通需要掌握以下内容,以下是一个深入学习路线图:阶段1:入门1.1学习数据库基础知识-数据库的概念和作用-关系数据库和非关系数据库的区别-NoSQL数据库的特点和优势1.2安装和配置MongoDB-下载并安装MongoDB-配置Mongo......
  • 18-Hive入门&安装
    1.Hive概述1.1什么是Hive?ApacheHive是一款建立在Hadoop之上的开源数据仓库工具,可以将存储在Hadoop文件中的结构化、半结构化数据文件映射为一张数据库表,基于表提供了一种类似SQL的查询模型,称为Hive查询语言(HQL),用于访问和分析存储在Hadoop文件中的大型数据集。H......
  • Webpack 入门教程-安装
    Webpack是一个前端资源加载/打包工具。安装Webpack使用cnpm安装webpack:cnpminstallwebpack-g创建项目接下来我们创建一个目录app:mkdirapp在app目录下添加runoob1.js文件,代码如下:app/runoob1.js文件document.write("Itdashu.");app/index.html文件<html>......
  • Android studio 4.1.2安装入门教程
    目录JDK安装与配置一、下载JDK二、JDK安装三、JDK的环境配置四、JDK的配置验证Androidstudio安装Androidstudio连接手机真机调试(以华为鸿蒙为例)一、新建一个android项目二、进入项目面板三、配置AndroidStudio四、安装手机驱动程序五、连接手机六、运行程序七、......
  • 【NestJS系列】从Nest CLI开始入门
    初识NestJSNest是一个渐进的Node.js框架,它可以在TypeScript和JavaScript(ES6、ES7、ES8)之上构建高效、可伸缩的企业级服务器端应用程序。Nest基于TypeScript编写并且结合了OOP(面向对象编程),FP(函数式编程)和FRP(函数式响应编程)的相关理念。在设计上的很多灵感来自于Ang......
  • Python入门简单代码
     1.#定义一个函数,使该函数能够返回4个参数中的最大值。defmax4(a,b,c,d):max1=max(a,b)max2=max(c,d)max3=max(max1,max2)returnmax3print(max4(1,2,3,4))2.#使用匿名函数完成求两个参数之和的功能add=lambdax,y:x+yprint(add(1,2))3.#编写一个......
  • JavaWeb之Servlet入门版教务系统(一)
    本次要分享的内容是使用Servlet技术实现最简单的从页面到后台的一个简化版的教务系统功能模块。在讲述系统之前,首先需要了解一下JavaWeb中的MVC分层重要思想,请看下图:MVC分层思想把软件系统分为View(视图层),Controller(控制层),Model(模型层),通过这三层结构。让页面请求必须通过控制......