91.【SpringBoot-03】

news2024/12/28 22:40:47

SpringBoot-03

  • (十四)、任务
    • 1.异步任务
    • 2.邮件任务
        • (1).简单邮箱发送
        • (2).复杂邮箱发送
    • 3.定时任务
        • (1).cron表达式
        • (2).特殊表达式
        • (3).定时任务测试
        • (4).常用cron表达式
  • (十五)、Dubbo和Zookeeper集成
    • 1.分布式原理
        • (1).Dubbo文档
    • 2.什么是RPC?
    • 3.Dubbo的概念和介绍
        • (1).Dubbo是什么
        • (2). Dubbo能做什么
    • 3.搭建测试环境
        • (1).Zookeeper介绍
        • (2).window下安装zookeeper
        • (3).window下安装dubbo-admin
    • 4.SpringBoot + Dubbo + zookeeper
        • (1).框架搭建
        • (2).服务提供者 provider-server
        • (3).服务消费者

(十四)、任务

1.异步任务

所谓异步,在某些功能实现时可能要花费一定的时间,但是为了不影响客户端的体验,选择异步执行执行等待,前端直接展现。
在本列中我们设置线程等待事件为3秒,接着影响的是前端会转圈三秒才能进入

service层

@Service
public class AsyncService {

    public void hello(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("数据正在传输...");
    }
}

controller层

@RestController
public class AsyncController {

    @Autowired
    AsyncService asyncService;

    @RequestMapping("/hello")
    public String async(){
        asyncService.hello();
        return "ok";
    }
}

这样在执行/hello请求时,网站会延时三秒再显示ok,后台数据也会三秒后显示数据正在传输

在这里插入图片描述

现在想要做到前端快速响应我们的页面,后台去慢慢的传输数据,就要用到springboot自带的功能-----》 异步
①想办法告诉spring我们的异步方法是异步的,所以要在方法上添加注解

package com.jsxs.service;


import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
// 告诉Spring这是一个异步的方法
@Async
public class AsyncService {
    public void hello(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("数据正在处理⭐⭐⭐");
    }
}

②去springboot主程序中开启异步注解功能

package com.jsxs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
// 开启异步注解功能
@EnableAsync
public class SpringBoot09TestApplication {

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

}

重启即可
我么发现前端页面会直接显示,后端的等待事件进行异步等待
在这里插入图片描述
在这里插入图片描述

2.邮件任务

邮件发送,在我们的日常开发中,也非常的多,Springboot也帮我们做了支持

  • 邮件发送需要引入spring-boot-start-mail
  • SpringBoot 自动配置MailSenderAutoConfiguration
  • 定义MailProperties内容,配置在a
  • pplication.yml中
  • 自动装配JavaMailSender测试邮件发送

测试

(1).简单邮箱发送

1、引入pom依赖

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

2、配置文件:

#  用户名
spring.mail.username=2261203961@qq.com
#  授权码
spring.mail.password=你的邮箱授权码
#  链接主机
spring.mail.host=smtp.qq.com
# 开启加密验证
spring.mail.properties.mail.smtp.ssl.enable=true

首先你需要去邮箱网站开启POP3/SMTP
在这里插入图片描述
3、Spring单元测试

package com.jsxs;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import javax.annotation.Resource;

@SpringBootTest
class SpringBoot09TestApplicationTests {

    @Resource
    JavaMailSenderImpl sender;
    @Test
    void contextLoads() {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("2022吉林省软件设计大赛");   //  主题
        message.setText("汪汪队摸大鱼荣获三等奖");   // 文章内容
        message.setFrom("2261203961@qq.com");   //  发送人
        message.setTo("2261203961@qq.com");
        sender.send(message);
        System.out.println("发送成功");
    }

}

在这里插入图片描述

(2).复杂邮箱发送

发送一个较为复杂的邮件:

    @Test
    void contextLoads2() throws MessagingException {
        //  一个复杂的邮件
        MimeMessage message = sender.createMimeMessage();
        // 组装
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message,true);
        mimeMessageHelper.setSubject("2022吉林省软件设计大赛");
        //  html
        mimeMessageHelper.setText("<p style='color:red'>汪汪队摸大鱼荣获三等奖</p>",true);   //   添加true目的是为了能够解析html
        //  附件  ----> 一定要复制绝对路径
        mimeMessageHelper.addAttachment("1.jpg",new File("E:\\Ideal源码\\SpringBoot-09-test\\src\\main\\resources\\static\\img\\1.jpg"));

        mimeMessageHelper.setFrom("2261203961@qq.com");
        mimeMessageHelper.setTo("2261203961@qq.com");
        sender.send(message);
    }

在这里插入图片描述

查看邮箱,邮件接收成功!

我们只需要使用Thymeleaf进行前后端结合即可开发自己网站邮件收发功能了!

要学会封装成一个工具类,自己调用自己设置的接口就可以了

3.定时任务

项目开发中经常需要执行一些定时任务,比如需要在每天凌晨的时候,分析一次前一天的日志信息,Spring为我们提供了异步执行任务调度的方式,提供了两个接口。

  • TaskExecutor接口 -----》任务调度者
  • TaskScheduler接口 ------》任务执行者

两个注解:

  • @EnableScheduling ----- 》开启定时的注解
  • @Scheduled -----》什么时候执行

(1).cron表达式

Cron表达式是一个具有时间含义的字符串,字符串以5-6个空格隔开,分为6~7个域,格式为X X X X X X X。其中X是一个域的占位符。最后一个代表年份的域非必须,可省略。单个域有多个取值时,使用半角逗号,隔开取值。每个域可以是确定的取值,也可以是具有逻辑意义的特殊字符。每个域最多支持一个前导零。

cron表达式格式:

{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
字段允许值允许的特殊字符
秒(Seconds)0~59的整数, - * / 四个字符
分(Minutes)0~59的整数, - * / 四个字符
小时(Hours)0~23的整数, - * / 四个字符
日期(DayofMonth)1~31的整数(但是你需要考虑你月的天数,- * ? / L W C 八个字符
月份(Month))1~12的整数或者 JAN-DEC, - * / 四个字符
星期(DayofWeek)1~7的整数或者 SUN-SAT (1=SUN), - * ? / L C # 八个字符
年(可选,留空)(Year)1970~2099, - * / 四个字符

(2).特殊表达式

Cron表达式中的每个域都支持一定数量的特殊字符,每个特殊字符有其特殊含义。
在这里插入图片描述

(3).定时任务测试

1、创建一个ScheduledService

我们里面存在一个hello方法,他需要定时执行,怎么处理呢?

package com.jsxs.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledService {

    //  我们想要在一个特定的时间执行这个方法~

    // cron 表达式--》  秒 分 时 日 月 周几
    @Scheduled(cron = "0 39 18 * * 0-7")
    public void hello(){
        System.out.println("hello 被你执行了");
    }
}

2、这里写完定时任务之后,我们需要在主程序上增加@EnableScheduling 开启定时任务功能

package com.jsxs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
// 开启异步功能的注解
@EnableAsync
// 开启定时功能的注解
@EnableScheduling
public class SpringBoot09TestApplication {

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

}

在这里插入图片描述

(4).常用cron表达式


(1)0 0 2 1 * ? *   表示在每月的1日的凌晨2点调整任务
(2)0 15 10 ? * MON-FRI   表示周一到周五每天上午10:15执行作业
(3)0 15 10 ? 6L 2002-2006   表示2002-2006年的每个月的最后一个星期五上午10:15执行
(4)0 0 10,14,16 * * ?   每天上午10点,下午2点,4
(5)0 0/30 9-17 * * ?   朝九晚五工作时间内每半小
(6)0 0 12 ? * WED    表示每个星期三中午12
(7)0 0 12 * * ?   每天中午12点触
(8)0 15 10 ? * *    每天上午10:15触
(9)0 15 10 * * ?     每天上午10:15触
(10)0 15 10 * * ? *    每天上午10:15触
(11)0 15 10 * * ? 2005    2005年的每天上午10:15触
(12)0 * 14 * * ?     在每天下午2点到下午2:59期间的每1分钟触
(13)0 0/5 14 * * ?    在每天下午2点到下午2:55期间的每5分钟触
(14)0 0/5 14,18 * * ?     在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触
(15)0 0-5 14 * * ?    在每天下午2点到下午2:05期间的每1分钟触
(16)0 10,44 14 ? 3 WED    每年三月的星期三的下午2:10和2:44触发
(17)0 15 10 ? * MON-FRI    周一至周五的上午10:15触发
(18)0 15 10 15 * ?    每月15日上午10:15触发
(19)0 15 10 L * ?    每月最后一日的上午10:15触发
(20)0 15 10 ? * 6L    每月的最后一个星期五上午10:15触发
(21)0 15 10 ? * 6L 2002-2005   2002年至2005年的每月的最后一个星期五上午10:15触发
(22)0 15 10 ? * 6   #3   每月的第三个星期五上午10:15触发
(1)0/2 * * * * ?   表示每2秒 执行任务
(1)0 0/2 * * * ?   表示每2分钟 执行任务
(1)0 0 2 1 * ?   表示在每月的1日的凌晨2点调整任务
(2)0 15 10 ? * MON-FRI   表示周一到周五每天上午10:15执行作业
(3)0 15 10 ? 6L 2002-2006   表示2002-2006年的每个月的最后一个星期五上午10:15执行作
(4)0 0 10,14,16 * * ?   每天上午10点,下午2点,4点
(5)0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
(6)0 0 12 ? * WED   表示每个星期三中午12点
(7)0 0 12 * * ?   每天中午12点触发
(8)0 15 10 ? * *   每天上午10:15触发
(9)0 15 10 * * ?     每天上午10:15触发
(10)0 15 10 * * ?   每天上午10:15触发
(11)0 15 10 * * ? 2005   2005年的每天上午10:15触发
(12)0 * 14 * * ?     在每天下午2点到下午2:59期间的每1分钟触发
(13)0 0/5 14 * * ?   在每天下午2点到下午2:55期间的每5分钟触发
(14)0 0/5 14,18 * * ?     在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
(15)0 0-5 14 * * ?   在每天下午2点到下午2:05期间的每1分钟触发
(16)0 10,44 14 ? 3 WED   每年三月的星期三的下午2:10和2:44触发
(17)0 15 10 ? * MON-FRI   周一至周五的上午10:15触发
(18)0 15 10 15 * ?   每月15日上午10:15触发
(19)0 15 10 L * ?   每月最后一日的上午10:15触发
(20)0 15 10 ? * 6L   每月的最后一个星期五上午10:15触发
(21)0 15 10 ? * 6L 2002-2005   2002年至2005年的每月的最后一个星期五上午10:15触发
(22)0 15 10 ? * 6#3   每月的第三个星期五上午10:15触发

(十五)、Dubbo和Zookeeper集成

1.分布式原理

在《分布式系统原理与范型》一书中有如下定义:“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”;

​ 分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据

​ 分布式系统(distributed system)是建立在网络之上的软件系统。

​ 首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。(所以分布式不应该在一开始设计系统时就考虑到)因为,分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。
在这里插入图片描述

(1).Dubbo文档

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,急需一个治理系统确保架构有条不紊的演进

在Dubbo的官网文档有这样一张图

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

在这里插入图片描述
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
在这里插入图片描述

垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
在这里插入图片描述
缺点:公用模块无法重复利用,开发性的浪费

分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
在这里插入图片描述

流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
在这里插入图片描述

2.什么是RPC?

在这里插入图片描述

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。为什么要用RPC呢就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯,由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。RPC就是要像调用本地的函数一样去调远程函数;
在这里插入图片描述

推荐阅读文章:https://www.jianshu.com/p/2accc2840a1b

说白了就是不同于调用本地的而是调用远程资源和方法

RPC原理
在这里插入图片描述
步骤分析:
在这里插入图片描述
RPC两个核心模块:通讯(信息传送),序列化(数据传输需要转换)。

3.Dubbo的概念和介绍

(1).Dubbo是什么

Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架

其核心部分包含:
1》远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2》集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
3》自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

(2). Dubbo能做什么

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

3.搭建测试环境

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

在这里插入图片描述
服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

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

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

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

调用关系说明

l 服务容器负责启动,加载,运行服务提供者。

l 服务提供者在启动时,向注册中心注册自己提供的服务。

l 服务消费者在启动时,向注册中心订阅自己所需的服务。

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

l 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

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

(1).Zookeeper介绍

Zoookeeper是什么?

官方文档上这么解释zookeeper,它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。

上面的解释有点抽象,简单来说zookeeper=文件系统+监听通知机制

①.文件系统
Zookeeper维护一个类似文件系统的数据结构

在这里插入图片描述
每个子目录项如 NameService 都被称作为 znode(目录节点),和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

有四种类型的znode:

  1. PERSISTENT-持久化目录节点客户端与zookeeper断开连接后,该节点依旧存在
  2. PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
  3. EPHEMERAL-临时目录节点-客户端与zookeeper断开连接后,该节点被删除
  4. EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

②、 监听通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

就这么简单,下面我们看看Zookeeper能做点什么呢?

Zookeeper能做什么?

zookeeper功能非常强大,可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理等功能,我们这里拿比较简单的分布式应用配置管理为例来说明。

假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 zookeeper 的通知,然后从 zookeeper 获取新的配置信息应用到系统中。
在这里插入图片描述
如上,你大致应该了解zookeeper是个什么东西,大概能做些什么了,我们马上来学习下zookeeper的安装及使用

(2).window下安装zookeeper

1、下载zookeeper :地址, 我们下载3.4.14 , 最新版!解压zookeeper

2、运行/bin/zkServer.cmd ,初次运行会报错,没有zoo.cfg配置文件;

安装包地址:链接:https://pan.baidu.com/s/1_iRikIPD7J115f8r8uTLKg 提取码:xd91

可能遇到问题:闪退 !
解决方案:编辑zkServer.cmd文件末尾添加pause 。这样运行出错就不会退出,会提示错误信息,方便找到原因。
在这里插入图片描述
3、修改zoo.cfg配置文件

将conf文件夹下面的zoo_sample.cfg复制一份改名为zoo.cfg即可。

注意几个重要位置:

dataDir=./ 临时数据存储的目录(可写相对路径)

clientPort=2181 zookeeper的端口号

修改完成后再次启动zookeeper
在这里插入图片描述
在这里插入图片描述
4、使用zkCli.cmd测试

ls /:列出zookeeper根下保存的所有节点

[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]

在这里插入图片描述
create –e /jsxs 12:创建一个jsxs节点,值为12

[zk: localhost:2181(CONNECTED) 10] create -e /jsxs 12
Created /jsxs

我们再来查看一下节点

get /jsxs
12
cZxid = 0x6
ctime = Thu Feb 09 12:17:02 GMT+08:00 2023
mZxid = 0x6
mtime = Thu Feb 09 12:17:02 GMT+08:00 2023
pZxid = 0x6
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x1000db767b10000
dataLength = 2
numChildren = 0

(3).window下安装dubbo-admin

dubbo本身并不是一个服务软件。它其实就是一个jar包,能够帮你的java程序连接到zookeeper,并利用zookeeper消费、提供服务。

但是为了让用户更好的管理监控众多的dubbo服务,官方提供了一个可视化的监控程序dubbo-admin,不过这个监控即使不装也不影响使用。

我们这里来安装一下:

1、下载dubbo-admin

地址 :https://github.com/apache/dubbo-admin/tree/master

2、解压进入目录
解压后,进入dubbo-admin-master,
首先,要进入dubbo-admin-master\dubbo-admin-server\src\main\resources中的application.properties目录下,指定zookeeper的地址:

server.port=7001
spring.velocity.cache=false
spring.velocity.charset=UTF-8
spring.velocity.layout-url=/templates/default.vm
spring.messages.fallback-to-system-locale=false
spring.messages.basename=i18n/message
spring.root.password=root
spring.guest.password=guest

dubbo.registry.address=zookeeper://127.0.0.1:2181

在这里插入图片描述

3、在项目目录下打包dubbo-admin
e:
cd Dubbo-admin\dubbo-admin-master-0.2.0\dubbo-admin-master-0.2.0

mvn clean package -Dmaven.test.skip=true

第一次打包的过程有点慢,需要耐心等待!直到成功!

在这里插入图片描述

4、执行 dubbo-admin\target 下的dubbo-admin-0.0.1-SNAPSHOT.jar

java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

【注意:zookeeper的服务一定要打开!】

执行完毕,我们去访问一下 http://localhost:7001/ , 这时候我们需要输入登录账户和密码,我们都是默认的root-root;

登录成功后,查看界面
在这里插入图片描述

4.SpringBoot + Dubbo + zookeeper

(1).框架搭建

1 启动zookeeper !

2 IDEA创建一个空项目;

3.创建一个模块,实现服务提供者:provider-server , 选择web依赖即可

4.项目创建完毕,我们写一个服务,比如卖票的服务;

编写接口

package com.jsxs.provider.service;

public interface TicketService {
   public String getTicket();
}

编写实现类

package com.jsxs.service;

public class TicketServiceImpl implements TicketService{
    @Override
    public String getTicket() {
        return "JSXS";
    }
}

5.创建一个模块,实现服务消费者:consumer-server , 选择web依赖即可

6.项目创建完毕,我们写一个服务,比如用户的服务;

编写service

package com.jsxs.service;

public interface UserService {
    // 想获取provider-server提供的票
    
}

需求:现在我们的用户想使用买票的服务,这要怎么弄呢 ?

(2).服务提供者 provider-server

1、将服务提供者注册到注册中心,我们需要整合Dubbo和zookeeper,所以需要导包

我们从dubbo官网进入github,看下方的帮助文档,找到dubbo-springboot,找到依赖包

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

zookeeper的包我们去maven仓库下载,zkclient;

<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency>
   <groupId>com.github.sgroschupf</groupId>
   <artifactId>zkclient</artifactId>
   <version>0.1</version>
</dependency>

【新版的坑】zookeeper及其依赖包,解决日志冲突,还需要剔除日志依赖;

<!-- 引入zookeeper -->
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-framework</artifactId>
   <version>2.12.0</version>
</dependency>
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-recipes</artifactId>
   <version>2.12.0</version>
</dependency>
<dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.14</version>
   <!--排除这个slf4j-log4j12-->
   <exclusions>
       <exclusion>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
       </exclusion>
   </exclusions>
</dependency>

2、在springboot配置文件中配置dubbo相关属性!

# 售票服务端口 8081 用户端口 8082
server.port=8081
#当前应用名字
dubbo.application.name=provider-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#扫描指定包下服务
dubbo.scan.base-packages=com.jsxs.service

3、在service的实现类中配置服务注解,发布服务!注意导包问题,因为这里的Service注解需要导入的是dubbo中的注解,而不是spring的注解,所以要把其注入就要用Componet,不过最新版本的好像已经解决这个问题:一个新的注解@DubboService
在这里插入图片描述

package com.jsxs.service;

import org.apache.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;

@Service       //将服务发布出去  org.apache.dubbo.config.annotation.Service
@Component   //放在容器中
public class TicketServiceImpl implements TicketService{

    @Override
    public String getTicket() {
        return "JSXS";
    }
}


逻辑理解 :应用启动起来,dubbo就会扫描指定的包下带有@component注解的服务,将它发布在指定的注册中心中!

开启服务在这里插入图片描述>
链接服务
在这里插入图片描述

开启视图在这里插入图片描述

查看视图在这里插入图片描述

查看数据在这里插入图片描述

(3).服务消费者

1.导入依赖,和之前的依赖一样;

<!--dubbo-->
<!-- Dubbo Spring Boot Starter -->
<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>2.7.3</version>
</dependency>
<!--zookeeper-->
<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency>
   <groupId>com.github.sgroschupf</groupId>
   <artifactId>zkclient</artifactId>
   <version>0.1</version>
</dependency>
<!-- 引入zookeeper -->
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-framework</artifactId>
   <version>2.12.0</version>
</dependency>
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-recipes</artifactId>
   <version>2.12.0</version>
</dependency>
<dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.14</version>
   <!--排除这个slf4j-log4j12-->
   <exclusions>
       <exclusion>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
       </exclusion>
   </exclusions>
</dependency>

2.配置参数

# 售票服务端口 8081 用户端口 8082
server.port=8082

#  消费者去哪里拿?

#当前应用名字
dubbo.application.name=consumer-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

3.本来正常步骤是需要将服务提供者的接口打包,然后用pom文件导入,我们这里使用简单的方式,直接将服务的接口拿过来,路径必须保证正确,即和服务提供者相同;
在这里插入图片描述

4.完善消费者的服务类

package com.jsxs.service;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;


@Service //注入到容器中 springframework.stereotype.Service;
public class UserService {
    // 想获取provider-server提供的票,要去注册中心拿

    @Reference //远程引用指定的服务,他会按照全类名进行匹配,看谁给注册中心注册了这个全类名
    TicketService ticketService;

    public void buyTicket() {
        String ticket = ticketService.getTicket();
        System.out.println("在注册中心买到" + ticket);
    }

}

5.测试类编写

package com.jsxs;

import com.jsxs.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
class ConsumerServerApplicationTests {
    @Resource
    UserService userService;
    @Test
    void contextLoads() {
        userService.buyTicket();
    }

}

在这里插入图片描述
微服务架构问题:

分布式架构会遇到的四个核心问题:

1.这么多的服务,客户端该如何去访问?
2.这么多的服务,服务器之间如何进行通信?
3.这么多的服务,该如何管理和治理?
4.服务挂了,怎么办?

解决方案:

SpringCloud,是一套生态,就是来解决以上分布式架构的四个问题

想使用SpringCloud,必须要掌握Springboot,因为它是基于SpirngBoot的

1.SpringCloud NetFlix,出了一套解决方案

2.Apcahe Dubbo zookeeper 第二套解决方案

API:没有,要么找第三方,要么自己实现

Dubbo是一个高性能的基于java实现的RPC通信框架

服务注册与发现,zookeeper,没有熔断机制,接住了Hystrix

3.SpringCloud Alibaba 一站式解决方案!

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

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

相关文章

详细聊聊spring核心思想

犹记我当年初学 Spring 时&#xff0c;还需写一个个 XML 文件&#xff0c;当时心里不知所以然&#xff0c;跟着网上的步骤一个一个配置下来&#xff0c;配错一个看着 error 懵半天&#xff0c;不知所谓地瞎改到最后能跑就行&#xff0c;暗自感叹 tmd 这玩意真复杂。 到后来用上…

最短路之Dijkstra(15张图解)

&#x1f33c;多年后再见你 - 乔洋/周林枫 - 单曲 - 网易云音乐 闲来无事听听歌 Dijkstra可解决“单源最短路径”问题 四种最短路算法 Floyd算法 时间复杂度高&#xff0c;但实现容易&#xff08;5行核心代码&#xff09;&#xff0c;可解决负权边&#xff0c;适用于数据范围…

凭借这份《2022测试八股文》候选者逆袭面试官,offer拿到手软

《2023测试面试八股文》800 道软件测试面试真题&#xff0c;高清打印版打包带走&#xff0c;横扫软件测试面试高频问题&#xff0c;涵盖测试理论、Linux、MySQL、Web 测试、接口测试、App 测试、Python、Selenium、性能测试、LordRunner、计算机网络、数据结构与算法、逻辑思维…

opencv——傅里叶变换、低通与高通滤波及直方图等操作

1、傅里叶变换a、傅里叶变换原理时域分析&#xff1a;以时间为参照进行分析。频域分析&#xff1a;相当于上帝视角一样&#xff0c;看事物层次更高&#xff0c;时域的运动在频域来看就是静止的。eg&#xff1a;投球——时域分析&#xff1a;第1分钟投了3分&#xff0c;第2分钟投…

“学好英语网”首页制作

“学好英语网”首页制作一、实验名称&#xff1a;二、实验日期&#xff1a;三、实验目的&#xff1a;四、实验内容&#xff1a;五、实验步骤&#xff1a;六、实验结果&#xff1a;七、源程序&#xff1a;八、心得体会&#xff1a;一、实验名称&#xff1a; “学好英语网”首页…

Linux第三讲

目录 三、 磁盘和文件管理和使用检测和维护 3.1 磁盘目录 3.2 安装软件 3.2.1 rpm命令 3.2.2 克隆虚拟机 3.2.3 yum或压缩包方式安装jdk 3.2.4 使用虚拟机运行SpringBoot项目 3.2.5 安装mysql80&#xff08;57&#xff09; 3.2.6 运行web项目 3.2.7 安装tomcat 三、 …

情人节前夕,竞品在小红书平台如何布局营销策略?

情人节作为全球性消费型节日之一&#xff0c;其营销价值不言而喻。以女性用户群体为主导的小红书平台&#xff0c;更是成为该营销节点众多品牌争夺流量的阵地。 那么&#xff0c;情人节前夕竞品在小红书平台布局什么样的营销策略&#xff1f;创作何种内容&#xff0c;如何推广&…

手把手教你用Python做可视化数据,还能调节动画丝滑度

数据可视化动画还在用Excel做&#xff1f; 现在一个简单的Python包就能分分钟搞定&#xff01; 而且生成的动画也足够丝滑&#xff0c;效果是酱紫的&#xff1a; 这是一位专攻Python语言的程序员开发的安装包&#xff0c;名叫Pynimate。 目前可以直接通过PyPI安装使用。 使用…

线程池小结

什么是线程池 线程池其实就是一种多线程处理形式&#xff0c;处理过程中可以将任务添加到队列中&#xff0c;然后在创建线程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学过的实现了Runnable或Callable接口的实例对象; 为什么使用线程池 …

1001. x+y 1002. x+y+z etiger.vip 解析与答案

目录 1001题 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例#1: 输出样例#1: 头文件和数组等初始定义 第一个函数——converts 第二个函数——add 第三个函数——print 主函数部分 完整代码 1002题 题目描述 输入输出格式 输入格式 输出格…

Vue3快速入门【一】

Vue3快速入门一、Vue脚手架1.1、Vite简介1.2、创建项目二、更换Vue模板支持工具三、项目相关命令解析四、生命周期钩子函数五、ref方法的几种使用方式5.1、ref方法(操作基本类型数据)5.2、ref方法(操作复杂类型数据)5.3、ref方法获取标签六、reacttive方法和toRefs方法七、setu…

开发人员 ONLYOFFICE 文档 v7.3:API 与文档生成器更新

随着版本 7.3 新功能的发布&#xff0c;我们也对编辑器、插件以及文档生成器的 API 进行了更新。在下方了解更多详情。 增强的 WOPI 支持 从现在开始&#xff0c;您可在 WOPI 集成中使用二进制格式&#xff0c;如 doc、ppt 以及 xls。我们现已实现了相应方案&#xff0c;其中包…

ClickHouse 合并树表引擎 MergeTree 索引与数据存储方式

目录 1. 一级索引 1.1 稀疏索引 1.2 索引粒度 1.3 索引数据的生成规则 1.4 索引的查询过程 2. 二级索引 2.1 granularity 与 index_granularity 2.2 跳数索引的生成规则

阿里6面,成功唬住面试官拿了27K,软件测试面试也没有传说中那么难吧....

阿里的面试挺独特&#xff0c;每轮面试都没有 HR 约时间&#xff0c;一般是晚上 8 点左右面试官来一个电话&#xff0c;问是否能面试&#xff0c;能的话开始面&#xff0c;不能就约一个其它时间。 全程 6 面&#xff0c;前五面技术面&#xff0c;电话面试&#xff0c;最后一面…

KEITHLEY吉时利2410数字源表

产品概览 Keithley 2410 高压源表专为需要紧密耦合源和测量的测试应用而设计。Keithly 2410 提供精密电压和电流源以及测量功能。它既是高度稳定的直流电源&#xff0c;又是真正的仪器级 5-1/2 数字万用表。电源特性包括低噪声、精度和回读。万用表功能包括高重复性和低噪声。…

《真象还原》读书笔记——第三章 完善MBR(3.5 硬盘)

3.5 硬盘介绍 3.5.2 硬盘工作原理 柱面-磁头-扇区 磁道的编号从0 开始&#xff0c;相同编号的此道组成的管状区域就是柱面。 盘面和磁头一一对应&#xff0c;所以用磁头号表示盘面&#xff0c;磁头编号从上到下从0开始。 扇区编号与盘面和磁道不同&#xff0c;各磁道内的扇区都…

选择万德L2接口需要遵循什么原则?

万德L2接口是一种可以让程序拥有查询股票相关数据的应用查询编程接口&#xff0c;通过这个数据接口&#xff0c;可以直接调用相应的数据&#xff0c;而不用进行额外的编程工作&#xff0c;甚至不需要理解其中的工作机制&#xff0c;是十分方便快捷的一种数据接口。 但是市场上…

操作系统基础---多线程

文章目录操作系统基础---多线程1.为何引入线程程序并发的时空开销线程的设计思路线程的状态和线程控制块TCB2.线程与进程的比较3.线程的实现⭐1.内核支持线程KST2.用户级线程3.组合方式操作系统基础—多线程 1.为何引入线程 利用传统的进程概念和设计方法已经难以设计出适合于…

方向导数与梯度下降

文章目录方向角与方向余弦方向角方向余弦方向导数定义性质梯度下降梯度下降法&#xff08;Gradient descent&#xff09;是一个一阶最优化算法&#xff0c;通常也称为最速下降法。 要使用梯度下降法找到一个函数的局部极小值&#xff0c;必须向函数上当前点对应梯度&#xff08…

学习数据库第一天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、数据库的开启和关闭二、数据库的登录 添加数据库以及表1.登录数据库2.查看数据库三 数据表前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#x…