文章目录
- 什么是微服务
- 服务注册中心(Service)
- 消费者服务调用(负载均衡+服务注册中心)
- 服务--降级&熔断&限流
- 服务网关Gateway
- 服务配置Config +服务总线Bus (Nacos取代)
- SpringCloud Alibaba
什么是微服务
相当于是Springboot开发的一个一个的功能模块间相互协调与配合
每个微服务模块既可以作为服务调用者也可以作为被调用者(利用http实现相互的调用)
我打算学习:Eureka(server注册中心+集群) , Ribbon /Openfeign (client端服务调用+负载均衡), Hystrix(服务熔断降级限流)、zuul/gateway , nacos(要听=config(选听)+bus(选听) )+sentienl(服务降级)
大厂的微服务架构例子
京东的微服务架构
新建工程搭建环境
dependencyManagement和 properties的妙用,用来统一管理子类以来版本
<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.18.10</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.27</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>2.1.1</mybatis.spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>4.0.0</version>
<type>maven-plugin</type>
</dependency>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 阿里巴巴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Restcontroller和controller的区别
controller层返回的是魔板引擎还是返回json字符串!!!
分布式与集群的区别
不同的服务分布在不同的服务器上属于分布式部署,同一个服务使用了多台的服务器属于集群部署
RPC 与REST的区别
*支付模块构建(Payment和order两个模块)
两个微服务间的服务调用(使用RestTemplate基于http的调用)
对于80端口的Order消费者,调用8001端口的Payment模块的服务,实现利用基于http的两个微服务模块间的远程调用
相当于使用80端口的Order消费者模块的controller层业务调用,进而利用restTemplate实现对8001端口的Payment模块的controller层服务调用,进而8001端口的controller层调用service层以及dao层以及数据库的增删改查
项目重构(构建公共包的依赖)
踩坑:注意新建maven项目的时候改groupid,不要使用默认的org.example(防止出错)
注意:groupid+atifactid(tomcat打包名称)确定一个maven依赖
服务注册中心(Service)
实际相当于是为了将多台服务器(被调用的微服务模块)注册在服务中心,方便调用服务方(客户端的微服务模块)的负载均衡以及防止单点故障的问题。
Eureka技术
基础核心思想
服务注册中心单机版部署
eureka报错的添加这个依赖
启动成功了
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.15</version>
</dependency>
8001端口和80端口的注册pom也要加上这个依赖,应该是版本问题,导致都需要这个包的支撑
注册成功了(register的true和false可以自动开关)
服务注册中心多机版部署(集群)
c盘:windows/system32/drivers/etc/hosts目录下添加主机键值对
按照7001,7002,8001,80按顺序启动
微服务的集群部署
支付服务8001和8002两个
注意order端需要进行开启负载均衡的注解以及不要限定死payment服务的端口号
消费者order使用的服务器不同
actuator健康检查
服务发现Discovery(查询本服务的信息)
@GetMapping(value = "/payment/discovery")
public Object discovery() {
List<String> services = discoveryClient.getServices();
for (String service : services) {
log.info("*****element"+service);
}
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
}
return this.discoveryClient;
}
Eureka的自我保护
关闭自我保护机制(默认是开启的)
消费者服务调用(负载均衡+服务注册中心)
Ribbon技术(client)
Ribbon+Eureka(将多台服务器注册在其中)+restTemplate调用服务端模块的相应的url的controller层的服务
注意新版本的Eureka自带了ribbon的 依赖
Ribbon自带的均衡策略切换(IRule接口)
默认是轮询策略,否则需要自己制定
注意:切换默认的负载均衡的规则的类不要被ComponentScan扫描到,所以不要和主启动类在同一个包下面
自定义随机的负载均衡后,不再是8001和8002之间交替了
RoundRobin负载均衡策略的源码(自旋锁CAS+原子操作类)
OpenFeign技术(Client端)
Openfeign的服务调用(轮询调度的负载均衡)
OpenFeign+Eureka+直接使用service层绑定的服务端模块的端口号名字以及相应的url访问路径
service层
controller层调用service层
Openfeign的超时控制
在8001端口写一个超时的业务,发现实现了,在访问的时候会转圈圈才能加载出来
Openfeign客户端默认等待1秒,对于3秒会报超时错误
设置Openfeign端更长的超时等待时间,5秒时又可以跑通了
OpenFeign的日志增强
编写配置类,配置详细日志
每次调用service接口的方法就会在后台打印日志
服务–降级&熔断&限流
Hystrix技术(鼻祖–理念思想)
Hystrix的作用
Jmeter压测学习
相当于20000的并发量
感觉电脑要坏了!!!
解决方案
案例技术栈:Eureka(8001端口服务器端注册)+Openfeign(80端口)+Hystrix
服务降级
8001服务端自身找问题(HystrixCommand+fallback方法)
系统繁忙来了:针对超时情况
系统运行报错:针对业务代码错误
80客户端找问题(HystrixCommand+fallback方法)
服务端超时3秒,客户端的上限为1.5秒
自身业务逻辑出错:自己兜底的fallback方法
全局的defaultfallback方法(减少冗余)
解决服务器端不宕机的情况下,各种业务逻辑问题+超时问题
针对业务逻辑出错的方法
通配的Feignfallback (针对服务端宕机)
解决服务器端不宕机的情况下,客户端与服务器端的业务逻辑处理代码的解耦(不是在controller层写fallback方法)
解决服务器端突然宕机的情况
8001没有宕机的情况下,正常的访问了
8001宕机的情况下。80客户端的通配fallback方法
服务熔断
注意:熔断后慢慢的恢复调用链路
度过窗口期的半熔断状态,是能否关闭熔断机制的关键节点(如果请求成功就会关闭,如果请求失败就会再经历一个窗口期等待下一个的半熔断的状态的到来)!!!
参数是正数,就正常运行
参数是负数,抛出异常调用兜底的fallback()方法
连续在10秒内点击多次的负数请求,之后立刻输入正数的请求,发现断路器还没关闭,仍然执行的是fallback方法。只有在“ 度过窗口期10秒之后(处于半熔断状态,让一个请求进行转发,一旦成功就会完全关闭熔断,失败还是处于熔断状态并重新倒计时窗口期)”,让一个正数请求进行转发,成功请求,关闭熔断
服务限流(Nocaos待学)
服务网关Gateway
主要是对多个微服务进行统一的安全管理(没有什么是加一层解决不了的)
网关的原理及基本的概念
服务网关的作用及概念
GateWay的三大核心概念:
网关路由的两种配置方式
yml配置文件中配置
避坑(不要导入start-web和actuator的依赖,回合webflux冲突)
网关在8001外面套了一层,相当于做了一层与8001的映射路径关系
添加网关前:
添加网关后:
代码注入RouteLocator的Bean(了解)
Gateway配置动态路由
通过微服务名实现动态路由
通过网关包装后,仍然可以负载均衡
Predicate断言的作用(类似“前端的过滤器”)
限定网站访问的允许时间
如果没到时间访问就会报错
限定cookie的名称
限定请求头的格式
Gateway的filter
自定义Global Filter
类似servlet的request和filter和ModelAndView之间的关系
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("***********come in MyLogGateWayFilter: " + new Date());
// 获取请求参数中的 uname(设置用户名的过滤链)
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if (uname == null) {
log.info("*******用户名为null,非法用户,o(╥﹏╥)o");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
/**
* 加载过滤器顺序,数字越小优先级越高
*
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
请求中需要带上uname的键值对(uname不能为空),才能访问成功
没有uname键值对,直接进不去
RewritePath写法的理解
服务配置Config +服务总线Bus (Nacos取代)
Config +bus实现动态刷新全局配置
SpringCloud Alibaba
1. Nacos服务“注册”与“配置中心”
兼顾了Eureka+config+bus
1.1 安装1.1.4版本的nacos
1.2 服务注册中心
服务注册与负载均衡(集成了Ribbon)
为什么能负载均衡,因为jar包的以来已经整合了Ribbon
启动客户端83+服务端9001和9002
客户端的轮询调度:别忘了配置支持负载均衡的注解配置类
Nacos支持AP和CP两种模式的切换
1.2 服务配置中心
动态配置刷新
nacos内置的配置管理取代原来的git
注意:yml写成yaml,相当于把yaml注册到nacos中
此时在nacos配置中心修改版本号为2,并进行刷新访问的url(不用启动服务器即可实现动态刷新)
分类管理(Namespace+Group+Data ID):多种配置环境的定位
Data ID方案环境区分
配置多个次测试环境的yaml,方便进行环境切换的时候,读取到相应的配置文件(方便切换和修改)
切换测试环境,从dev至test测试环境
Group方案环境区分
两者的Data ID相同,但是Group不同
如何实现使用不同分组的配置信息(相当于:group+dataID进行定位配置文件)
切换两个分组
Namespace方案环境区分
新建命名空间,会产生一个命名空间id
在新建的namespace创建不同的配置文件
此时按照Namespace+GROUP+data id来实现定位配置文件版本
1.3 Nacos的集群和持久化(Linux+nginx+nacos+Mysql)–太难了
nacos默认存储数据方式是嵌入式数据库,可以使用集中式数据库mysql来实现持久化存数据
使用mysql来保持数据的持久化+集群间的数据一致性问题
2. Sentinel实现熔断与限流
2.1 下载安装sentinel 1.7.0
密码和用户名都是sentinel
2.2 初始化监控台
必须先访问一条业务,监控台才能能检测到
2.3 流控规则概述
1 快速失败
1. 设置单机流控规则
狂点刷新,就会出现sentinel的线路操作提示
2. 设置关联的流控模式
postman线程模拟迭代快速运行testB
运行期间访问testA,发现被连坐不能运行
2 预热
防止一开始缓存还没成型,被击穿
3 排队等待
连续单机请求会发现在请求在转圈,因为在排队等待.每秒只能处理一个请求,其余快速的点击的请求仍然需要排队等待处理
2.4 服务降级规则
注意:sentinel没有半熔断的状态(区别于Hystrix)
1. RT (平均响应时间) 降级规则
jmeter压测一直运行+浏览器访问+发现断路器开启了
2. 异常比例降级规则
3. 异常数降级规则
连续请求5次异常的请求之后就会自动开启服务熔断
2.5 热点规则(@SentinelResource注解兜底方法)
注意,此时的sentinel只管理限流异常时的兜底处理,你的编码的其他异常当然是不会进行兜底的处理!!!!
情况1:设置一个传入参数的热点key的规则
如果违背了热点key的规则,则采用兜底的方法;如果不设置兜底的方法,则直接采用whitelabel error page (最原始的不使用sentinel的原始错误页面)
采用传统的rest风格进行url访问
第0个角标的第一个参数设置点击访问超出了阈值,就会出现服务熔断的情况,就是断路器打开的情况
(由于访问中加上点击的第一个参数的请款个,就会出现降级规则的限制)连续点击多次后出现的情况,会返回自己设置的callback方法进行处理
针对前面设置的降级规则,如果一直持续点击请求第二个参数(即不带上第一个参数的情况),就不会出现报错的情况
情况2:设置热点key的个别取值参数的例外配置
配置例外的参数项,增加p1=5时的例外项,限流的阈值为200毫秒;而其他的参数仍然的阈值为1秒(妙妙妙)
2.6 @SentinelResource注解+兜底方法
下方绿线:资源名称;红线:url 路径
1. 按资源名称限流
注意:如果关闭服务器8401,sentinel监控平台的流控规则就会消失
2. 按照url地址限流
3. 自定义的限流异常的处理逻辑(解耦callback和业务的代码)
2.7 服务熔断
测试环境准备:两个服务提供者+一个消费者(使用nacos的服务注册中心+sentinel的熔断)
1.没有配置
使用nacos的ribbon实现负载均衡:
2.只配置fallback(只处理代码逻辑异常)
2. 只配置blockHandler (只处理流控规则)
按照资源名来降级
超过异常数就会开启兜底的方法
3. 配置fallback && blockHandler
针对4这种有异常的情况,如果没有产生限流的问题,首先处理的是nacos的fallback的兜底方法.
针对4还出现异常超过了限流的次数,此时则会先处理限流的兜底方法,而不是执行fallack()方法.
2.8 sentinel整合ribbon+openfeign+fallback
使用84服务端口来调取9003端口
如果关闭9003,会有相应的兜底方法进行处理
3. Seata的分布式管理事务(待学–挺难的)
针对不同的微服务之间使用不同的数据源进行存储的情况
基本概念