微服务设计的特点
- 单一职责——独立开发
- 独立进程——独立部署
- 解耦,测试效率高
- 高可用,可靠性高——服务隔离
- 升级迭代方便——混合技术栈
- 按需伸缩
- 敏捷开发
- 但会带来一定的维护成本
微服务拆分——设计
拆分
- 服务边界划分——无定式,
太粗就走了单体的老路。
如果过细,服务调用的开销就大了,管理难度也指数增长。 - 大原则:当一块业务不依赖或者极少依赖其他服务。有独立的业务语义。为超过2个其他客户端提供数据。就应该被拆分为一个独立的服务模块。
设计
单一职责:只实现自己的业务逻辑。
服务自治:不依赖于其他模块,从开发测试运维等都是独立的。
轻量级通讯:跨语言,跨平台。减少技术钳制。
接口明确原则:让接口尽量做的更通用,更灵活,从而尽量避免其它模块也做调整。
微服务解决方案
- Spring Cloud Alibaba
- Sping Cloud Netfix
- 大厂自研
微服务组件如何选型
- 社区活跃度
- 稳定性
- 功能
- 性能
- 学习成本
常用的注册中心?
- Zookeeper
- Eureka
- Nacos
- Consul
Nacos是什么
是阿里基于SpringBoot技术实现的一个注册中心,本质也是一个Web服务。是CS架构的。
客户端负载均衡&服务端负载均衡的不同
客户端负载均衡是值客户端发出请求,经过DNS后找到Nginx反向代理,负载均衡转发到服务。
服务端负载均衡是值微服务之间的通讯和调用,通过发现中心获取注册表并负载均衡转发到合适的微服务。
Ribbon负载均衡策略
它们都实现了IRule接口
- 轮询
- 权重轮询
- 重试轮询——RetryRule
- 响应速度权重——WeightedResponseTimeRule
- 最优可用,过滤故障的。选择最小并发——BestAvailableRule
- 可用性过滤,过滤掉不可用,和并发连接超过阈值的。线性轮询一个——AvailabilityFilteringRule
- 区域性 可用性能 最优——ZoneAvoidanceRule
常用的服务调用方式有哪些
- RestTemplate——不经过注册中心
- LoadBalancerClient——通过注册中心拉取
- @LoadBalanced+RestTemplate——拦截请求,拉取注册表,负载均衡,访问
- @EnableFeignClients+@FeignClient——拉取注册表,负载均衡,访问
- 消息中间件,RabbitMQ,RocketMQ
@LoadBalanced注解
用来描述RestTemplate对象,为此对象的远程调用进行赋能,对请求过程进行拦截。
配置中心有哪些
- Nacos
- SpringCloudConfig
- Apollo
为什么使用配置中心
储存项目配置信息的一个服务,集中管理,可以动态发布和更新。
客户端如何感知配置中心数据变化?
nacos中:基于长轮询机制从nacos获取配置信息。
Feign自定义异常处理
1.实现FallbackFactory接口,通过泛型指定要异常处理的Feign接口。
2.重写create,返回类型为泛型指定的要异常处理的接口。
3.在Feign接口中,为@FeignClient注解添加属性fallbackFactory=xxx.class
4.yml配置:
feign:
hystrix:
enabled: true #默认值为false
Feign调用过程分析
- 通过@EnableFeignClients注解告诉SpringCloud启动Feign Starter组件。
- Feign Starter会在项目启动过程中注册全局配置,扫描包下@FeignClient注解的接口。并通过JDK代理构建类的对象,并交由Spring管理。
- Feign接口被调用时,底层代理对象会将接口中的请求信息通过编码器创建Request对象。基于此对象进行远程调用。
- Feign客户端请求对象会经Ribbon进行负载均衡,挑选出一个健康实例。
- Feign客户端会携带Request调用远端服务并返回一个响应。
- Feign客户端对象对Response信息进行解析然后返回客户端。
为什么使用Feign
- 调用过程更加友好,简化了消费方对服务方方法的调用。
注册中心的核心对象
- 服务提供方
- 服务消费方
- 注册中心-Registry
Nacos是如何保证高可用的
重试机制
本地缓存
集群
轮询,长轮询,长连接
轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。
优点:后端程序编写比较容易。
缺点:请求中有大半是无用,浪费带宽和服务器资源。
实例:适于小型应用。
长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
实例:WebQQ、Hi网页版、Facebook IM。
长连接:在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。
优点:消息即时到达,不发无用请求;管理起来也相对方便。
缺点:服务器维护一个长连接会增加开销。
实例:Gmail聊天
日志级别
debug,info,warn,error
Nacos中配置管理模型
namespace——>group——>service/data-id
Sentinel是如何限流的
基于Sentinel依赖提供的拦截器
Sentinel流控阈值类型
- QPS:当调用相关url对应的资源时,QPS达到单机阈值时,就会限流。
- 线程数:线程达到单机阈值时,就会限流。
常用限流模式
- 直接
- 关联——保证核心业务
- 链路——红绿灯
链路限流异常自定义处理
- 新建一个BlockHandler类,限流异常的父类为BlockException
- 修改@SentinelResource注解中的blockHandlerClass=xxx.class,blockHandler =“方法名”
Sentinel降级异常自定义处理
- 实现BlockExceptionHandler接口——用于处理BlockException
- 重写handle方法,用response自定义处理
为什么要进行熔断
平均响应速度越来越慢,或者经常出现异常。
这样可能会导致调用链堆积,最终导致系统崩溃。
抛出的异常
降级的异常父类是谁——BlockException
熔断降级后,抛出什么异常——DegradeException
Sentinel中异常处理即可下默认的实现类——DefaultBlockExceptionHandler
熔断降级阈值类型
- 慢调用比例
- 异常比例
- 异常数
热点规则限流(重点)
热点参数限流会统计传入参数中的热点数据,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
其中,Sentinel会利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
热点规则的限流模式只有QPS模式(这才叫热点)。
参数索引为@SentinelResource注解的方法参数下标,0代表第一个参数,1代表第二个参数。
单机阈值以及统计窗口时长表示在此窗口时间超过阈值就限流。
限流后台抛出异常:ParamFlowException
热点参数其实说白了就是特殊的流控,流控设置是针对整个请求的;但是热点参数他可以设置到具体哪个参数,甚至参数针对的值,这样更灵活的进行流控管理。
热点数据的限流规则是怎样的
主要是针对参数进行限流设计
热点限流中特殊参数
热点限流中的某个参数值的阈值设计
Sentinel系统规则
如何理解:
主要目的就是保证服务器正常的运行,不能被某些应用搞崩溃了;而且在保证稳定的前提下,保持系统的最大吞吐量。是对所有链路的控制规则,是一种系统保护策略。
系统规则是一种全局设计规则,其中,
- Load(负载,Linux设备有效)当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
- RT(响应时间):当单台及其上所有入口流量的平均RT达到阈值,触发保护机制
- 线程数:当单台及其上所有入口的流量的并发线程数达到阈值即触发保护机制
- 入口QPS:单台及其上所有入口的流量的QPS达到阈值即触发保护机制
- CPU使用率:当系统的CPU使用率超过阈值即触发保护(0-1)
异常抛出:
SystemBlockException
Sentinel授权规则
黑白名单规则(AuthorityRule)非常简单,主要有以下配置项:
- 资源名:即限流规则的作用对象
- 流控应用:对应的黑名单/白名单中设置的规则值,多个值用逗号隔开.
- 授权类型:白名单,黑名单(不允许访问).
案例实现:
定义请求解析器,sentinel拦截到用户请求后,会根据解析器判断对方是否符合黑白名单规则。
第一步:
- 实现RequestOriginParser接口
- 重写parseOrigin方法。从request中拿取参数origin的值。这个值假如是app1,在限流规则中、流控应用中添加app1即可识别到。
- 这个解析过程根据我们自己的来,可以基于请求头,请求体,中的数据,也可以根据IP进行。
授权规则流程
- 客户端发起一个请求,被Sentinel拦截器进行拦截。
- 拦截器会调用RequestOriginParser(请求解析对象),的解析方法进行解析。(其实就一个回调)
- 基于控制台的黑白名单进行比对。判定是否拦截
Sentinel限流算法
- 计数器
- 令牌桶
- 漏桶
- 滑动窗口算法——sentinel默认
@SentinelResource注解
在链路限流中描述资源节点
Sentinel常用限流效果
- 快速失败
- 预热
- 排队
触发限流后报出什么异常
BloackException的子类
对限流结果的自定义
有默认处理方案
也可以自定义规则,实现BlockExceptionHandler接口
Sentinel限流的基本原理
底层对请求进行拦截,然后通过流控规则限定对资源的访问
常用网关
- Spring Cloud Gateway
优点:
性能强劲:是第一代网关Zuul的1.6倍。
功能强大:内置了很多使用的功能,如转发,监控,限流等。
缺点:
依赖Netty与WebFlux(Spring5.0),学习成本高。
- Zuul
Gateway网关,作用,处理流程。
作用:(为什么使用网关)
- 实现服务的保护和转发
- 统一URL
- 统一身份认证
- 统一的跨域设计
请求处理原理分析:
处理流程:
- 客户端发起请求。
- Gateway Handler Mapping 通过谓词集合predicates,找到匹配的路由。
- 将其发送到 Gateway Web Handler。
- Gateway Web Handler基于路由配置中的过滤器(责任链模式),进一步的处理请求。(比如去掉一个前缀)。
- Filter虚线部分:在请求之前和之后进行拓展。
源码分析如下:
路由(Route) 是 gateway 中最基本的组件之一。
- id:路由标识符,区别与其他路由
- uri:路由指向的目的地URI,即客户端请求最终被转发到的微服务。
- predicate:谓词。判断对了才会返回真,才会执行路由。
- filter:用于修改请求和响应信息。
Gateway的谓词
- Path
- Method 判断请求类型,如:是否是GET
- Before 判断在这个时间之前访问
- Query 判断参数是否匹配,或匹配正则
- Header 判断请求头是否与正则匹配
网关中的过滤器类型
- GlobalFilter:应用到单个路由或一个分组的路由上。
- GatewayFilter——需要手动配置,应用到所有路由上(例如负载均衡过滤器,请求转发过滤器)
路由中的filters参数,即为一种局部过滤:
还有其他的,比如:
添加请求头:- AddRequestHeader=X-Request-Foo, Bar
添加参数和值:- AddRequestParameter=foo, bar
添加前缀路径:- PrefixPath=/mypath
最大请求包的大小:
- name: RequestSize
args:
# 单位为字节
maxSize: 5000000
Gateway网关底层通过谁实现
Netty网络编程框架-ServerSocket
Gateway层面负载均衡
网关可以不通过注册中心直接访问服务。
但是要进行负载均衡,还是要通过注册中心。
更改路由配置:
uri: lb://sac-provider
- 底层基于Ribbon实现
Gateway结合Sentinel限流类型
- 路由ID
- API分组——即对 url API 进行分组
网关层如何记录服务的映射
通过map,并考虑读写锁的应用。
SpringSecyruty认证流程
Oauth2规范
它基于认证和授权定义了一套规则,在这套规则中规定了实现一套认证授权系统需要哪些对象:
- 系统资源(数据)
- 资源拥有者(用户)
- 管理资源的服务器
- 对用户进行认证和授权的服务器
- 客户端系统(负责提交用户身份信息的系统)
oauth2规范中提供了这样的几种策略
- dbcTokenStore(这里是要将token存储到关系型数据库)
- RedisTokenStore(这是要将token存储到redis数据库-key/value)
- JwtTokenStore(这里是将产生的token信息存储客户端,并且token中可以以自包含的形式存储一些用户信息)
oauth2中规定了认证授权的几种模式:
- 密码模式
- 授权码模式
注册中心常见异常
IllegalStateException——非法声明,无法启动服务。要看后面的,检查启动类相关,DataSource相关,服务名相关。
BindException——绑定异常。要看后面的,端口冲突。
ConnectException ——连接异常。看后面的,IP和端口问题。
UnknowHostException——不明的主机。看后面的,检查@LoadBanlanced注解。
UnsatisfiedDependencyException——依赖注入异常。