目录
传送门
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
一、概念
1、微服务待解决问题
1.服务很多,客户端怎么去访问;2.这么多服务,如何通信;3.这么多服务如何治理;4.服务挂了怎么办
解决方案:
一、SpringCloud NetFlix 一站式解决方案
1.api网关,zuul组件;2.Fegin,采取HttpClient,Http通信方式,同步阻塞;3.Eureka; 4.熔断机制Hystrix
二、Apache Dubbo Zookeeper 半自动,需要整合别人的
1.API没有,需要找第三方组件或者自己实现;2.Dubbo,采取RPC,异步非阻塞;3.Zookeeper;4.没有,借助Hystrix
Dubbo并不完善,并不想和SpringCloud竞争,只想专一的做RPC框架,PRC做的很牛。
三、SpringCloud Alibaba 一站式解决方案,更简单
2019年10月才孵化第一版本
新概念:服务网格 ServerMesh istio
万变不离其宗:只要解决上面4个问题就行。归其原因是网络不可靠。
SpringCloud和Dubbo的区别:
最大区别是SpringCloud抛弃了RPC,采用的是Http通信方式。虽然没有RPC异步的性能好,但是HTTP更加灵活,服务方和调用方只依赖一纸契约(Http连接),不存在像RPC那种代码级别的强依赖,在现在的微服务环境下显然更适合更灵活。SpringCloud就像品牌机,做了大量的兼容测试,而Dubbo就像组装机,虽然各配件很自由,但是可能因为一个内存条兼容问题就点不亮了,不怎么让人放心,高手除外。SpringCloud能和spring完美融合。更重要的是Dubbo停止更新了5年,在2017.7才重启,并不是每个公司都有技术大牛来改造这个Dubbo。Dubbo原来是阿里巴巴的,后给了Apache
2、基本概念
微服务:提倡将单一的应用程序划分成一组小的服务,每个服务能被独立的部署到生产环境,服务之间采取轻量级的通信机制沟通。微服务只有业务逻辑的代码,不会和Html,css或其他界面混合。(纯后端)每个微服务都有自己的存储能力,可以有自己的数据库,也可以统一用一个。
中台:就是一个架构理念,它是介于前台与后台之间的(这句好像是废话),它是希望将一些可复用的“能力”统一起来,采用共享的方式去建设,用来解决各个业务团队重复开发、数据分散、试错成本高等问题,中台的核心就是**“对能力的共享”、“对能力的复用”**,它应该是公司内部的统一协同平台。 (企业级的能力复用平台)
负载均衡:就是将用户的请求平摊的分配到多个服务上,从而达到系统的高可用。
分布式:一个业务分拆多个子业务,部署在不同的服务器上
集群:同一个业务,分别部署在不同的服务器上
所以分布式的每一个节点,完成的是不同的业务,一个节点挂了,那么这个业务功能就无法访问了,甚至可能会影响到其他业务。而集群是一个比较有组织的架构,正因为有组织性,一个服务节点挂了,其他服务节点可以顶上来,从而保证了服务的健壮性。所以说,集群可以理解为:你中有我,我中有你,手拉手肩并肩,一起保证服务的健壮性。
微服务缺点: 1.服务间通信成本高了 2.数据一致性问题 3.开发人员处理分布式的复杂性 4.运维压力增加 5.性能监控
3、SpringCloud
SpringCloud是一系列框架的有序集合。是分布式系统开发工具包。
缺点:开发人员要处理分布式系统的复杂性;微服务太多维护成本高;分布式系统本身的开发成本高(容错,分布式事务等)对团队挑战大
和Spring Boot的关系
Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具。Spring -> Spring Boot > Spring Cloud 这样的关系。
Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系
Spring Boot专注于快速、方便集成的单个个体微服务,Spring Cloud是关注全局的服务治理框架
Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,可以不基于Spring Boot吗?不可以
4、SpringBoot上加载SpringCloud的流程
1.springCloudEureka01(我自己项目的名称),导入依赖,配置application.yml,主要配置eureka的server方面的配置,将这个微服务配置成Eureka Server注册中心。启动加注解@EnableEurekaServer。访问locathost:7001出现Eureka注册中心的可视化页面,可以监控一些注册进来的微服务。
2.springCloudProvider01(我自己项目的名称),导入依赖,配置application.yml,主要配置eureka的client方面的配置,将这个微服务配置成一个客户端。启动加注解@EnableEurekaClient。
3.如果配置注册中心集群,那么springCloudEureka02(我自己项目的名称)同第1步,然后主要改defaultZone。
4.springCloudConsumer(相当于主要改了这个项目)集成Ribbon消费端负载均衡,导入依赖,配置RestTemplateConfig类,springCloudProvider02和springCloudProvider03配置不同端口和一样的服务名字,默认轮询。
5.springCloudConsumerFeign(我自己项目的名称)集成Feign客户端,导入依赖,配置application.yml(主要复制后改下端口),配置ProviderService接口(主要配置这个),默认轮询。
6.springCloudConsumerFeign绑定Hystrix熔断器,导入依赖,配置application.yml(主要开启熔断),配置自定义熔断处理器。
7.springZuul(我自己项目的名称)集成zuul,导入依赖,配置application.yml。zuul代理统一访问。
8.springConfigServer集成Spring Config的server端,导入依赖,配置application.yml(指定了访问github的url,从GitHub访问配置);springConfigClient集成Spring Config的clent端,导入依赖,配置application.yml(基本的端口配置),增加配置bootstrap.yml(系统级别,高于application.yml,配置springConfigServer,)
5、RestTemplate
提供做种便捷访问远程http服务的方法,简单的Restful服务模板就是RestTemplate
消费者调用提供者的服务,用RestTemplate
二、Eureka
1、概念
在微服务架构中往往会有一个注册中心,每个微服务都会想注册中心去注册自己的地址和端口号,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,
这样当有的微服务需要调用其他服务是,就可以从自己获取到的服务列表中获取实例地址进行调用,Eurek实现了这套服务与发现机制。
Eureka架构本身包含两个组件:Eureka Server和Eureka Client,分别表示服务器端和客户端。Netflix公司发布的eureka1.x版本是开源的,2.x版本开始收费,不过1.x就够用了。Eureka有自我保护机制,当Eureka所在服务器故障后,会保存现有注册实例信息,不会删除,这样会让Eureka集群更健壮,可以设置关闭自我保护机制(不推荐关闭)。
2、CAP理论以及eureka和zookeeper 的区别
-
CAP 理论
在总结两者的区别之前,我们先来看一个 CAP 理论。什么叫 CAP 理论呢?CAP 理论是由 Eric Brewer 教授提出,是分布式系统中的一个重要的概念。具体如下:
C(Consistency):数据一致性。大家都知道,分布式系统中,数据会有副本。由于网络或者机器故障等因素,可能有些副本数据写入正确,有些却写入错误或者失败,这样就导致了数据的不一致了。而满足数据一致性规则,就是保证所有数据都要同步。
A(Availability):可用性。我们需要获取什么数据时,都能够正常的获取到想要的数据(当然,允许可接受范围内的网络延迟),也就是说,要保证任何时候请求数据都能够正常响应。
P(Partition Tolerance):分区容错性。当网络通信发生故障时,集群仍然可用,不会因为某个节点挂了或者存在问题,而影响整个系统的正常运作。
对于分布式系统来说,出现网络分区是不可避免的,因此分区容错性是必须要具备的,也就是说,CAP三者,P是必须的,是个客观存在的事实,不可避免,也无法绕过。最多只能同时实现两点,不可能三者兼顾。P是定死必须的,那么久只有CP和AP了。 -
zookeeper 的 CP 原则
对于 zookeeper 来书,它是 CP 的。也就是说,zookeeper 是保证数据的一致性的,但是这里还需要注意一点是,zookeeper 它不是强一致的,什么意思呢?打个比方,现在客户端 A 提交一个写操作,zookeeper 在过半数节点操作成功之后就可以返回,但此时,客户端 B 的读操作请求的是 A 写曹操尚未同步到的节点,那么读取的就不是 A 最新提交的数据了。
那如何保证强一致性呢?我们可以在读取数据的时候先执行一下 sync 操作,即与 leader 节点先同步一下数据,再去取,这样才能保证数据的强一致性。
但是 zookeeper 也有个缺陷,刚刚提到了 leader 节点,当 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader 选举。问题在于,选举 leader 的时间太长,30 ~ 120s, 且选举期间整个 zookeeper 集群都是不可用的,这就导致在选举期间注册服务瘫痪。
在云部署的环境下,因网络问题使得 zookeeper 集群失去 master 节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。比如双十一当天,那就是灾难性的。 -
eureka 的 AP 原则
大规模网络部署时,失败是在所难免的,因此我们无法回避这个问题。当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接 down 掉不可用。
Eureka 在被设计的时候,就考虑到了这一点,因此在设计时优先保证可用性,这就是 AP 原则。Eureka 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka 的客户端在向某个 Eureka 注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台 Eureka 还在,就能保证注册服务可用(即保证A原则),只不过查到的信息可能不是最新的(不保证B原则)。
正因为应用实例的注册信息在集群的所有节点间并不是强一致的,所以需要客户端能够支持负载均衡以及失败重试。在 Netflix 的生态中,ribbon 可以提供这个功能。
因此, Eureka 可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 zookeeper 那样使整个注册服务瘫痪。
作为服务注册中心,最重要的是要保证可用性,可以接收段时间内数据不一致的情况。个人觉得 Eureka 作为单纯的服务注册中心来说要比 zookeeper 更加“专业”一点。
3、代码
单个Eureka配置,访问需要具体端口
三、Ribbon
1、概念
实现客户端负载均衡的工具,就是一个负载均衡器(Load Balancer)(LB,low比),负载均衡就是将用户的请求平摊分配到多个服务上,从而达到系统的高可用性。Ribbon会根据某种规则(默认轮询,随机,自定义)去连接这些服务;Ribbon集成在服务消费端,消费方从注册中心获得哪些服务可用,然后从这些地址中选择一个合适的来消费服务。Ribbon一般植入到消费方。
(就是http请求封装了一下并支付负载均衡,rsetTemplate,步骤繁琐,被Feign代替了,核心注解@LoadBalance)
个人理解:先看完Feign的个人理解然后看这边,一个意思,都是接口和实现方法分开了,实现方法所在微服务什么都不用配置,接口消费者所在微服务注入restTemplate,这个就相当于UserService接口了,通过自己的api(传生产者服务名称弄成请求地址,传请求实体参数,传返回值Class),api的调用就请求到生产者服务去了,由于这边是普通Controller,所以不会像Feign那样在接口上加注解,Ribbon的注解加到了启动类那边了,加了个@RibbonClient(value=“生产者微服务名称”)。
2、代码
消费者的Controller使用,Eureka整合Ribbon后不用关心具体IP地址和端口了。
正常启动Ribbon默认的轮询策略
自定义Rule
自定义Rule(官网说明了,不能放在正常包下,会被扫描到的,就会走默认配置了,需要单独的新包)
四、Feign
1、概念
是声明式WebService客户端,能让编写的WebService(跨平台跨语言的规范,用于不同语言应用之间的交互)客户端更简洁。Feign 旨在使编写 Java Http 客户端变得更容易。前面在使用 Ribbon + RestTemplate 时,利用 RestTemplate 对 http 请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。SpringCould对Feign进行了封装。Feign也是客户端的负载均衡。
(就是Ribbon改进了一下,底层是Ribbon,不用rsetTemplate,创建接口,接口上加注解,感觉像调用本地方法而不是一个http,核心注解@ FeignClient)
调用微服务的两种方法:
Ribbon:微服务名字
Feign:接口和注解
个人理解:Feign生产者微服务提供具体方法实现,就像单机版的UserServiceImpl类,提供的是真正的方法实现,并且生产者服务不需要配置什么,Feign的消费者微服务,要调用(消费者微服务加个@EnableFeignClients),就需要增加一个UserService接口,一一对应Impl类中的方法,并且在这个接口上加@FeignClient(value=“生产者微服务名字”),这样注入UserService就可以用了。单机版的Service和ServiceImpl在同一个地方,Service接口上面加@Service注解,而Feign就是分开了,一个在消费者服务里面(Service接口),一个在生产者服务里面(ServiceImpl);当然将Service从消费者服务里面放到公共服务更好,这样很多个消费者服务都可以调用了。
2、代码
接口+注解(放到了一个公共的地方,其实直接可以放到消费者服务里面,但是公共地方很多其他微服务也方便调用了)
消费者服务的注解配置
消费者服务的使用
五、Hystrix
1、概念
雪崩效应,多个微服务之间调用,A调用B,B又调用了其他微服务,这个是所谓的扇出,若果扇出的链路上某个微服务的调用响应时间过长或者不可用,那么对A服务的调用就会占用越来越多的系统资源,进而引起系统崩溃就是雪崩效应。Hystrix可以解决雪崩效应。Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里面,许多服务无法避免会调用失败,比如超时,异常等,Hystrix能够保证在一个服务出现问题的情况下,不会导致整体服务的失败,避免级联故障,以提高分布式系统的弹性。所以叫断路器。当某个服务发生故障时,通过Hystrix会向调用方返回一个符合预期的,可以处理的的默认响应(也称备选响应,既fallBack),而不是长时间的等待或者直接返回一个异常信息。这样就能保证服务调用方可以顺利的处理逻辑,而不是那种漫长的等待或者其他故障。这种叫做“服务熔断”,跟熔断保险丝一个道理。Hystrix也是客户端的东西。Hystrix 的Dashbroad为监控。核心注解@HystrixCommand
服务降级:当访问微服务A的数据量爆炸的时候,将访问量特别少的微服务C暂时关闭,等到A服务访问量降低之后,再开启微服务C。
服务熔断和降级的区别:
服务熔断是服务端,某个服务超时或者异常,引起熔断(保险丝);服务降级是客户端,从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端,我们可以准备一个FallbackFactory,返回一个默认值(缺省值),整体的服务水平下降了,但是好歹能用,比直接挂掉强。
2、代码
服务提供者支持熔断
使用Hystrix的备选方法(熔断)
使用Hystrix的降级服务(降级)
关联服务降级
服务调用者需要单独设置开启降级
服务降级的展示结果(正常报错到熔断服务到服务降级,根据配置来定)
监控一
监控二
监控三
六、Zuul
1、概念
Zuul包含了对请求的路由和过滤两个最主要的功能。其中,路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。而过滤功能则是负责对请求的处理过程进行干预,是实现请求效验、服务聚合等功能的基础。zuul和eureka整合,将自己注册到eureka服务治理下,同时从eureka获得其他服务的消息,就可以让以后的访问微服务都通过zuul跳转。
(zuul=代理+路由+过滤,所有访问可以都走zuul地址)
2、代码
配置路由
开启
使用
七、Spring Cloud Config
1、概念
Config Server:服务端,分布式配置中心,是一个独立的微服务应用,为Spring Client客户端提供配置信息。
Config Client:客户端,在启动的时候从配置中心获取加载配置信息。
application.yml 是用户级的资源配置项,bootstrap.yml 是系统级的,优先级更高。
2、代码
Config Server开启服务
Config Server的配置
Config Server的使用(浏览器的访问地址有多种,可以看官方文档)
Config Client的配置
Config Client没有单独注解开启,这边写个Controller将来浏览器请求这个config地址可以拿到信息