微服务组件高可用架构
2024-03-18 15:53:56 1 举报
AI智能生成
Sentinel 还是 Hystrix
作者其他创作
大纲/内容
Sentinel 还是 Hystrix
共同特性
资源模型
Hystrix
采用了命令模式,将对外部资源的调用和 fallback 逻辑封装成一个命令对象 HystrixCommand 或 HystrixObservableCommand,其底层的执行是基于 RxJava 实现的
每个 Command 创建时都要指定 commandKey 和 groupKey(用于区分资源)以及对应的隔离策略(线程池隔离 or 信号量隔离)
线程池隔离模式下需要配置线程池对应的参数(线程池名称、容量、排队超时等),然后 Command 就会在指定的线程池按照指定的容错策略执行
信号量隔离模式下需要配置最大并发数,执行 Command 时 Hystrix 就会限制其并发调用。
Hystrix 的 Command 强依赖于隔离规则配置的原因是隔离规则会直接影响 Command 的执行
在执行的时候 Hystrix 会解析 Command 的隔离规则来创建 RxJava Scheduler 并在其上调度执行,若是线程池模式则 Scheduler 底层的线程池为配置的线程池,若是信号量模式则简单包装成当前线程执行的 Scheduler。
Sentinel
开发的时候只需要考虑这个方法/代码是否需要保护,置于用什么来保护,可以任何时候动态实时的区修改
支持基于注解的资源定义方式,可以通过注解参数指定异常处理函数和 fallback 函数
除了直接通过 loadRules API 将规则注册到内存态之外,用户还可以注册各种外部数据源来提供动态的规则。用户可以根据系统当前的实时情况去动态地变更规则配置,数据源会将变更推送至 Sentinel 并即时生效。
隔离设计
Hystrix
线程池隔离
针对不同的资源分别创建不同的线程池,不同服务调用都发生在不同的线程池中,在线程池排队、超时等阻塞情况时可以快速失败,并可以提供 fallback 机制。
好处是隔离度比较高,可以针对某个资源的线程池去进行处理而不影响其它资源,但是代价就是线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。
线程池隔离并没有带来非常多的好处
让机器资源碎片化
本身 Tomcat 自身的线程数目就非常多了(可能到几十或一百多),如果加上 Hystrix 为各个资源创建的线程池,总共线程数目会非常多(几百个线程),这样上下文切换会有非常大的损耗
线程池模式比较彻底的隔离性使得 Hystrix 可以针对不同资源线程池的排队、超时情况分别进行处理,但这其实是超时熔断和流量控制要解决的问题,如果组件具备了超时熔断和流量控制的能力,线程池隔离就显得没有那么必要了
Hystrix
设计
调用延迟和调用失败进行控制和容错保护
阻止某一个依赖服务的故障在整个系统中蔓延
fail-fast(快速失败)和快速恢复
fallback 优雅降级
近实时的监控、报警以及运维
细节
阻止任何一个依赖服务耗尽所有的资源
避免请求排队和积压,采用限流和 fail fast
fallback 降级机制
资源隔离技术,比如 bulkhead(舱壁隔离技术)、swimlane(泳道技术)、circuit breaker(断路技术)
近实时的统计/监控/报警
近实时的属性和配置热修改
保护依赖服务调用的所有故障情况
线程池技术实现资源隔离
资源隔离
对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内,不会去用其它资源了
Command
将调用商品服务的操作封装在 HystrixCommand 中,限定一个 key,比如下面的 GetProductInfoCommandGroup,在这里我们可以简单认为这是一个线程池,每次调用商品服务,就只会用该线程池中的资源,不会再去用其它线程资源了。
线程池隔离技术,是用 Hystrix 自己的线程去执行调用
适合绝大多数场景,比如说我们对依赖服务的网络请求的调用和访问、需要对调用的 timeout 进行控制(捕捉 timeout 超时异常)
信号量机制实现资源隔离
服务 A 的信号量大小为 10,那么就是说它同时只允许有 10 个 tomcat 线程来访问服务 A,其它的请求都会被拒绝
Hystrix 的线程池隔离技术,控制的是 tomcat 线程的执行
Hystrix 线程池满后,会确保说,tomcat 的线程不会因为依赖服务的接口调用延迟或故障而被 hang 住,tomcat 其它的线程不会卡死,可以快速返回,然后支撑其它的事情
信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行
适合说你的访问不是对外部依赖的访问,而是对内部的一些比较复杂的业务逻辑的访问,并且系统内部的代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流就可以了,因为不需要去捕获 timeout 类似的问题
商品详情页
小型
页面全量静态化
页面静态化系统,将数据填充进静态模板中,形成静态化页面,推入 Nginx 服务器
取用一个已经静态化好的 html 页面,直接返回回去,不涉及任何的业务逻辑处理
Java 中可以使用 velocity、freemarker、thymeleaf 等等,模板变更的时候,点击按钮或者系统自动化重新进行全量渲染
大型
每次页面模板修改了,都需要将这么多页面全量静态化,每次渲染花个好几天时间,那你整个网站就废掉了
当商品数据发生变更时,会将变更消息压入 MQ 消息队列中
缓存服务从消息队列中消费这条消息时,通过调用数据服务接口,获取变更后的数据,然后将整合好的数据推送至 redis 中
Nginx 本地缓存的数据是有一定的时间期限的,比如说 10 分钟,当数据过期之后,它就会从 redis 获取到最新的缓存数据,并且缓存到自己本地
动态将 Nginx 本地数据渲染到本地 html 模板并返回给用户
0 条评论
下一页