【SpringBoot】Dubbo、Zookeeper

文章目录

前提知识概要

分布式系统

  1. "分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统";
  2. 其目的是利用更多的机器,处理更多的数据
  3. 用小而多,代替大且贵
  4. 只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统;
  5. 分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题;
  6. 但是 缺点也在于这里 过分的依赖于 网络通信协议;

单体架构

网络吞吐量小时,使用一个应用(application),将所有的功能都部署在一起,以减少部署的节点和成本。为此简化CRUD的数据访问框架ORM就是关键。

ORM:Mybatis、Hibernate

使用场景:小型网站,将所有功能都部署到一个地方,简单,易用

缺点:

  • 性能扩展比较难
  • 协同开发问题
  • 不利于升级维护

垂直应用架构

数据吞吐量打的时候,单一的应用会增加机器所在压力,将应用的几块拆成互不相干的几个应用以提升效率。这个时候加速前端页面开发的WEB框架又是关键:

WEB框架:MVC,MVVM

通过切分业务 来实现各个模块的独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能拓展也更加的方便,更有针对性。

缺点:

  • 公用的模块无法重复利用;
  • 多重复写功能导致资源浪费;

分布式架构

当垂直的应用越来越多,应用之间的交互不可避免,就去优化垂直应用架构;

将核心的业务提取,成为独立的服务,逐步形成稳定的服务中心,是前段更好的应用市场。

提高业务服用整合的**分布式框架 **又是关键。

分布式框架:RPC

流式架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,这个时候有需要一个调度中心,能够将有限的资源得到最大的利用, 这时候,用于提高机器利用率的资源调度又成为了重点

提高机器利用率的资源调度和治理中心(SOA)[Service Oriented Architecture]是关键

RPC

RPC【Remote Procedure Call】是指远程过程调用,是一只进程思想,而不是一种规范,类似于我们的。

允许程序调用另一个地址空间 。(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。

两台服务器A、B,主要是部署在A服务器上,想要调用B服务器,但是不在一个机器中,不能直接去调用,需要利用网络,通过网络传输将自己想要的数据及想要在B服务站执行的内容 传输过去。

RPC 所实现的内容就是让A服务器调用B服务器 的过程被忽略在调用函数 候像调用A自己 本身的函数一样;

RPC的两个核心就是:通讯(HTTP、RPC)、序列化(序列化的方式就是方便数据传输);

如何给老婆解释什么是RPC

假设你有一个计算器接口,Calculator,以及它的实现类CalculatorImpl,那么在系统还是单体应用时,你要调用Calculator的add方法来执行一个加运算,直接new一个CalculatorImpl,然后调用add方法就行了,这其实就是非常普通的本地函数调用,因为在同一个地址空间,或者说在同一块内存,所以通过方法栈和参数栈就可以实现。

现在,基于高性能和高可靠等因素的考虑,你决定将系统改造为分布式应用,将很多可以共享的功能都单独拎出来,比如上面说到的计算器,你单独把它放到一个服务里头,让别的服务去调用它。

**问题:**服务A里头并没有CalculatorImpl这个类,那它要怎样调用服务B的CalculatorImpl的add方法呢?

  • 可以模仿B/S架构的调用方式呀,在B服务暴露一个Restful接口,然后A服务通过调用这个Restful接口来间接调用CalculatorImpl的add方法。

很好,这已经很接近RPC了,不过如果是这样,那每次调用时,是不是都需要写一串发起http请求的代码呢?比如httpClient.sendRequest...之类的,能不能像本地调用一样,去发起远程调用,让使用者感知不到远程调用的过程呢,像这样:

  • 代理模式呀!而且最好是结合Spring IoC一起使用,通过Spring注入calculator对象,注入时,如果扫描到对象加了@Reference注解,那么就给它生成一个代理对象,将这个代理对象放进容器中。而这个代理对象的内部,就是通过httpClient来实现RPC远程过程调用的。

就是很多RPC框架要解决的问题和解决的思路,比如阿里的Dubbo。

ps:Dubbo以前是阿里的,后来才移交给了Apache

RPC要解决的两个问题:

  • 解决分布式系统中,服务之间的调用问题。
  • 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。

RPC很少用到http(超文本传输协议)协议来进行数据传输,毕竟我只是想传输一下数据而已,何必动用到一个文本传输的应用层协议呢,我为什么不直接使用二进制传输?比如直接用Java的Socket协议进行传输。

以左边的Client端为例,Application就是rpc的调用方,Client Stub就是我们上面说到的代理对象,也就是那个看起来像是Calculator的实现类,其实内部是通过rpc方式来进行远程调用的代理对象,至于Client Run-time Library,则是实现远程调用的工具包,比如jdk的Socket,最后通过底层网络实现实现数据的传输。

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:柳树之

链接:https://www.jianshu.com/p/2accc2840a1b

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Client将数据进行序列化 传输给Server,Server对数据进行反序列化,读取数据内容,只进行服务调用,程序处理,将处理的内容结果通过在进行序列化 传输到Client,最终实现全局的调用;

Dubbo

类比于SpringCloud,都是使用的分布式架构思想,但是Dubbo是一个框架,而SpringCloud是一套整合于Spring的生态;

概念

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:

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

官网:cn.dubbo.apache.org

QuickStart:https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/quick-start/starter/

  1. 基本概念

**服务提供者(**Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

服务消费者(Consumer):调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者

监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

调用关系:

  1. 服务Provider容器 Container负责启动start,加载,运行服务提供者。
  2. 服务提供者Provider在启动时,向注册中心Registry注册register自己提供的服务。
  3. 服务消费者Consumer在启动时,向注册中心Registry订阅subscribe自己所需的服务。
  4. 注册中心Registry返回服务提供者Provider地址列表通知notify给消费者,如果有变更,注册中心将基于长连接推送invoke变更数据给消费者。
  5. 服务消费者Consumer,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

Dubbo环境搭建

在最新的3.3.0版本官网上,可以直接创建你 基于Spring Boot 的微服务应用 ,需要注意

因为是看的狂神的20年的视频,所以先按照他当时的做法思路使用zookeeper,这个要参照官网

Zookeeper

学习文档:https://cn.dubbo.apache.org/zh-cn/overview/reference/integrations/zookeeper/

Zookeeper: https://zookeeper.apache.org/releases.html

  1. 下载Zookeeper

下载3.8.4 是稳定版;

官网太慢,去镜像站下载:https://mirrors.aliyun.com/apache/zookeeper

  1. 解压 apache-zookeeper-3.8.4widows运行"D:\work\apache-zookeeper-3.8.4\bin\zkServer.cmd",添加pause ,报错查看错误信息
  2. 解决 java.lang.ClassNotFoundException问题

发现调用jar包找不到,我下载的是源码版,重新下载个二进制版,把libcopy进去,网络不好的情况下不要自己编译。

  1. 解决 Error processing D:\work\apache-zookeeper-3.8.4\bin\..\conf\zoo.cfg的问题

目录下没有zoo.cfg文件,copy sample生成一个,根据上述内容配置,然后启动

  1. 启动成功

测试 Zookeeper

  1. run zkCli.cmd,显示连接成功;
  2. create --e /aaa 123:创建一个aaa节点,值为123

在 Zookeeper 3.8 版本之后,create -e(表示创建一个带有 ephemeral 选项的节点)已被废弃。现在,如果你想创建一个临时节点(ephemeral node),你应该使用 create 命令时直接指定 -e 参数后面跟路径和数据。

  1. get /aaa,显示没有创建?检查问题,重新创建使用 create /aaa 123就好了;

Window环境下使用Dubbo-admin

在官网可以看到这段描述,Dubbo-admin可以对整个集群进行查询调用,

官网:

文档编辑完 没检查就提交了 哈哈哈

  1. 下载Dubbo-admin
  1. 下载完解压,使用目前最新的 最稳定版本,解压 ;
  2. 检查 dubbo-admin-server\src\main\resources\application.properties的端口号配置;
  3. 打包 cd 到根目录mvn clean package -Dmaven.test.skip=true,等待打包完成;
  4. 执行打包好的jar包java -jar dubbo-admin-0.4.0.jar
  5. Session 0x0 for server 127.0.0.1/<unresolved>:2181, unexpected error, closing socket connection and attempting reconnect提示报错,配置host文件 把localhost的地址映射加进去;
  6. 一直启动失败??问题好奇怪
  7. 访问http://localhost:7001/?,默认账号名root 密码 root

版本匹配不对

对应的版本不对?

  • Dubbo Admin 0.4.0发布于2020年,其设计主要针对JDK8环境
  • Zookeeper 3.8.4对JDK17的支持尚不完善,已知存在NIO通道问题

更换完版本后,启动依旧报错,系统提示 java.lang.IllegalStateException

java 复制代码
java.lang.IllegalStateException: zookeeper not connected, the address is: zookeeper://127.0.0.1:2181/org.apache.dubbo.config.ConfigCenterConfig?check=true&config-file=dubbo.properties&group=dubbo&highest-priority=false&namespace=dubbo&timeout=30000 at org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.<init> (CuratorZookeeperClient.java:118)

Jdk17连接zookeeper报错:127.0.0.1/<unresolved>:2181_java.lang.illegalargumentexception: unable to cano-CSDN博客

使用 Dubbo Admin 0.6.0看看,访问 http://localhost:38080

好了,终于进去了,使用Dubbo Admin 0.6.0也是报错,之后再去检查pom中的依赖,发现org.apache.zookeeper的依赖默认版本是zookeeper-3.4.14,于是将他升级为最新版,启动成功。其他问题还在等待校验。

服务注册实战

官方文档: https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/tasks/service-discovery/zookeeper/

内容总结

  1. zookeeper :一个jar包 (必须存在)
  2. dubbo-admin:是一个监控管理后台 (可有可无)
  3. Dubbo:jar包 (需要用)
  4. 最新的Dubbo 有好多实现方案,根据具体情况使用,阿里云本身有nacos

导入相关依赖

  1. SpringBoot
xml 复制代码
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>
<!-- 仅当 Zookeeper Server 版本是 3.4.x 及以下时,使用此依赖 -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-zookeeper-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>
<!-- 仅当 Zookeeper Server 版本是 3.5.x 及以上时,使用此依赖-->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-zookeeper-curator5-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>

检查自己 的Zookeeper的版本是 3.8.4 所以使用dubbo-zookeeper-curator5-spring-boot-starter;

找不着依赖就mvn clean install

  1. 不使用SpringBoot
xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>3.3.0</version>
    </dependency>
    <!-- This dependency helps to introduce Curator and Zookeeper dependencies that are necessary for Dubbo to work with zookeeper as transitive dependencies. -->
    <!-- 仅当 Zookeeper Server 版本是 3.4.x 及以下时,使用此依赖 -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>3.3.0</version>
        <type>pom</type>
    </dependency>
    <!-- 仅当 Zookeeper Server 版本是 3.5.x 及以上时,使用此依赖	-->
	<dependency>
		<groupId>org.apache.dubbo</groupId>
		<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
		<version>3.3.0</version>
		<type>pom</type>
	</dependency>

</dependencies>

选择 Zookeeper 版本

Dubbo 3.3.0 版本开始正式支持 JDK 17,如果您使用 JDK 17,则必须选用 dubbo-dependencies-zookeeper-curator5 或 dubbo-zookeeper-curator5-spring-boot-starter 依赖,对应的 Zookeeper Server 推荐是 3.8.0 版本及以上。

::当前使用的最新稳定版 3.8.4

配置并启用 Zookeeper

配置properties,注册中心的地址,服务发现名 和 扫描包

properties 复制代码
# dubbo.properties
dubbo.registry.address=zookeeper://localhost:2181
# 新用户请设置此值,表示启用应用级服务发现,可选值 interface、instance、all,默认值为 all,未来版本将切换默认值为 instance
dubbo.registry.register-mode=instance

address 是启用 zookeeper 注册中心唯一必须指定的属性,而在生产环境下,address 通常被指定为集群地址,如 address=zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181

protocol 与 address 分开配置的模式也可以,

<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181" />

创建服务接口和实现(DubboService)类,这里是配置Provider

使用@DubboService的注解 ,为了将接口暴漏出去,使外部接口可以扫描的到TicketService

java 复制代码
package com.demo.service.impl;

import com.demo.service.TicketService;
import org.apache.dubbo.config.annotation.DubboService;


@DubboService
public class TicketImpl implements TicketService {
    @Override
    public String getTicket() {
        return "Mrs.K sailed ticket";
    }
}

启动Dubbo的扫描(EnableDubbo)

  1. 如果没有找到注解@EnableDubbo,记得去更新下maven包,看看有没有把依赖导进来,依赖启动器导入的情况下一般就能够发现;
java 复制代码
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableDubbo
@SpringBootApplication
public class Springboot09DubboserveApplication {

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

}
  1. 启动项目测试,项目正常启动,
  1. 服务测试

重复上述操作,将需要注册Dubbo的配置下

  1. 配置端口,注册地址;
  1. 启动类开启Dubbo;

编写Service,这次是消费者,调用提供者所提供的内容

在Dubbo中,分提供者Provider和消费者Consumer两个概念;

  • 提供者实现接口,提供具体的实现内容;
  • 消费者负责调用接口,使用提供者所实现的功能;
  • 因为不是在一个服务中启动,所以存在RPC的管理,Dubbo的解决方案由此而生;
  1. 在Dubbo中,消费者所需要使用的是Refer,选择指向的地址@DubboReference
java 复制代码
@Component
public class UserServiceImpl implements UserService {

    //我们需要去拿去注册中心的服务
    @DubboReference
    private TicketService ticketService;

    public void buyTicket() {

        System.out.println("》》User正在买票...");
        System.out.println("User正在调用ticket服务...");
        System.out.println(ticketService.getTicket());
        System.out.println("调用Ticket完成《《");
    }

}
  1. 这样子代码就会去找 TicketService接口,但是因为TicketService是在另一个服务中启用的,所以需要把那个接口在这重现一下
java 复制代码
package com.demo.service;

public interface TicketService {

    String getTicket();

}
  1. 在Dubbo-admin中查找,启用成功
  1. 代码测试,要先关闭Dubbo-admin,还是不行。。。

技术没到家,一直在报端口占用服务冲突的错

java 复制代码
package com.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.demo.service.UserService;

@SpringBootTest
class Springboot09DubboserveApplicationTests {

    @Autowired
    UserService userService;

    @Test
    void contextLoads() {
        userService.buyTicket();
    }
}
  1. 写个Controller,在Controller中调用Service之后,启动页面测试
  1. 优化下 优化内容显示到页面上

项目启动成功:

测试功能

相关推荐
芒克芒克20 分钟前
本地部署SpringBoot项目
java·spring boot·spring
小突突突1 小时前
Spring框架中的单例bean是线程安全的吗?
java·后端·spring
iso少年1 小时前
Go 语言并发编程核心与用法
开发语言·后端·golang
roman_日积跬步-终至千里1 小时前
【大数据架构-数据中台(1)】解码数据中台:从概念到认知
大数据·架构·dubbo
掘金码甲哥1 小时前
云原生算力平台的架构解读
后端
码事漫谈1 小时前
智谱AI从清华实验室到“全球大模型第一股”的六年征程
后端
码事漫谈1 小时前
现代软件开发中常用架构的系统梳理与实践指南
后端
Mr.Entropy1 小时前
JdbcTemplate 性能好,但 Hibernate 生产力高。 如何选择?
java·后端·hibernate
YDS8292 小时前
SpringCloud —— MQ的可靠性保障和延迟消息
后端·spring·spring cloud·rabbitmq
无限大62 小时前
为什么"区块链"不只是比特币?——从加密货币到分布式应用
后端