当前位置: 首页 > news >正文

spring cloud

一、前言

1.应用分类

1.1单体应用框架

  • 复杂性高:整个项目包含的模块非常多、模块的边界模糊,依赖关系不清晰,代码混乱地堆砌到一起,修改 Bug 或新增功能都可能带来隐含的缺陷;
  • 技术债务:随着时间的推移、人员的变更,会逐渐形成应用程序的技术债务,而且越积越多,Not broken,dont fix(不坏不修),这在软件开发中非常常见,已使用的系统设计或代码难以被修改,因为应用程序中的其它模块可能会以意料之外的方式在使用它;
  • 部署效率低:随着代码的增多,构建和部署的时间也会增多,每次修复 Bug 或新增功能都要重新部署整个应用,全部署的方式耗时长、影响范围大、风险高,这儿使得单体应用上线部署效率很低;
  • 可靠性差:某个应用 Bug,可能会导致整个应用崩溃;
  • 扩展能力受限:单体应用只能作为一个整体扩展,无法根据业务模块的需要进行伸缩,例如:应用中有的模块是计算密集型的,需要强劲的 Cpu,有的模块是 IO 密集型的,需要更大的内存,由于这些模块都部署在一起,不得不在硬件的选择上做妥协;
  • 阻碍技术创新:单体应用往往使用统一的技术平台或方案解决所有问题,团队中的每个人都必须使用相同的语言和技术框架,要想引入新的东西比较困难,例如:一个 Struts2 构建,有 100w 行代码的单体应用,如果想换成 Spring Boot,毫无疑问,切换的成本是非常高的;

1.2分布式服务架构

  • 将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常为 HTTP 资源 Api),这些服务通过全自动部署机制独立部署,共用一个集中式的管理,服务可以使用不同语言开发,使用不同的数据存储技术;
  • 搜索引擎、电商网站、微博、微信、O2O 平台……凡是涉及到大规模用户、高并发访问的,无一不是分布式,“大系统小做”,对于一个大的复杂系统,首先想到的就是对其分拆,拆成多个子系统,每个子系统自己的存储、Service、接口层,各个子系统独立开发、测试、部署、运维;
  • 优点:易于扩展、部署简单、技术异构性、从团队管理角度讲,也可以不同团队用自己熟悉的语言体系,团队之间基于接口进行协作,职责清晰,各司其职;

2、基础理论

2.1分布式和集群

  • 集群是多台计算机完成一样的工作,提高效率和安全性,需要考虑一致性的问题;
  • 分布式是多台计算机协同完成工作,提高效率和扩展性,需要考虑事务的问题;

2.2 一致性

        强一致性、弱一致性、最终一致性;

2.3 ACID:

  • 事务的四大特性,原子性、一致性、隔离性、持久性,MySQL 通过 InnoDB 日志和锁来保证事务的强一致性;

2.4 CAP 理论;

  • 1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标:Consistency(一致性)、Availability(有效性)、Partition tolerance(分区容错性:单个组件不可用,依然能完成操作,分区容错性是分布式系统的根本);
    • 在 G1 和 G2 通讯中,有可能无法成功(断电、出错、网络延迟等),有可能此时 Client 已经发起查询操作;
    • 在同步服务器时候,需要停掉 G2 的读写操作,无法保证有效性;
    • 允许 G2 查询得到未同步之前的数据,无法保证一致性;
  • 两个分支;
  • CP 架构:放弃可用性,追求一致性和分区容错性;
  • AP 架构:放弃强一致,追求分区容错性和可用性,这是很多分布式系统设计时的选择;
  • BASE 理论:BA(Basic Available 基本可用)、S(Soft State 柔性状态,同一数据的不同副本的状态,不需要实时一致)、E(Eventual Consisstency 最终一致性);
  • 酸碱平衡:ACID && BASE 理论平衡,比如交易系统需要强一致性,遵循 ACID,注册成功后发送邮件只需遵循 BASE 理论即可;

3.系统架构

3.1物理相关

  • 负载均衡器;
  • Linux HA:又称“双机热备”,是两台机器装上同样的系统,配好后通过“心跳线”互相监测,数据存放在共享阵列库中,当主服务器出现问题时,从服务器会接管主服务器上的所有服务;
  • 多机房:同城灾备,异地灾备;

3.2 存储

  • 存储分类
    • Nosql:内存数据库(Redis)、文件型数据库(MongoDB);
    • Sql:Mysql、Sql Server、Oracal,会设计到分库分表的几个关键性的问题:切分维度,Join 的处理,分布式事务;
    • 读写分离:对传统的单机 Mysql 数据库,读和写是完全同步的,写进去的内容,立马就可以读到,但在高并发情况下,或者读和写并不需要完全同步的情况,就可以分开存储,采用读写分离;
      • 缓存:缓存大家都不陌生,遇到性能问题,大家首先想到的就是缓存;
      • 重写轻读 VS 重读轻写;
      • 重写轻读:本质就是“空间换时间“,你不是计算起来耗时,延迟高吗,那我可以提前计算,然后存储起来,取的时候,直接去取;
      • 重读轻写:我们通常对 Mysql 的用法,写的时候,简单,查的时候,做复杂的 Join 计算,返回结果,这样做的好处是容易做到数据的强一致性,不会因为字段冗余,造成数据的不一致,但是性能可能就是问题;
  • 冷热分离:比如定期把 Mysql 中的历史数据,同步到 Hive;

3.3 Service

  • 负载均衡;
  • 分布式事务;
  • 并发:通过设计保证系统能够同时并行处理很多请求,垂直扩展(提升单机处理能力)、水平扩展(增加服务器数量,线性扩充系统性能);
  • 同步 VS 异步:因为非实时,我们就可以做异步,比如使用消息队列,比如使用后台的 Job,周期性处理某类任务;
  • Push vs Pull
  • 在所有分布式系统中,都涉及到一个基本问题:节点之间(或者 2 个子系统之间)的状态通知,比如一个节点状态变更了,要通知另外一个节点;
  • Pull: 节点 B 周期性的去询问节点 A 的状态;
  • Push: 节点 A 状态变了, Push 给节点 B;
  • 批量:批量其实也是在线/离线的一种思想,把实时问题,转化为一个批量处理的问题,从而降低对系统吞吐量的压力,比如 Kafka 中的批量发消息,比如广告扣费系统中,把多次点击累积在一起扣费;
  • 限流:现在很多电商都会有秒杀活动,秒杀的一个特点就是商品很少,但短时间内流量暴增,服务器完全处理不了这么多请求,那索性不要放那么多人进去;
  • 服务熔断与降级:服务降级是系统的最后一道保险,就是当某个服务不可用时,干脆就别让其提供服务了,直接返回一个缺省的结果,虽然这个服务不可用,但它不至于让整个主流程瘫痪,这就可以最大限度的保证核心系统可用;
  • 前端
  • 动静分离:动态的页面放在 Web服务器上,静态的资源如 Css/Js/Img,直接放到 CDN(内容分发网络)上,这样既提高性能,也极大的降低服务器压力;
  • 其他
  • 故障监控:系统监控、链路监控、日志监控;
  • 自动预警;

4.数据库分库分表

4.1 数据分片

  • 离散式分片:按照数据的某一字段哈希取模后进行分片存储;
  • 跨库操作需要由数据分库分表中间件来完成,影响数据的查询效率;
    • 当数据存储能力出现瓶颈需要扩容时,离散分片规则需要将所有数据重新进行哈希取模运算,产生数据迁移问题;
  • 连续分片:数据按照时间或连续自增主键连续存储;
  • 大量的读写往往都集中在最新存储的那一部分数据,会导致热点问题;

4.2 数据库扩展

  • 垂直分库:将一个完整的数据库根据业务功能拆分成多个独立的数据库,这些数据库可以运行在不同的服务器上,从而提升数据库整体的数据读写性能;
  • 垂直分表:如果一张表的字段非常多,将一张表中不常用的字段拆分到另一张表中,从而保证第一张表中的字段较少,提升查询效率,而另一张表中的数据通过外键与第一张表进行关联;
  • 水平分表:如果一张表中的记录数过多(超过 1000 万条记录),那么会对数据库的读写性能产生较大的影响,将一张含有很多记录数的表水平切分,拆分成几张结构相同的表,根据某字段进行哈希取模后均匀地存储在切分表中;
  • 水平分库分表:水平数据分片首先将数据表进行水平拆分,然后按照某一分片规则存储在多台数据库服务器上;
  • 跨库操作
    • 跨库 Join 变得非常麻烦,而且基于架构规范,性能,安全性等方面考虑,一般是禁止跨库 Join 的;
    • 在业务系统层面,通过多次 SQL 查询,完成数据的组装和拼接;
    • 中间件:Cobar(分库)、MyCat;

5.分布式事务

  • 目前数据库不支持跨库事务,我们就需要在数据库之上通过某种手段,实现支持跨数据库的事务支持,比如:商品系统、订单系统、支付系统、积分系统、库存系统等,用户下单,2、3、4、5需要在一个事务控制;

5.1 分布式事务协议

  • 2PC:两阶段提交协议
  • 有一个事务管理器的概念,负责协调多个数据库的事务,事务管理器先问各个数据库你准备好了吗?如果每个数据库都回复 OK,那么就正式提交事务,在各个数据库上执行操作,如果任何其中一个数据库回答 NO,那么就回滚事务;
    • PreCommit 阶段
    • 节点:协调者 Coordinator、参与者 Cohorts;
  • 协调者向所有参与者询问是否可以执行提交操作 Vote;
    • 参与者执行询问,Undo 信息和 Redo 信息写入日志;
    • 参与者向协调者发起询问,返回“成功”(事务操作成功)或“中止”(事务操作失败);
  • DoCommit 阶段
    • 协调者获得参与者“同意”时,发出“Commit”请求,参与者完成请求,释放资源,向协调者返回“完成”消息,协调者收到消息后完成事务;
      • 协调者获得参与者“中止”消息时,发出“Rollback”请求,参与者完成请求,释放资源;
      • 缺点
      • 参与者节点事务都是阻塞型的;
        • 协调者发生故障,参与者会一直阻塞;
        • 第二阶段,在协调者发出“Commit”后,协调者和其中的参与者都宕机,没人知道事务是否提交;
  • 3PC:三阶段提交协议
  • 在 2PC 的基础上,引入了协调者和参与者的超时机制,并将 Precommit 阶段分成了两个准备阶段;
  • CanCommit 阶段、PreCommit 阶段、DoCommit 阶段;

5.2 分布式事务模式

  • AT:两阶段型,是一种无侵入的分布式事务解决方案,阿里的 Seata 实现了该模式;
  • TCC:两阶段型、补偿型;
  • Try 阶段:对各个服务的资源做检测以及对资源进行锁定或者预留;
    • 这种方案使用较少,因为事务回滚实际上是严重依赖于你自己写代码来回滚;
    • Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作;
    • Confirm 阶段:在各个服务中执行实际的操作;
  • Saga:两阶段、补偿型;
  • 每个 Saga 由一系列 sub-transaction Ti 组成
    • 和 TCC 相比,Saga 没有“预留”动作,它的 Ti 就是直接提交到库;
    • 每个 Ti 都有对应的补偿动作 Ci,补偿动作用于撤销 Ti 造成的结果;
  • XA:分布式强一致性的解决方案,性能低而使用较少;

二、分布式框架

1.Dubbo + Zookeeper

以bubbo来调用的

dubbo:阿里程序员,自创,一个技术,

zookeeper:注册中心功能

类似于我们的controller调用service,通过RPC去调用远程接口

1.1RPC

  • Remote Procedure Call Protocol,远程过程调用协议,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议;
  • 该协议允许运行于一台计算机的程序调用另一台计算机的程序,通过一个双向的通信连接(Socket 套接字),实现数据的交换;
  • 关键是创建“客户端存根”,存根就像是代理模式中的代理,生成代理后,代理跟远程服务端通信;

2.spring cloud

Netflix

注册中心,负载均衡器,网关,远程调用。

3.spring cloud Alibaba

使用了spring cloud的组件,另外添加了三大组件:

1.Nacos

2.Sentinel

3.Seata

三、分布式架构

  • Provider:生产者,接口提供方;
  • Consumer:消费者,调用接口方;
  • Registry:注册中心,服务注册与发现;
  • Monitor:监控中心,统计服务的调用次数和时间;
  • Container:服务运行容器;
  • ----------------
  • Container 负责启动,加载,运行服务;
  • Provider 在启动时,向 Registry 注册自己提供的服务;
  • Consumer 在启动时,向 Registry 订阅自己所需的服务;
  • Registry 返回 Provider 地址列表给 Consumer,如果有变更,Registry 将基于长连接推送变更数据给 Consumer;
  • Consumer 从 Provider 地址列表中,基于软负载均衡算法,选一台 Provider 进行调用,如果调用失败,再选另一台;
  • Provider 和 Consumer,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到 Monitor;

四、简介

1.特点

  • 官方文档:https://spring.io/projects/spring-cloud;
  • 在 Spring Boot 基础之上构建,用于快速构建分布式系统的通用模式的工具集;
  • 集大成者,Spring Cloud 包含了微服务架构的方方面面;
  • 约定优于配置,基于注解,配置文件少;
  • 轻量级组件、开发简便、灵活;
  • 项目结构复杂,每一个组件或者每一个服务都需要创建一个项目;
  • 部署门槛高,项目部署需要配合 Docker 等容器技术进行集群部署;

2.版本

Maven 中央库搜索 Spring Cloud Dependencies,查看 Spring Cloud 版本;

  • Spring Boot 版本以伦敦地铁站命名,对非英语母语国家开发者并不友好,2020 版本变更了命名规则;

Spring Boot 和 Spring Cloud 版本对应关系;

2020 版本变更

  • Spring Cloud 一直以来把 Netflix OSS 套件作为其官方默认的一站式解决方案,可是 Netflix 公司在 2018 年前后宣布其核心组件 Hystrix、Ribbon、Zuul、Archaius 等均进入维护状态,迫于无奈,Spring Cloud 做了阻断式升级,发布了 2020 版本;

  • Bootstrap 父上下文配置默认不再启动,参见 BootstrapApplicationListener.java,对 BootStrap 做了判断;
  • 全新的配置方式,可以使用 spring.config.import 导入其它组件的配置,如:spring.config.import=configserver:xxx,这么做更具模块化,更符合云原生环境的要求;

3.组件

  • 注册中心:Netflix Eureka;
  • 负载均衡:Netflix Ribbon(2020 版本前)、Spring Cloud Loadbalancer(2020 版本后);
  • 熔断器:Netflix Hystrix(2020 版本前)、Resilience4j(2020 版本后);
  • 声明式服务调用组件:Feign(最初属 Netflix 公司,后来移交给 OpenFeign 组织);
  • 网关:Netflix Zuul(2020 版本前)、Spring Cloud Gateway(2020 版本后);
  • 配置中心:Spring Cloud Config;
  • 事件、消息总线:Spring Cloud Bus;
  • 安全组件:Spring Cloud Security;

五、公共项目搭建

搭建一个spring cloud项目

目标:将之前写的spring boot项目拆解到spring cloud 项目中

一下市搭建分布式项目的步骤:

entity项目问题?

问题1:为什么要创建一个entity项目?

微服务之间涉及到跨模块的beanentity的调用,所以我首先将所有的分布式系统里的bean抽取出来,形成单独的模块,其他微服务以jar包的方式引入

问题2:微服务会不会跨服务调用 bean? 不会

举个栗子

其他模块会不会调用 账户模块 的user 对象? 会

对啊,既然会用到,那么我微服务 B 怎么去调用 微服务 A 里面的 bean?

问题3: 每个微服务就是一个项目? 是的

问题4: 是不是将每个微服务的 bean 抽取出来,形成一个单独的项目,其他微服务只要添加该项目依赖就可以引用到了

问题5: 那以后是不是还要把每一个service之类的都抽出来?
不用啊,我们通过resttemplate调用接口的方式实现微服务接口调用

1、Entity 项目

1.1.简介

在 Spring Cloud 项目中,每个微服务都可能用到的内容,比如 Entity、Util 等,我们将这些内容单独放到一个项目内,成为其余微服务的依赖;

1.2.创建entity

1.创建骨架

创建 Java Maven 项目 java_spring_cloud_entity;

这时骨架就搭建好了,

2.导入依赖

  • Pom 添加依赖
<!-- servlet -->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>4.0.1</version>
</dependency>

<!-- javax.persistence -->
<dependency>
	<groupId>javax.persistence</groupId>
	<artifactId>javax.persistence-api</artifactId>
	<version>2.2</version>
</dependency>

<!-- Jackson -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-core</artifactId>
	<version>${jackson.version}</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>${jackson.version}</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-annotations</artifactId>
	<version>${jackson.version}</version>
</dependency>
<!-- 序列化 LocalDateTime 等时间类 -->
<dependency>
	<groupId>com.fasterxml.jackson.datatype</groupId>
	<artifactId>jackson-datatype-jsr310</artifactId>
	<version>${jackson.version}</version>
</dependency>

<!-- Commons -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-lang3</artifactId>
	<version>3.12.0</version>
</dependency>

 

<jackson.version>2.11.3</jackson.version>

3. 包装:将之前项目各个模块中 Entity 移植到该项目;

1.在基础包下创建与之前项目模块各个相同的包名

2.复制之前的entity过来放在对应的包中

3.复制过来后,需要修改entity中的引用路径

全部修改完后就,没错了,下一步打成jar包

4.打包jar

  • Maven 打包项目,在本地仓库生成 Jar;
  • 命令:mvn clean install -Dmaven.test.skip=true

 

这里会出现问题情况:

这里是你的maven环境变量没有配置,步骤如下:

  • 环境变量
  • MAVEN_HOME:D:\Program Files\apache-maven-3.6.3
  • Path:%MAVEN_HOME%\bin;
  • cmd:mvn --version

d30d56e381a36a83ac96adff4fb36aa2.png

这样直接点确定,就好了,然后去测试,打开cmd

测试结果是正常这样后,就配好了,但是idea还没有感应到,重启idea,然后打开entity项目,重新输入打包命令

5.找到jar包,在target下面

这样就打好了,然后就可以把你的项目上传到远程仓库里面了

2.创建注册中心

2.1Netflix Eureka

简介

  • Spring Cloud 提供了多种注册中心的支持,如:Eureka、Consul、ZooKeeper 等,Netflix Eureka 本身是一个基于 REST 的服务,包含两个组件:Eureka Server 和 Eureka Client;
  • Eureka Server 提供服务注册服务,各个节点启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 的服务注册表将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到;
  • Eureka Server 之间通过复制的方式完成数据的同步,Eureka 还提供了客户端缓存机制,即使所有的 Eureka Server 都挂掉,客户端依然可以利用缓存中的信息消费其他服务的 API;
  • Eureka Client:生产者或消费者;
  • 在应用启动后,Eureka Client 将会向 Eureka Server 发送心跳,默认周期为 30 秒,如果 Eureka Server 在多个心跳周期内(默认 90 秒)没有接收到某个节点的心跳,Eureka Server 将会进入自我保护机制;

3.写微服务,生产者和消费者

4.微服务之间相互调用,resttemplate,openfeign

5.给微服务添加集群,引入负载均衡器组件

6.引入熔断器组件

cap理论:分区容错性

7、引入一个网关,将所有的微服务同一管理

8.写一个配置中心

9.将页面移植到微服务中进行联调

相关文章:

  • 【MySQL】必知必会知识点
  • 复盘模型总结
  • Spring5学习笔记03--Bean的生命周期
  • 在小熊派BearPi-HM_Micro_small开发板上安装HAP
  • 基数排序(学习)
  • hive窗口函数最全总结
  • Vulnhub靶场 ICA: 1
  • Tomcat部署
  • 大数据如何进行测试
  • python基础专栏13-python基础篇-控制结构
  • 3.4 创建共用模块-供其它模块使用
  • 通用Excel表格导出(Map类型数据导出为表格)
  • leetcode刷题 (9.1) 动态规划
  • 【C++】如何理解函数调用中的传值和传址
  • 糖尿病会隐身,这些信号一定要重视
  • ----------
  • [笔记] php常见简单功能及函数
  • crontab执行失败的多种原因
  • Fundebug计费标准解释:事件数是如何定义的?
  • If…else
  • Ruby 2.x 源代码分析:扩展 概述
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • WebSocket使用
  • 浮动相关
  • 来,膜拜下android roadmap,强大的执行力
  • 理清楚Vue的结构
  • 思维导图—你不知道的JavaScript中卷
  • 微信小程序设置上一页数据
  • 我的业余项目总结
  • 我感觉这是史上最牛的防sql注入方法类
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 转载:[译] 内容加速黑科技趣谈
  • Hibernate主键生成策略及选择
  • kubernetes资源对象--ingress
  • UI设计初学者应该如何入门?
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • (接口自动化)Python3操作MySQL数据库
  • (五)关系数据库标准语言SQL
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (转) Android中ViewStub组件使用
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)深入super,看Python如何解决钻石继承难题
  • .NET HttpWebRequest、WebClient、HttpClient
  • .net Stream篇(六)
  • .net6+aspose.words导出word并转pdf
  • .NET导入Excel数据
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET基础篇——反射的奥妙
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • .NET中的十进制浮点类型,徐汇区网站设计
  • [Android Studio] 开发Java 程序
  • [android] 手机卫士黑名单功能(ListView优化)
  • [BIZ] - 1.金融交易系统特点
  • [BZOJ1060][ZJOI2007]时态同步 树形dp
  • [C++] 默认构造函数、参数化构造函数、拷贝构造函数、移动构造函数及其使用案例